diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index cb9920bf..1959586e 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -33,7 +33,7 @@ jobs: - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: - hugo-version: '0.80.0' + hugo-version: '0.132.2' extended: true - name: Generate documentation translations diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ea51c9ff..1e3e485f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ pages: image: registry.gitlab.com/pages/hugo/hugo_extended:latest variables: GIT_SUBMODULE_STRATEGY: recursive - GIT_SUBMODULE_PATHS: support/documentation/themes/hugo-theme-learn + GIT_SUBMODULE_PATHS: support/documentation/themes/hugo-theme-relearn script: # gitlab need the generated documentation to be in the /public dir. - hugo -s support/documentation/ --minify -d ../../public/ --baseURL='https://livingston.frama.io/peertube-plugin-livechat/' diff --git a/.gitmodules b/.gitmodules index 5f7f7e4e..91decf4c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,6 +2,6 @@ # # SPDX-License-Identifier: AGPL-3.0-only -[submodule "documentation/themes/hugo-theme-learn"] - path = support/documentation/themes/hugo-theme-learn - url = https://github.com/matcornic/hugo-theme-learn.git +[submodule "support/documentation/themes/hugo-theme-relearn"] + path = support/documentation/themes/hugo-theme-relearn + url = https://github.com/McShelby/hugo-theme-relearn.git diff --git a/.reuse/dep5 b/.reuse/dep5 index 68795aa2..0f4c7451 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -32,3 +32,7 @@ License: AGPL-3.0-only Files: .github/PULL_REQUEST_TEMPLATE.md Copyright: 2024 John Livingston License: AGPL-3.0-only + +Files: prosody-modules/mod_firewall/* +Copyright: Prosody Community Modules +License: MIT diff --git a/CHANGELOG.md b/CHANGELOG.md index 352a3d9f..5e08072f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,42 @@ # Changelog +## 11.0.1 + +### Minor changes and fixes + +* Fix "send message" button that was sending the message twice. + +## 11.0.0 + +### Importante Notes + +With the new [mod_firewall](https://livingston.frama.io/peertube-plugin-livechat/documentation/admin/mod_firewall/) feature, Peertube admins can write firewall rules for the Prosody server. These rules could be used to run arbitrary code on the server. If you are a hosting provider, and you don't want to allow Peertube admins to write such rules, you can disable the online editing by creating a `disable_mod_firewall_editing` file in the plugin directory. Check the documentation for more information. This is opt-out, as Peertube admins can already run arbitrary code just by installing any plugin. + +The concord theme was removed from ConverseJS. If you had it set in the plugin settings, it will fallback to the Peertube theme. + +### New features + +* Updating ConverseJS, to use upstream (v11 WIP). This comes with many improvements and new features. +* #146: copy message button for moderators. +* #137: option to hide moderator name who made actions (kick, ban, message moderation, ...). +* #144: [moderator notes](https://livingston.frama.io/peertube-plugin-livechat/documentation/user/streamers/moderation_notes/). +* #145: action for moderators to find all messages from a given participant. +* #97: option to use and configure [mod_firewall](https://livingston.frama.io/peertube-plugin-livechat/documentation/admin/mod_firewall/) at the server level. + +### Minor changes and fixes + +* #118: improved accessibility. +* Avatar set for anonymous users: new 'none' choice (that will fallback to Converse new colorized avatars). +* New translation: Albanian. +* Translation updates: Crotian, Japanese, traditional Chinese, Arabic, Galician. +* Updated mod_muc_moderation to upstream. +* Fix new task ordering. +* Fix: clicking on the current user nickname in message history was failing to open the profile modal. +* Fix: increase chat height on small screens, try to better detect the device viewport size and orientation. +* Converse theme: removed concord, added cyberpunk. +* Fixed Converse theme settings localization. +* Fix: improved minimum chat width. + ## 10.3.3 ### Minor changes and fixes diff --git a/assets/styles/admin/firewall/_firewall.scss b/assets/styles/admin/firewall/_firewall.scss new file mode 100644 index 00000000..1871a09b --- /dev/null +++ b/assets/styles/admin/firewall/_firewall.scss @@ -0,0 +1,94 @@ +/* + * SPDX-FileCopyrightText: 2024 John Livingston + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/* stylelint-disable custom-property-pattern */ + +@use "sass:color"; +@use "../../variables"; + +.peertube-plugin-livechat-admin-firewall { + h1 { + padding-top: 40px; + + /* See Peertube sub-menu-h1 mixin */ + font-size: 1.3rem; + border-bottom: 2px solid var(--greyBackgroundColor); + padding-bottom: 15px; + } + + textarea[name^="_content_"] { + min-height: 10rem; + } + + input[type="submit"], + input[type="reset"], + button[type="submit"], + button[type="reset"] { + // Peertube rounded-line-height-1-5 mixins + line-height: variables.$button-calc-line-height; + + // Peertube peertube-button mixin + padding: 4px 13px; + border: 0; + font-weight: variables.$font-semibold; + border-radius: 3px !important; + text-align: center; + cursor: pointer; + font-size: variables.$button-font-size; + } + + input[type="submit"], + button[type="submit"] { + // Peertube orange-button mixin + &, + &:active, + &:focus { + color: #fff; + background-color: var(--mainColor); + } + + &:hover { + color: #fff; + background-color: var(--mainHoverColor); + } + + &[disabled], + &.disabled { + cursor: default; + color: #fff; + background-color: var(--inputBorderColor); + } + } + + input[type="reset"], + button[type="reset"] { + // Peertube grey-button mixin + background-color: var(--greyBackgroundColor); + color: var(--greyForegroundColor); + + &:hover, + &:active, + &:focus, + &[disabled], + &.disabled { + color: var(--greyForegroundColor); + background-color: var(--greySecondaryBackgroundColor); + } + + &[disabled], + &.disabled { + cursor: default; + } + } + + .peertube-livechat-admin-firewall-col-name { + width: 25%; + } + + .peertube-livechat-admin-firewall-col-content { + width: 65%; + } +} diff --git a/assets/styles/elements/_spinner.scss b/assets/styles/elements/_spinner.scss index 672bf01c..9fa9e39d 100644 --- a/assets/styles/elements/_spinner.scss +++ b/assets/styles/elements/_spinner.scss @@ -15,9 +15,9 @@ livechat-spinner, height: 48px; margin: 20px; /* stylelint-disable-next-line custom-property-pattern */ - border: 5px solid var(--greyBackgroundColor); + border: 5px solid var(--greyBackgroundColor) !important; // !important is required for it to work in ConverseJS /* stylelint-disable-next-line custom-property-pattern */ - border-bottom-color: var(--mainColor); + border-bottom-color: var(--mainColor) !important; // !important is required for it to work in ConverseJS border-radius: 50%; display: inline-block; box-sizing: border-box; diff --git a/assets/styles/style.scss b/assets/styles/style.scss index 0fd2c1bb..1dbc8f8a 100644 --- a/assets/styles/style.scss +++ b/assets/styles/style.scss @@ -9,4 +9,5 @@ @use "elements/index"; @use "video"; @use "configuration/configuration"; +@use "admin/firewall/firewall"; @use "list-rooms/list-rooms.scss"; diff --git a/assets/styles/video/_container.scss b/assets/styles/video/_container.scss index e9c83592..e3a155b9 100644 --- a/assets/styles/video/_container.scss +++ b/assets/styles/video/_container.scss @@ -18,17 +18,31 @@ /* Note: livechat-viewer-mode-content (the form where anonymous users can choose nickname or log in with external account), can be something like ~180px height (at time of writing). - We must ensure that the 200px limit for converse-muc and converse-root is + We must ensure that the px height limit for converse-muc and converse-root is always higher than livechat-viewer-mode-content max size. + Note: We also must ensure that when the user has choosen its nickname, and there is an + ongoing poll, the user can see the chat when the poll is folded. */ #peertube-plugin-livechat-container converse-root { display: block; border: 1px solid black; - min-height: max(30vh, 200px); // Always at least 200px, and ideally at least 30% of viewport. + min-height: max(30vh, 300px); // Always at least 200px, and ideally at least 30% of viewport. height: 100%; + min-width: min(400px, 25vw); converse-muc { - min-height: max(59vh, 400px); + min-height: max(30vh, 300px); + } + + @media screen and (orientation: portrait) and (max-width: 767px) { + /* On small screen, and when portrait mode, we are giving the chat more vertical space. + It should go under the video. + */ + min-height: max(50vh, 300px); + + converse-muc { + min-height: max(50vh, 300px); + } } } diff --git a/client/@types/global.d.ts b/client/@types/global.d.ts index ecc2d9be..13bbbbfc 100644 --- a/client/@types/global.d.ts +++ b/client/@types/global.d.ts @@ -12,6 +12,7 @@ declare const MUSTACHE_CONFIGURATION_CHANNEL: string // Constants that begins with "LOC_" are loaded by build-client.js, reading the english locale file. // See the online documentation: https://livingston.frama.io/peertube-plugin-livechat/contributing/translate/ declare const LOC_ONLINE_HELP: string +declare const LOC_CHAT: string declare const LOC_OPEN_CHAT: string declare const LOC_OPEN_CHAT_NEW_WINDOW: string declare const LOC_CLOSE_CHAT: string @@ -133,3 +134,13 @@ declare const LOC_POLL_VOTE_OK: string declare const LOC_MODERATION_DELAY: string declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_MODERATION_DELAY_DESC: string +declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_ANONYMIZE_MODERATION_LABEL: string +declare const LOC_LIVECHAT_CONFIGURATION_CHANNEL_ANONYMIZE_MODERATION_DESC: string + +declare const LOC_PROSODY_FIREWALL_CONFIGURATION: string +declare const LOC_PROSODY_FIREWALL_CONFIGURATION_HELP: string +declare const LOC_PROSODY_FIREWALL_DISABLED_WARNING: string +declare const LOC_PROSODY_FIREWALL_FILE_ENABLED: string +declare const LOC_PROSODY_FIREWALL_NAME: string +declare const LOC_PROSODY_FIREWALL_NAME_DESC: string +declare const LOC_PROSODY_FIREWALL_CONTENT: string diff --git a/client/admin-plugin-client-plugin.ts b/client/admin-plugin-client-plugin.ts index 4233e525..7b0f872b 100644 --- a/client/admin-plugin-client-plugin.ts +++ b/client/admin-plugin-client-plugin.ts @@ -270,6 +270,8 @@ function register (clientOptions: RegisterClientOptions): void { return !(options.formValues['chat-all-lives'] === true && options.formValues['chat-per-live-video'] === true) case 'auto-ban-anonymous-ip': return options.formValues['chat-no-anonymous'] !== false + case 'prosody-firewall-configure-button': + return options.formValues['prosody-firewall-enabled'] !== true } if (name?.startsWith('external-auth-')) { diff --git a/client/common-client-plugin.ts b/client/common-client-plugin.ts index e1c23f2b..af7e1d46 100644 --- a/client/common-client-plugin.ts +++ b/client/common-client-plugin.ts @@ -8,6 +8,7 @@ import { registerConfiguration } from './common/configuration/register' import { registerVideoWatch } from './common/videowatch/register' import { registerRoom } from './common/room/register' import { initPtContext } from './common/lib/contexts/peertube' +import { registerAdminFirewall } from './common/admin/firewall/register' import './common/lib/elements' // Import shared elements. async function register (clientOptions: RegisterClientOptions): Promise { @@ -69,7 +70,8 @@ async function register (clientOptions: RegisterClientOptions): Promise { await Promise.all([ registerVideoWatch(), registerRoom(clientOptions), - registerConfiguration(clientOptions) + registerConfiguration(clientOptions), + registerAdminFirewall(clientOptions) ]) } diff --git a/client/common/admin/firewall/elements/admin-firewall.ts b/client/common/admin/firewall/elements/admin-firewall.ts new file mode 100644 index 00000000..aba28c90 --- /dev/null +++ b/client/common/admin/firewall/elements/admin-firewall.ts @@ -0,0 +1,131 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { AdminFirewallConfiguration } from 'shared/lib/types' +import { AdminFirewallService } from '../services/admin-firewall' +import { LivechatElement } from '../../../lib/elements/livechat' +import { ValidationError, ValidationErrorType } from '../../../lib/models/validation' +import { tplAdminFirewall } from '../templates/admin-firewall' +import { TemplateResult, html, nothing } from 'lit' +import { customElement, state } from 'lit/decorators.js' +import { Task } from '@lit/task' + +@customElement('livechat-admin-firewall') +export class AdminFirewallElement extends LivechatElement { + private _adminFirewallService?: AdminFirewallService + + @state() + public firewallConfiguration?: AdminFirewallConfiguration + + @state() + public validationError?: ValidationError + + @state() + public actionDisabled: boolean = false + + private _asyncTaskRender: Task + + constructor () { + super() + this._asyncTaskRender = this._initTask() + } + + protected _initTask (): Task { + return new Task(this, { + task: async () => { + this._adminFirewallService = new AdminFirewallService(this.ptOptions) + this.firewallConfiguration = await this._adminFirewallService.fetchConfiguration() + this.actionDisabled = false // in case of reset + }, + args: () => [] + }) + } + + /** + * Resets the form by reloading data from backend. + */ + public async reset (event?: Event): Promise { + event?.preventDefault() + this.actionDisabled = true + this._asyncTaskRender = this._initTask() + this.requestUpdate() + } + + /** + * Resets the validation errors. + * @param ev the vent + */ + public resetValidation (_ev?: Event): void { + if (this.validationError) { + this.validationError = undefined + this.requestUpdate('_validationError') + } + } + + /** + * Saves the configuration. + * @param event event + */ + public readonly saveConfig = async (event?: Event): Promise => { + event?.preventDefault() + if (!this.firewallConfiguration || !this._adminFirewallService) { + return + } + this.actionDisabled = true + this._adminFirewallService.saveConfiguration(this.firewallConfiguration) + .then((result: AdminFirewallConfiguration) => { + this.validationError = undefined + this.ptTranslate(LOC_SUCCESSFULLY_SAVED).then((msg) => { + this.ptNotifier.info(msg) + }, () => {}) + this.firewallConfiguration = result + this.requestUpdate('firewallConfiguration') + this.requestUpdate('_validationError') + }) + .catch(async (error: Error) => { + this.validationError = undefined + if (error instanceof ValidationError) { + this.validationError = error + } + this.logger.warn(`A validation error occurred in saving configuration. ${error.name}: ${error.message}`) + this.ptNotifier.error( + error.message + ? error.message + : await this.ptTranslate(LOC_ERROR) + ) + this.requestUpdate('_validationError') + }) + .finally(() => { + this.actionDisabled = false + }) + } + + public readonly getInputValidationClass = (propertyName: string): { [key: string]: boolean } => { + const validationErrorTypes: ValidationErrorType[] | undefined = + this.validationError?.properties[`${propertyName}`] + return validationErrorTypes ? (validationErrorTypes.length ? { 'is-invalid': true } : { 'is-valid': true }) : {} + } + + public readonly renderFeedback = (feedbackId: string, + propertyName: string): TemplateResult | typeof nothing => { + const errorMessages: TemplateResult[] = [] + const validationErrorTypes: ValidationErrorType[] | undefined = + this.validationError?.properties[`${propertyName}`] ?? undefined + + // FIXME: this code is duplicated in dymamic table form + if (validationErrorTypes && validationErrorTypes.length !== 0) { + return html`
${errorMessages}
` + } else { + return nothing + } + } + + protected override render = (): unknown => { + return this._asyncTaskRender.render({ + pending: () => html``, + error: () => html``, + complete: () => tplAdminFirewall(this) + }) + } +} diff --git a/client/common/admin/firewall/elements/index.ts b/client/common/admin/firewall/elements/index.ts new file mode 100644 index 00000000..71940db2 --- /dev/null +++ b/client/common/admin/firewall/elements/index.ts @@ -0,0 +1,5 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import './admin-firewall' diff --git a/client/common/admin/firewall/register.ts b/client/common/admin/firewall/register.ts new file mode 100644 index 00000000..a9e63d45 --- /dev/null +++ b/client/common/admin/firewall/register.ts @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { RegisterClientOptions } from '@peertube/peertube-types/client' +import { html, render } from 'lit' +import './elements' // Import all needed elements. + +/** + * Registers stuff related to mod_firewall configuration. + * @param clientOptions Peertube client options + */ +async function registerAdminFirewall (clientOptions: RegisterClientOptions): Promise { + const { registerClientRoute } = clientOptions + + registerClientRoute({ + route: 'livechat/admin/firewall', + onMount: async ({ rootEl }) => { + render(html``, rootEl) + } + }) +} + +export { + registerAdminFirewall +} diff --git a/client/common/admin/firewall/services/admin-firewall.ts b/client/common/admin/firewall/services/admin-firewall.ts new file mode 100644 index 00000000..e4cc908a --- /dev/null +++ b/client/common/admin/firewall/services/admin-firewall.ts @@ -0,0 +1,108 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { RegisterClientOptions } from '@peertube/peertube-types/client' +import type { AdminFirewallConfiguration } from 'shared/lib/types' +import { + maxFirewallFileSize, maxFirewallNameLength, maxFirewallFiles, firewallNameRegexp +} from 'shared/lib/admin-firewall' +import { ValidationError, ValidationErrorType } from '../../../lib/models/validation' +import { getBaseRoute } from '../../../../utils/uri' + +export class AdminFirewallService { + public _registerClientOptions: RegisterClientOptions + + private readonly _headers: any = {} + + constructor (registerClientOptions: RegisterClientOptions) { + this._registerClientOptions = registerClientOptions + + this._headers = this._registerClientOptions.peertubeHelpers.getAuthHeader() ?? {} + this._headers['content-type'] = 'application/json;charset=UTF-8' + } + + async validateConfiguration (adminFirewallConfiguration: AdminFirewallConfiguration): Promise { + const propertiesError: ValidationError['properties'] = {} + + if (adminFirewallConfiguration.files.length > maxFirewallFiles) { + const validationError = new ValidationError( + 'AdminFirewallConfigurationValidationError', + await this._registerClientOptions.peertubeHelpers.translate(LOC_TOO_MANY_ENTRIES), + propertiesError + ) + throw validationError + } + + const seen = new Map() + for (const [i, e] of adminFirewallConfiguration.files.entries()) { + propertiesError[`files.${i}.name`] = [] + if (e.name === '') { + propertiesError[`files.${i}.name`].push(ValidationErrorType.Missing) + } else if (e.name.length > maxFirewallNameLength) { + propertiesError[`files.${i}.name`].push(ValidationErrorType.TooLong) + } else if (!firewallNameRegexp.test(e.name)) { + propertiesError[`files.${i}.name`].push(ValidationErrorType.WrongFormat) + } else if (seen.has(e.name)) { + propertiesError[`files.${i}.name`].push(ValidationErrorType.Duplicate) + } else { + seen.set(e.name, true) + } + + propertiesError[`files.${i}.content`] = [] + if (e.content.length > maxFirewallFileSize) { + propertiesError[`files.${i}.content`].push(ValidationErrorType.TooLong) + } + } + + if (Object.values(propertiesError).find(e => e.length > 0)) { + const validationError = new ValidationError( + 'AdminFirewallConfigurationValidationError', + await this._registerClientOptions.peertubeHelpers.translate(LOC_VALIDATION_ERROR), + propertiesError + ) + throw validationError + } + + return true + } + + async saveConfiguration ( + adminFirewallConfiguration: AdminFirewallConfiguration + ): Promise { + if (!await this.validateConfiguration(adminFirewallConfiguration)) { + throw new Error('Invalid form data') + } + + const response = await fetch( + getBaseRoute(this._registerClientOptions) + '/api/admin/firewall/', + { + method: 'POST', + headers: this._headers, + body: JSON.stringify(adminFirewallConfiguration) + } + ) + + if (!response.ok) { + throw new Error('Failed to save configuration.') + } + + return response.json() + } + + async fetchConfiguration (): Promise { + const response = await fetch( + getBaseRoute(this._registerClientOptions) + '/api/admin/firewall/', + { + method: 'GET', + headers: this._headers + } + ) + + if (!response.ok) { + throw new Error('Can\'t get firewall configuration.') + } + + return response.json() + } +} diff --git a/client/common/admin/firewall/templates/admin-firewall.ts b/client/common/admin/firewall/templates/admin-firewall.ts new file mode 100644 index 00000000..ffa430c9 --- /dev/null +++ b/client/common/admin/firewall/templates/admin-firewall.ts @@ -0,0 +1,88 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { AdminFirewallElement } from '../elements/admin-firewall' +import type { TemplateResult } from 'lit' +import type { DynamicFormHeader, DynamicFormSchema } from '../../../lib/elements/dynamic-table-form' +import { maxFirewallFiles, maxFirewallNameLength, maxFirewallFileSize } from 'shared/lib/admin-firewall' +import { ptTr } from '../../../lib/directives/translation' +import { html } from 'lit' + +export function tplAdminFirewall (el: AdminFirewallElement): TemplateResult { + const tableHeaderList: DynamicFormHeader = { + enabled: { + colName: ptTr(LOC_PROSODY_FIREWALL_FILE_ENABLED) + }, + name: { + colName: ptTr(LOC_PROSODY_FIREWALL_NAME), + description: ptTr(LOC_PROSODY_FIREWALL_NAME_DESC), + headerClassList: ['peertube-livechat-admin-firewall-col-name'] + }, + content: { + colName: ptTr(LOC_PROSODY_FIREWALL_CONTENT), + headerClassList: ['peertube-livechat-admin-firewall-col-content'] + } + } + const tableSchema: DynamicFormSchema = { + enabled: { + inputType: 'checkbox', + default: true + }, + name: { + inputType: 'text', + default: '', + maxlength: maxFirewallNameLength + }, + content: { + inputType: 'textarea', + default: '', + maxlength: maxFirewallFileSize + } + } + + return html` +
+

+ ${ptTr(LOC_PROSODY_FIREWALL_CONFIGURATION)} +

+

+ ${ptTr(LOC_PROSODY_FIREWALL_CONFIGURATION_HELP, true)} + + +

+ ${ + el.firewallConfiguration?.enabled + ? '' + : html`

${ptTr(LOC_PROSODY_FIREWALL_DISABLED_WARNING, true)}

` + } + +
+ { + el.resetValidation(e) + if (el.firewallConfiguration) { + el.firewallConfiguration.files = e.detail + el.requestUpdate('firewallConfiguration') + } + } + } + > + +
+ + +
+
+
` +} diff --git a/client/common/configuration/elements/channel-home.ts b/client/common/configuration/elements/channel-home.ts index 6d70459a..0a861ccc 100644 --- a/client/common/configuration/elements/channel-home.ts +++ b/client/common/configuration/elements/channel-home.ts @@ -50,7 +50,7 @@ export class ChannelHomeElement extends LivechatElement { \n" +avatar_set_option_none: Nichts +livechat_configuration_channel_anonymize_moderation_label: Moderationsaktionen anonymisieren +livechat_configuration_channel_anonymize_moderation_desc: "Moderationsaktionen anonymisieren + Standardwert für neue Räume.\nWenn dies aktiviert ist, werden Moderationsaktionen + anonymisiert, um zu vermeiden, dass bekannt wird, wer Teilnehmer bannt/verweist/....\n" +moderator_notes_create_error: Fehler beim Speichern der Notiz +moderator_note_description: Beschreibung +moderator_note_delete: Notiz löschen +moderator_note_create_for_participant: Eine neue Notiz erstellen +moderator_note_search_for_participant: Notizen suchen +moderator_note_filters: Suchfilter +moderator_note_original_nick: Nickname des Teilnehmers zum Zeitpunkt der Erstellung + der Notiz +moderator_note_create: Eine neue Notiz erstellen +moderator_note_delete_confirm: Sind Sie sicher, dass Sie diese Notiz löschen wollen? +moderator_notes: Moderationsnotizen +message_search: Suche nach Nachrichten +search_occupant_message: Alle Nachrichten suchen +message_search_original_nick: Nickname des Teilnehmers zum Zeitpunkt des Versendens + der Nachricht +prosody_firewall_label: Prosody mod_firewall einschalten +prosody_firewall_description: "Sie können mod_firewall auf Ihrem Prosody-Server aktivieren.\nWeitere + Informationen finden Sie unter in der Dokumentation.\n" +prosody_firewall_configure_button: "mod_firewall konfigurieren\n" +prosody_firewall_configuration: Prosody mod_firewall Konfiguration +prosody_firewall_configuration_help: "Hier können Sie das Modul Prosody mod_firewall konfigurieren.\n + Sie können mehrere Konfigurationsdateien unten erstellen und deren Reihenfolge ändern.\n + Zögern Sie nicht, Ihre Konfigurationen mit der Gemeinschaft zu teilen (z. B. indem + Sie einige Beispiele zu der Plugin-Dokumentation hinzufügen).\n" +prosody_firewall_disabled_warning: "Warnung: mod_firewall ist in den livechat Plugin-Einstellungen + deaktiviert, du musst es aktivieren, wenn du willst, dass diese Konfiguration + beachtet wird.\n" +prosody_firewall_file_enabled: Aktiviert +prosody_firewall_name: Name +prosody_firewall_name_desc: "Darf nur folgende Zeichen enthalten: alphanumerische + Zeichen, Unterstriche und Bindestriche.\nDie Skripte werden in alphabetischer Reihenfolge + geladen.\n" +prosody_firewall_content: Dateiinhalt +chat: Chat diff --git a/languages/en.yml b/languages/en.yml index 22b31a56..505cc906 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -1,3 +1,4 @@ +chat: Chat online_help: "Online help" open_chat: "Open chat" open_chat_new_window: "Open chat in a new window" @@ -182,12 +183,13 @@ avatar_set_option_fenec: "Fenecs (Mobilizon mascot)" avatar_set_option_abstract: Abstract avatar_set_option_legacy: "Legacy Sepia avatars (those included in previous plugin versions)" +avatar_set_option_none: None converse_theme_label: "ConverseJS theme" converse_theme_description: "Please choose the converseJS theme you want to use." converse_theme_option_peertube: "Peertube theme" converse_theme_option_default: "Default ConverseJS theme" -converse_theme_option_concord: "ConverseJS concord theme" +converse_theme_option_cyberpunk: "ConverseJS Cyberpunk theme" autocolors_label: "Automatic color detection" autocolors_description: | @@ -568,18 +570,23 @@ livechat_configuration_channel_terms_desc: | new_poll: Create a new poll poll: Poll poll_title: New poll -poll_instructions: Complete and submit this form to create a new poll. This will end and replace any existing poll. +poll_instructions: Complete and submit this form to create a new poll. This will end + and replace any existing poll. poll_question: Question poll_duration: Poll duration (in minutes) poll_anonymous_results: Anonymous results poll_choice_n: 'Choice {{N}}:' poll_end: 'Poll ends at:' -poll_vote_instructions: "To vote, click on your choice or send a message with an exclamation mark followed by your choice number (Example: !1)." -poll_vote_instructions_xmpp: "Send a message with an exclamation mark followed by your choice number to vote. Example: !1" +poll_vote_instructions: "To vote, click on your choice or send a message with an exclamation + mark followed by your choice number (Example: !1)." +poll_vote_instructions_xmpp: "Send a message with an exclamation mark followed by + your choice number to vote. Example: !1" poll_is_over: This poll is now over. poll_choice_invalid: This choice is not valid. -poll_anonymous_vote_ok: Your vote is taken into account. Votes are anonymous, they will not be shown to other participants. -poll_vote_ok: Your vote has been taking into account, the counters will be updated in a moment. +poll_anonymous_vote_ok: Your vote is taken into account. Votes are anonymous, they + will not be shown to other participants. +poll_vote_ok: Your vote has been taking into account, the counters will be updated + in a moment. moderation_delay: Moderation delay livechat_configuration_channel_moderation_delay_desc: | @@ -588,3 +595,45 @@ livechat_configuration_channel_moderation_delay_desc: |
  • 0: moderation delay disabled
  • Any positive integer: messages will be delayed for X seconds for non-moderator participants, allowing moderators to delete message before any user can read it.
  • + +livechat_configuration_channel_anonymize_moderation_label: "Anonymize moderation actions" +livechat_configuration_channel_anonymize_moderation_desc: | + Anonymize moderation actions default value for new rooms. + When this is enabled, moderation actions will be anonymized, to avoid disclosing who is banning/kicking/… occupants. + +moderator_notes: Moderation notes +moderator_notes_create_error: 'Error when saving the note' +moderator_note_create: 'Create a new note' +moderator_note_description: 'Description' +moderator_note_delete: 'Delete note' +moderator_note_delete_confirm: 'Are you sure you want to delete this note?' +moderator_note_create_for_participant: 'Create a new note' +moderator_note_search_for_participant: 'Search notes' +moderator_note_filters: 'Search filters' +moderator_note_original_nick: 'Nickname of the participant at the time of the note + creation' + +search_occupant_message: 'Search all messages' +message_search: 'Message search' +message_search_original_nick: Nickname of the participant when the message was sent + +prosody_firewall_label: 'Enable Prosody mod_firewall' +prosody_firewall_description: | + You can enable mod_firewall on your Prosody server. + For more information, please check the documentation. +prosody_firewall_configure_button: | + Configure mod_firewall + +prosody_firewall_configuration: Prosody mod_firewall configuration +prosody_firewall_configuration_help: | + Here you can configure Prosody mod_firewall module. + You can create multiple configuration files bellow, and change their order. + Don't hesitate to share your configurations with the community (for example by adding some examples in the plugin documentation). +prosody_firewall_disabled_warning: | + Warning: mod_firewall is disabled in the livechat plugin settings, you have to enable it if you want this configuration to be taken into account. +prosody_firewall_file_enabled: Enabled +prosody_firewall_name: Name +prosody_firewall_name_desc: | + Can only contain: alphanumerical characters, underscores and hyphens. + Scripts will be loaded in alphabetical order. +prosody_firewall_content: File content diff --git a/languages/es.yml b/languages/es.yml index 225dc960..854dd306 100644 --- a/languages/es.yml +++ b/languages/es.yml @@ -103,7 +103,7 @@ no_anonymous_description: "Si se marca, los usuarios anónimos de Peertube no ve el chat.\nFuncionalidad en desarrollo.\nSi la activas, es muy recomendable marcar también \"No publicar información del chat\".\nDe lo contrario, algunas herramientas de terceros podrían intentar abrir el chat , generando comportamientos imprevistos.\n" -converse_theme_option_concord: Tema concord de ConverseJS +converse_theme_option_cyberpunk: Tema cyberpunk de ConverseJS help_builtin_prosody_description: "Este plugin utiliza el servidor XMPP Prosody para manejar salas de chat.
    \nEste plugin viene con una AppImage de Prosody, que se utilizará para ejecutar el servicio.\n" diff --git a/languages/fr.yml b/languages/fr.yml index fc444fe5..a6a4cba3 100644 --- a/languages/fr.yml +++ b/languages/fr.yml @@ -130,7 +130,7 @@ converse_theme_description: "Merci de choisir le thème ConverseJS que vous voul utiliser." converse_theme_option_peertube: "Thème Peertube" converse_theme_option_default: "Thème par défaut de ConverseJS" -converse_theme_option_concord: "Thème concord de ConverseJS" +converse_theme_option_cyberpunk: "Thème cyberpunk de ConverseJS" autocolors_label: "Détection automatique des couleurs" autocolors_description: | @@ -541,7 +541,8 @@ chat_terms_description: "Ces conditions d'utilisation seront affichées à tous utilisateur⋅rices lorsqu'iels rejoindront les salons de discussion.\nLes streameur⋅euses peuvent également configurer des conditions d'utilisation pour leurs canaux, qui seront affichées juste après les conditions de l'instance.\n" -livechat_configuration_channel_terms_label: Conditions d'utilisation tchat de la chaîne +livechat_configuration_channel_terms_label: Conditions d'utilisation du tchat de la + chaîne livechat_configuration_channel_terms_desc: "Vous pouvez configurer un message de \"\ conditions d'utilisation\" qui sera affiché aux utilisateur⋅rices qui rejoignent vos salons de discussion.\n" @@ -573,3 +574,49 @@ livechat_configuration_channel_moderation_delay_desc: "Valeur par défaut du dé non modérateur⋅rices, ce qui permet à ces derniers de supprimer les messages avant qu'un utilisateur⋅rice ne puisse le lire.\n\n" moderation_delay: Délai de modération +avatar_set_option_none: Aucun +livechat_configuration_channel_anonymize_moderation_label: Anonymiser les actions + de modération +livechat_configuration_channel_anonymize_moderation_desc: "Anonymiser les actions + de modération : valeur par défaut pour les nouveaux salons.\nLorsque cette option + est activée, les actions de modération sont rendues anonymes, afin d'éviter de révéler + qui bannit/expulse/... les occupants.\n" +moderator_notes_create_error: Erreur lors de l'enregistrement de la note +moderator_note_description: Description +moderator_note_delete: Supprimer la note +moderator_note_delete_confirm: Êtes-vous sûr de vouloir supprimer cette note ? +moderator_note_search_for_participant: Recherche de notes +moderator_note_filters: Filtres de recherche +moderator_note_original_nick: Pseudonyme du participant⋅e au moment de la création + de la note +moderator_note_create: Créer une nouvelle note +moderator_note_create_for_participant: Créer une nouvelle note +moderator_notes: Notes de modération +message_search: Recherche de messages +search_occupant_message: Rechercher tous les messages +message_search_original_nick: Pseudonyme du participant⋅e au moment de l'envoi du + message +prosody_firewall_configure_button: "Configurer mod_firewall\n" +prosody_firewall_configuration: Configuration de mod_firewall pour Prosody +prosody_firewall_label: Activer mod_firewall pour Prosody +prosody_firewall_description: "Vous pouvez activer mod_firewall sur votre serveur Prosody.\nPour plus d'informations, + veuillez consulter la documentation.\n" +prosody_firewall_configuration_help: "Ici vous pouvez configurer le module Prosody + mod_firewall.\n + Vous pouvez créer plusieurs fichiers de configuration ci-dessous, et changer leur + ordre.\nN'hésitez pas à partager vos configurations avec la communauté (par exemple + en ajoutant des exemples dans la documentation du plugin).\n" +prosody_firewall_disabled_warning: "Attention : mod_firewall est désactivé dans les + paramètres + du plugin livechat , vous devez l'activer si vous voulez que cette configuration + soit prise en compte.\n" +prosody_firewall_file_enabled: Activé +prosody_firewall_name: Nom +prosody_firewall_name_desc: "Ne peut contenir que des caractères alphanumériques, + des traits de soulignement et des traits d'union.\nLes scripts seront chargés par + ordre alphabétique.\n" +prosody_firewall_content: Contenu du fichier +chat: Tchat diff --git a/languages/gl.yml b/languages/gl.yml index 85f14db7..a0cc8949 100644 --- a/languages/gl.yml +++ b/languages/gl.yml @@ -1,31 +1,30 @@ -open_chat_new_window: Abrir chat en nova ventá -open_chat: Abrir chat -share_chat_link: Compartir ligazón ao chat +open_chat_new_window: Abrir charla en nova xanela +open_chat: Abrir charla +share_chat_link: Compartir ligazón á charla transparent_background: Fondo transparente (para integración coa retransmisión, por exemplo con OBS) -use_chat_help: Se o activas, haberá un chat xunto ao vídeo. +use_chat_help: Se o activas, haberá unha charla xunto ao vídeo. read_only: Só lectura show_scrollbarr: Mostrar barra desprazameto copy: Copiar important_note_title:

    Notas importantes

    -important_note_text: "Aquí tes a documentación acerca do complemento:\n\n\ - \ Documentación sobre Peertube Plugin Livechat\n.\n" -chat_title:

    Chat

    +important_note_text: "Aquí tes a documentación sobre o complemento:\n\n Documentación sobre Peertube Plugin Livechat\n.\n" +chat_title:

    Charla

    connect_using_xmpp_help: Podes conectarte á sala usando unha conta XMPP externa, e o teu cliente XMPP favorito. diagnostic: "Antes de pedir axuda, por favor usa a ferramenta de diagnóstico:\nIniciar o diagnóstico\n - (se o botón non abre outra ventá, intenta actualizar a páxina).\n" + (se o botón non abre outra xanela, intenta actualizar a páxina).\n" online_help: Axuda en liña -close_chat: Pechar chat -use_chat: Usar chat +close_chat: Fechar charla +use_chat: Usar charla link_copied: Ligazón copiada error: Erro open: Abrir use_current_theme_color: Usar esquema de cores actual -generate_iframe: Crear un iframe para incrustar o chat nun sitio web -chat_for_live_stream: 'Chat para a emisión en directo:' +generate_iframe: Crear un marco para incrustar a charla nun sitio web +chat_for_live_stream: 'Charla para a emisión en directo:' room_name: Nome da sala room_description: Descrición da sala not_found: Non se atopa diff --git a/languages/hr.yml b/languages/hr.yml index acae6a4d..fb96a32b 100644 --- a/languages/hr.yml +++ b/languages/hr.yml @@ -209,8 +209,8 @@ share_url_description: Postojat će gumb za dijeljenje URL-a chata (može se na koristiti za OBS integraciju). per_live_video_description: Ako je označeno, sva videa uživo imat će potvrdni okvir u svojim svojstvima za aktiviranje web chata. -per_live_video_label: Korisnici mogu aktivirati chat za svoja videa uživo -all_lives_label: Aktiviraj chat za sva videa uživo +per_live_video_label: Korisnici mogu aktivirati chat za svoje prijenose uživo +all_lives_label: Aktiviraj chat za sve prijenose uživo no_anonymous_label: Sakrij chat za anonimne korisnike theming_advanced_description:

    Izgled

    chat_style_description: "Dodatni stilovi koji se dodaju atributu stila iframea.
    \n @@ -234,15 +234,15 @@ external_auth_custom_oidc_description: "Možeš konfigurirati eksternog pružate external_auth_description: "

    Eksterna autentifikacija

    \nZa korisnike koji nemaju Peertube račun možeš aktivirati različite načine autentifikacije pomoću externih pružatelja usluge autentifikacije.\n" -all_lives_description: Ako je označeno, chat će se aktivirati za sva videa uživo. -all_non_lives_description: Ako je označeno, chat će se aktivirati za sva videa koja - nisu uživo. -all_non_lives_label: Aktiviraj chat za sva videa koja nisu uživo -converse_theme_option_concord: ConverseJS concord tema +all_lives_description: Ako je označeno, chat će se aktivirati za sve prijenose uživo. +all_non_lives_description: Ako je označeno, chat će se aktivirati za sve prijenose + koji nisu uživo. +all_non_lives_label: Aktiviraj chat za sve prijenose koji nisu uživo +converse_theme_option_cyberpunk: ConverseJS cyberpunk tema chat_style_label: Atribut stila ifreama za chat prosody_muc_log_by_default_description: "Ako je označeno, sadržaj sobe će se standardno spremati.\nSvaki korisnik koji se pridruži sobi vidjet će što je napisano prije - nego što se pridruži.
    \nArhiviranje sadržaja se uvijek moguće aktivirati/deaktivirati\n + nego što se pridruži.
    \nArhiviranje sadržaja se uvijek može aktivirati/deaktivirati\n za određenu sobu, uređivanjem njezinih svojstava.\n" auto_ban_anonymous_ip_label: Blokiraj IP anonimnog korisnika kada je korisniku zabranjen pristup chat sobi @@ -275,3 +275,72 @@ share_chat_embed: Ugradi token_label: Oznaka auth_description: "

    Autentifikacija

    \n" chat_terms_label: Uvjeti i odredbe +muted_anonymous_message: Samo registrirani korisnici mogu slati poruke. +livechat_configuration_channel_mute_anonymous_label: Isključi zvuk anonimnih korisnika +login_remote_peertube_video_not_found_try_anyway: U nekim slučajevima, video se ipak + može dohvatiti ako se povežeš s eksternom instancom. +livechat_configuration_channel_moderation_delay_desc: "Standardna vrijednost odgode + moderiranja:\n
      \n
    • 0: odgoda moderiranja je deaktivirana
    • \n
    • Bilo + koji pozitivni cijeli broj: poruke će se odgoditi za X sekundi za sudionike koji + nisu moderatori, dopuštajući moderatorima da izbrišu poruku prije nego što je bilo + koji korisnik može pročitati.
    • \n
    \n" +moderation_delay: Odgoda moderiranja +livechat_configuration_channel_forbidden_words_label_desc: Oznaka za ovo pravilo zabranjenih + riječi +livechat_configuration_channel_emojis_desc: "Možeš konfigurirati prilagođene emojije + za svoj kanal.\nOvi emojiji će biti dostupni u alatu za biranje emojija.\nKorisnici + ih također mogu koristiti sa svojim kratkim imenom (na primjer tako da napišu \"\ + :shortname:\").\n" +livechat_emojis_shortname_desc: "Emotikone možeš koristiti u chatu koristeći \":shortname:\"\ + .\nKratko ime može započeti i/ili završiti dvotočkom (:) te koristiti samo alfanumeričke + znakove, podvlake i crtice.\nPreporuča se započeti ih dvotočkom, kako bi korisnici + mogli koristiti automatsko dovršavanje (upisivanjem \":\" i pritiskom tipke tabulatora).\n" +validation_error: Došlo je do greške tijekom provjere valjanosti. +help_builtin_prosody_description: "Ovaj dodatak koristi Prosody XMPP server za upravljanje + sobama za razgovor.
    \nOvaj dodatak dolazi s Prosody AppImage koji će se koristiti + za pokretanje usluge.\n" +livechat_configuration_channel_terms_desc: "Možeš konfigurirati poruku „uvjeti i odredbe” + koja će se prikazati korisnicima koji se pridružuju tvojim chat sobama.\n" +poll_vote_instructions_xmpp: 'Pošalji poruku s uskličnikom i brojem izbora za glasanje. + Primjer: !1' +invalid_value_file_too_big: 'Datoteka je prevelika (maksimalna veličina: %s).' +per_live_video_warning_description: "\n Postavka „Korisnici mogu aktivirati chat za svoje prijenose uživo” je aktivirana.\n\ + \ Postavka je redundanta s postavkom „Aktiviraj chat za sve prijenose uživo”.\n\ + \n" +new_poll: Stvori novu anketu +invalid_value_missing: Ova je vrijednost obavezna. +invalid_value_wrong_type: Neispravna vrsta vrijednost. +invalid_value_wrong_format: Neispravan format vrijednosti. +invalid_value_not_in_range: Vrijednost ne odgovara dopuštenom rasponu. +invalid_value_duplicate: Dupla vrijednost +too_many_entries: Previše unosa +promote: Postani moderator +livechat_emojis_shortname: Kratko ime +action_import_emojis_info: Ako su uvezeni podaci u redu, ne zaboravi spremiti obrazac. +share_chat_peertube_tips: Ova će poveznica otvoriti chat unutar Peertube sučelja. +token_password: Token lozinke +token_date: Datum +token_action_create: Stvori novi token +token_default_label: Token generiran iz web sučelja +token_action_revoke: Opozovi token +token_action_revoke_confirm: Stvarno želiš opozvati ovaj token? +livechat_token_disabled_label: Deaktiviraj tokene za chat uživo +invalid_value_too_long: Vrijednost je predugačka +livechat_configuration_channel_terms_label: Uvjeti i odredbe kanala chata +poll: Anketa +poll_title: Nova anketa +poll_instructions: Ispuni i pošalji ovaj obrazac za izradu nove ankete. Ovo će zamijeniti + sve postojeće ankete. +poll_question: Pitanje +poll_duration: Trajanje ankete (u minutama) +poll_anonymous_results: Anonimni rezultati +poll_choice_n: 'Izbor {{N}}:' +poll_end: 'Anketa završava:' +poll_vote_instructions: 'Za glasanje klikni na svoj izbor ili pošalji poruku s uskličnikom + iza kojeg slijedi broj tvog izbora (Primjer: !1).' +poll_is_over: Ova anketa je sada završena. +poll_choice_invalid: Ovaj izbor nije valjan. +poll_anonymous_vote_ok: Tvoje se glasanje uzima u obzir. Glasanja su anonimna, neće + se prikazati drugim sudionicima. +poll_vote_ok: Tvoje se glasanje uzima u obzir. Brojači će se uskoro aktualizirati. diff --git a/languages/it.yml b/languages/it.yml index 0f386275..dc416b98 100644 --- a/languages/it.yml +++ b/languages/it.yml @@ -120,7 +120,7 @@ converse_theme_label: "Tema ConverseJS" converse_theme_description: "Scegli il tema converseJS che desideri utilizzare." converse_theme_option_peertube: "Tema Peertube" converse_theme_option_default: "Tema predefinito di ConverseJS" -converse_theme_option_concord: "Tema “Concord“ di ConverseJS" +converse_theme_option_cyberpunk: "Tema “cyberpunk“ di ConverseJS" autocolors_label: "Rilevamento automatico dei colori" autocolors_description: | diff --git a/languages/ja.yml b/languages/ja.yml index 8a796c03..ce141fbd 100644 --- a/languages/ja.yml +++ b/languages/ja.yml @@ -7,7 +7,7 @@ share_chat_link: チャットリンクを共有 read_only: 読み取り専用にする show_scrollbarr: スクロールバーを表示する transparent_background: 透過型背景にする (OBSなどを使用したストリーミング連携に最適) -tips_for_streamers: "ストリーマーの方へ: OBSにチャットを追加する場合は、読み取り専用のチャットリンクを生成し、ブラウザソースで読み込んでください。" +tips_for_streamers: "ストリーマーの方へ: OBSなどを使用して動画ストリームにチャットを埋め込む場合は、読み取り専用のチャットリンクを生成し、ブラウザソースで読み込んでください。\n" copy: コピー link_copied: リンクをコピーしました error: エラー @@ -70,7 +70,7 @@ converse_theme_label: ConverseJSのテーマ converse_theme_description: 使用したいconverseJSのテーマを選択してください。 converse_theme_option_peertube: PeerTubeのテーマ converse_theme_option_default: デフォルトのConverseJSテーマ -converse_theme_option_concord: ConverseJS concordテーマ +converse_theme_option_cyberpunk: ConverseJS cyberpunkテーマ autocolors_label: 色を自動検出 chat_style_label: チャットのiframeスタイル属性 chat_style_description: "追加のスタイル設定をiframeスタイルの属性に追加します。
    \n例)height:400px;\n" @@ -230,3 +230,150 @@ external_auth_custom_oidc_description: "チャットへのログインに、外 \ target=\"_blank\">設定ページ\n" external_auth_custom_oidc_button_label_description: このラベルは、OIDCプロバイダーを使用して認証するボタン名としてユーザーに表示されます。 copied: コピーしました +chat_terms_label: 利用規約 +tasks: タスク +task_list_create: '新規タスクリストを作成:' +task_list_name: タスクリスト名 +task_list_create_error: タスクリストを保存中にエラーが発生しました +task_delete_confirm: このタスクを削除してもよろしいですか? +task_delete: タスクを削除 +external_auth_oidc_redirect_uris_info_description: "Callback/Redirect URI:\n\ + 外部アプリケーション上に認証されたリダイレクションURIを設定したい場合は、このURLを追加してください:\n" +external_auth_google_oidc_label: Googleを使用 +login_using_external_account: 外部アカウントを使用してログイン +login_remote_peertube: 'ほかのPeerTubeインスタンスのアカウントを使用してログイン:' +login_remote_peertube_url: あなたのPeerTubeインスタンスURL +login_remote_peertube_url_invalid: 無効なPeerTube URLです。 +login_remote_peertube_no_livechat: このPeerTubeインスタンスには、ライブチャットプラグインがインストールされていません。 +login_remote_peertube_video_not_found_try_anyway_button: PeerTubeインスタンスで動画を開く +livechat_configuration_channel_anonymize_moderation_label: モデレーション操作を匿名か +moderator_notes_create_error: ノートを保存中にエラーが発生しました +moderator_note_create: 新規ノートを作成 +moderator_note_description: 概要 +moderator_note_delete: ノートを削除 +moderator_note_delete_confirm: このノートを削除してもよろしいですか? +moderator_note_create_for_participant: 新規ノートを作成 +moderator_note_filters: フィルタ検索 +moderator_note_original_nick: ノート作成時の参加者のニックネーム +prosody_c2s_interfaces_label: クライアントとサーバー間のネットワークインタフェース +login_remote_peertube_video_not_found: この動画はこのPeerTubeインスタンス上では利用できません。 +avatar_set_option_none: なし +validation_error: 検証中にエラーが発生しました。 +invalid_value_missing: この項目は必須です。 +invalid_value_wrong_type: 誤った形式の値です。 +too_many_entries: エントリーが多すぎます +chatroom_not_accessible: このチャットルームは存在しないか、アクセス権限がありません。 +login_remote_peertube_searching: PeerTubeインスタンス上の動画を検索中... +login_remote_peertube_video_open_failed: 'お使いのブラウザーはリモートインスタンスを開くことがブロックされています。このリンクを手動で開いてください:' +task_list_delete: タスクリストを削除 +task_list_delete_confirm: このタスクリストを削除してもよろしいですか? +task_create: 新規タスクを作成 +task_name: タスク名 +task_list_pick_title: タスクリストを選択してください +livechat_emojis_shortname: 短縮名 +livechat_emojis_shortname_desc: "チャット上で、絵文字を\":shortname:\"で使用できます。\n短縮名は、先頭と末尾にコロン(:)があり、英数字、アンダーバー、ハイフンのみが含まれている必要があります。\n\ + 自動補完(\":\"を入力後、Tabキーを押下)を利用できるようコロンから入力することを強くお勧めします。\n" +livechat_emojis_file: ファイル +promote: モデレーターにする +livechat_emojis_file_desc: "絵文字に使用するファイルです。\n" +action_import: インポート +action_export: エクスポート +action_import_emojis_info: インポートしたデータが問題ない場合、フォームを保存することを忘れないでください。 +action_remove_entry: このエントリーを削除 +action_remove_entry_confirm: このエントリーを削除してもよろしいですか? +loading_error: データの読み込み中にエラーが発生しました。 +share_chat_embed: 埋め込み +share_chat_peertube_tips: このリンクで、PeerTubeインスタンス内でチャットが開きます。 +token_password: パスワードトークン +token_date: 日付 +token_action_create: 新規トークンを作成 +token_action_revoke: トークンを無効化 +token_default_label: Web UIから生成されたトークン +livechat_token_disabled_description: "ユーザーはチャットに接続するための長期的なトークンを生成できます。\nこれらのトークンは、OBSのカスタムブラウザドックなどで使用できます。\n + 詳細は、ドキュメントをご確認ください。\nこの設定にチェックをつけることで、この機能を無効にできます。\n" +muted_anonymous_message: 登録済みユーザーのみがメッセージを送信できます。 +livechat_configuration_channel_mute_anonymous_label: 匿名ユーザーをミュート +livechat_configuration_channel_mute_anonymous_desc: "新規チャットルームのデフォルト値です。\n既存のチャットルームは、ルーム設定フォーム内の機能で変更できます。\n\ + この設定が有効の場合、匿名ユーザーはチャットは閲覧のみ可能で、メッセージの送信はできません。\n" +livechat_configuration_channel_terms_label: チャンネルのチャットルームの利用規約 +livechat_configuration_channel_terms_desc: "ユーザーがチャットルームに参加する際に表示される\"利用規約\"メッセージを設定します。\n" +new_poll: 新規投票を作成 +poll: 投票 +poll_title: 新規投票 +poll_instructions: 投票を作成するには、内容を設定して送信してください。既存の投票は終了し、この投票で置き換えられます。 +poll_question: 質問 +poll_duration: 投票期間 (分) +poll_anonymous_results: 匿名の結果 +poll_choice_n: '選択肢 {{N}}:' +poll_end: '投票は次で終了:' +poll_vote_instructions: '投票するには、選択肢をクリックするか、感嘆符(!)を付与した後に選択肢番号を入力してメッセージを送信してください(例: + !1)。' +poll_vote_instructions_xmpp: '投票するには、感嘆符(!)を付与した後に選択肢番号を入力してメッセージを送信してください。例: !1' +poll_is_over: この投票は終了しました。 +poll_vote_ok: あなたの投票は受け付けられ、まもなくカウンターが更新されます。 +moderation_delay: モデレーションの遅延時間 +livechat_configuration_channel_moderation_delay_desc: "モデレーションの遅延時間のデフォルト値:\n
      \n\ + \
    • 0: モデレーション遅延無効
    • \n
    • 任意の整数値n: モデレーター以外の参加者からのメッセージはn秒後に表示されるようになり、モデレーターはメッセージが他の参加者に読まれる前に削除することができます。
    • \n\ +
    \n" +livechat_configuration_channel_forbidden_words_label_label: ラベル +livechat_configuration_channel_forbidden_words_label_desc: この禁止語規則のラベル +login_remote_peertube_video_not_found_try_anyway: 場合によっては、外部インスタンスに接続できれば動画を取得できることがあります。 +login_external_auth_alert_message: 認証に失敗しました +invalid_value_not_in_range: 値が許可された範囲にありません。 +search_occupant_message: 全てのメッセージを検索 +message_search: メッセージ検索 +chat_terms_description: "この利用規約はチャットルームに参加する際に全てのユーザーに表示されます。\n配信者はこの利用規約に加えて、チャンネル独自の利用規約を設定できます。チャンネル独自の利用規約は全てのユーザー向けの利用規約の右側に表示されます。\n" +invalid_value_too_long: 値が大きすぎます +moderator_notes: モデレーションノート +moderator_note_search_for_participant: ノートを検索 +message_search_original_nick: メッセージ送信時の参加者のニックネーム +prosody_firewall_label: Prosody mod_firewallを有効にする +prosody_firewall_configure_button: "mod_firewallを設定\n" +prosody_firewall_file_enabled: 有効 +prosody_firewall_name: 名前 +prosody_firewall_name_desc: "次の値のみ利用可能: 英数字、アンダーバー、ハイフン。\nスクリプトは、英字順で読み込まれます。\n" +prosody_firewall_content: ファイルコンテンツ +token_label: ラベル +task_description: 概要 +livechat_configuration_channel_emojis_title: チャンネルの絵文字 +invalid_value_file_too_big: 'ファイルサイズが大きすぎます(最大ファイルサイズ: %s)。' +action_add_entry: エントリーを追加 +share_chat_dock: ドック +livechat_token_disabled_label: ライブチャットトークンを無効化 +token_action_revoke_confirm: 子のトークンを無効化してよろしいですか? +auth_description: "

    認証

    \n" +poll_choice_invalid: この選択肢は無効です。 +poll_anonymous_vote_ok: あなたの投票を受け付けました。投票は匿名で行われ、他の参加者には表示されません。 +task_list_pick_message: "タスクリストを選択すると、新しいタスクが作成されます。\nタスクを確認するには、トップメニューからタスクアプリケーションを開いてください。\n\ + 詳細については、ライブチャットプラグインのドキュメントを参照してください。\n" +share_chat_dock_tips: "チャットページを新規ページかつPeerTubeアカウントにログインした状態で開くリンクを生成できます。\n例えばこのリンクをOBSのカスタムブラウザドックに設定し、OBS上から直接チャットを読んだり、反応することができるようになります。\n\ + このリンクは、あなた自身として接続するため、外部には絶対に公開しないでください。\n既に生成した認証トークンのリストを以下から見つけてください。\n新しいトークンを生成したり、既に生成済みのトークンを無効化できます。\n\ + これらのトークンには有効期限はありません。\n" +livechat_configuration_channel_anonymize_moderation_desc: "新しいルームに対するモデレーションアクションの匿名化をデフォルトにします。 + \nこれを有効にすると、誰がユーザーを追放、キックなどのモデレーションアクションを実施したのかを匿名化します。\n" +prosody_firewall_description: "お使いのProsodyサーバーのmod_firewallを有効にできます。\n詳しくは、ドキュメントをご確認ください。\n" +prosody_firewall_configuration: Prosody mod_firewallの設定 +prosody_firewall_configuration_help: "ここでProsody mod_firewallモジュールの設定が可能です。\n複数の設定ファイルを作成し、以下から順番を変更できます。\n\ + 最適な設定が出来たら、コミュニティメンバーと設定を共有してみてください(プラグインドキュメントに掲載させていただくこともあります)。\n" +prosody_firewall_disabled_warning: "警告: mod_firewallは、ライブチャットのプラグイン設定で無効になっており、この設定を反映するには、機能を有効にする必要があります。\n" +task_list_pick_empty: タスクリストが存在しません。新規作成してください +external_auth_facebook_oidc_label: Facebookを使用 +external_auth_facebook_oidc_description: "有効にすると\"Facebookでログイン\"ボタンを追加します。\nFacebook + OAuthアプリケーションの設定が必要です。\n" +external_auth_google_oidc_description: "有効にすると\"Googleでログイン\"ボタンを追加します。\nGoogle OAuthアプリケーションの設定が必要です。\n" +prosody_c2s_interfaces_description: "クライアントとサーバー間接続のためにリッスンするネットワークインターフェイスです。
    \n\ + この設定は、より高度な設定が可能なユーザー向けに提供されています。設定内容を完全に理解できていない場合は変更しないでください。
    \nリッスンするIPのリストをコンマ区切り(スペースは削除されます)で指定してください。
    \n\ + «*»を指定することで全てのIPv4アドレス、«::»を指定することで全てのIPv6アドレスをリッスンします。
    \n例:\n
      \n
    • *, + ::
    • \n
    • *
    • \n
    • 127.0.0.1, ::1
    • \n
    • 127.0.0.1, ::1, 172.18.0.42
    • \n\ +
    \n" +invalid_value_wrong_format: 誤ったフォーマットの値です。 +invalid_value_duplicate: 重複した値です +livechat_configuration_channel_emojis_desc: "チャンネルのカスタム絵文字を設定できます。\nこれらの絵文字は、絵文字ピッカーから利用できます。\n\ + 絵文字は、短縮名でも使用できます。(例えば\":shortname:\")\n" +chat: チャット diff --git a/languages/sq.yml b/languages/sq.yml index e69de29b..acd56b38 100644 --- a/languages/sq.yml +++ b/languages/sq.yml @@ -0,0 +1,248 @@ +muted_anonymous_message: Mesazhe mund të dërgojnë vetëm përdorues të regjistruar. +moderation_delay: Vonesë moderimi +share_url_label: Shfaq butonin “Ndani me të tjerët lidhje fjalosjeje” +no_anonymous_label: Fshihe fjalosjen për përdorues anonimë +theming_advanced_description:

    Aplikim temash

    +login_remote_peertube_url_invalid: URL PeerTube e pavlefshme. +tasks: Punë +task_list_create: 'Krijoni një listë të re punësh:' +task_list_create_error: Gabim teksa ruhej lista e punëve +task_list_delete_confirm: Jeni i sigurt se doni të fshihet kjo listë punësh? +avatar_set_option_abstract: Abstrakte +prosody_s2s_interfaces_label: Ndërfaqe rrjeti shërbyes te shërbyes +per_live_video_label: Përdoruesit mund të aktivizojnë fjalosje për transmetimet e + tyre të drejtpërdrejta +successfully_saved: U ruajtën me sukses +livechat_configuration_channel_quote_delay_label: Dërgoje çdo X minuta +livechat_configuration_title: Formësoni dhoma fjalosjeje të transmetimit tuaj të drejtpërdrejtë +avatar_set_label: Grup avatarësh +prosody_s2s_port_label: Portë Prosody shërbyes te shërbyes +prosody_c2s_label: Aktivizo lidhje klient te shërbyes +livechat_configuration_channel_bot_options_title: Mundësi roboti moderimi +livechat_configuration_channel_forbidden_words_label: Fjalë, ose shprehje të ndaluara +livechat_configuration_channel_forbidden_words_regexp_label: Konsideroji shprehje + të rregullta +livechat_configuration_channel_command_label: Urdhër roboti +prosody_c2s_interfaces_label: Ndërfaqe rrjeti klient te shërbyes +livechat_configuration_channel_command_message_label: Mesazh +task_list_name: Emër liste punësh +promote: Bëhuni moderator +open_chat: Hapni fjalosje +open_chat_new_window: Hap fjalosjen në dritare të re +read_only: Vetëm për lexim +show_scrollbarr: Shfaq rrëshqitës +close_chat: Mbylle fjalosjen +use_chat: Përdorni fjalosjen +use_chat_help: Në u aktivizoftë, në krah të videos do të ketë një fjalosje. +share_chat_link: Ndajeni lidhjen e fjalosjes me të tjerët +copy: Kopjoje +copied: U kopjua +use_current_theme_color: Përdor ngjyra të temës së tanishme +room_name: Emër dhome +room_description: Përshkrim dhome +not_found: S’u gjet +video: Video +important_note_title:

    Shënim të rëndësishme

    +chat_terms_label: Terma & Kushte +channel: Kanal +last_activity: Veprimtaria e fundit +connect_using_xmpp: Lidhu duke përdorur XMPP +connect_using_xmpp_help: Mund të lidheni me dhomën duke përdorur një llogari të jashtme + XMPP dhe klientin tuaj të parapëlqyer XMPP. +list_rooms_label: Paraqit dhoma ekzistuese +list_rooms_description: "Paraqit dhomat\n" +external_auth_description: "

    Mirëfilltësim së jashtmi

    \nPër përdorues që s’kanë + llogari Peertube, mund të aktivizoni mënyra të ndryshme mirëfilltësimi, bazuar në + shërbyes të largët mirëfilltësimesh.\n" +external_auth_custom_oidc_button_label_label: Etiketë për butonin e lidhjes +external_auth_oidc_client_id_label: ID Klienti +external_auth_oidc_client_secret_label: E fshehtë klienti +external_auth_facebook_oidc_label: Përdor Facebook +open_blank_description: Do të ketë një buton për hapje dritareje fjalosjeje në një + dritare të re. +room_type_option_video: Çdo video ka dhomën e vet të fjalosjes +share_url_option_nobody: Mos e shfaq për ndonjë +room_type_option_channel: Dhomat e fjalosjes grupohen sipas kanaleve +share_url_option_everyone: Shfaqe për këdo +videos_list_label: Aktivizo fjalosje për këto video +avatar_set_option_sepia: Sepia (simboli i PeerTube-it) +converse_theme_label: Temë ConverseJS +converse_theme_option_peertube: Temë PeerTube +converse_theme_option_default: Tema Parazgjedhje ConverseJS +system_prosody_label: Përdor Prosody sistemi +disable_websocket_label: Çaktivizo Websocket-in +prosody_peertube_uri_label: URL Peertube për thirrje API +cancel: Anuloje +livechat_configuration_channel_slow_mode_label: Mënyra ngadalë +livechat_configuration_channel_enable_bot_label: Aktivizo robot moderimi +prosody_muc_expiration_description: "Këtu mund të zgjidhni se për sa kohë mbahet lënda + e dhomës së fjalosjes nga shërbyesi. Vlera mund të jetë:\n
      \n
    • 60: + lënda do të ruhet për 60 sekonda. 60-n mund ta zëvendësoni me çfarëdo vlere + numër të plotë.
    • \n
    • 1d: lënda do të ruhet për 1 ditë. 1-shin + mund ta zëvendësoni me çfarëdo vlere numër të plotë.
    • \n
    • 1w: lënda + do të ruhet për 1 javë. 1-shin mund ta zëvendësoni me çfarëdo vlere numër + të plotë.
    • \n
    • 1m: lënda do të ruhet për 1 muaj. 1-shin mund + ta zëvendësoni me çfarëdo vlere numër të plotë.
    • \n
    • 1y: lënda do + të ruhet për 1 vit. 1-shin mund ta zëvendësoni me çfarëdo vlere numër të + plotë.
    • \n
    • never: lënda nuk skadon kurrë dhe do të mbahet përgjithnjë.
    • \n\ +
    \n" +livechat_configuration_channel_forbidden_words_reason_label: Arsye +livechat_configuration_channel_forbidden_words_comments_label: Komente +livechat_configuration_channel_quote_label2: Mesazhe +livechat_configuration_channel_command_message_desc: Mesazhi për t’u dërguar. +livechat_configuration_channel_banned_jids_label: Përdorues dhe rregullsi të dëbuara +validation_error: Pati një gabim gjatë vleftësimit. +invalid_value: Vlerë e pavlefshme. +invalid_value_missing: Kjo vlerë është e domosdoshme. +invalid_value_wrong_type: Vlera është e një lloji të gabuar. +invalid_value_wrong_format: Vlera është në format të gabuar. +invalid_value_not_in_range: Vlerë jo brenda intervalit të autorizuar. +invalid_value_duplicate: Vlerë e përsëdytur +invalid_value_too_long: Vlerë shumë e gjatë +too_many_entries: Shumë zëra +chatroom_not_accessible: Kjo dhomë fjalosjeje s’ekziston, ose s’lejoheni të hyni në + të. +login_using_external_account: Bëni hyrjen duke përdorur një llogari të jashtme +login_remote_peertube_url: URL e instancës tuaj Peertube +login_remote_peertube_video_not_found: Kjo video s’është në këtë instancë Peertube. +login_external_auth_alert_message: Mirëfilltësimi dështoi +task_list_delete: Fshi listë punësh +task_create: Krijoni një punë të re +task_name: Emër pune +task_description: Përshkrim +task_delete_confirm: Jeni i sigurt se doni të fshihet kjo punë? +task_list_pick_title: Ju lutemi, zgjidhni një listë punësh +livechat_configuration_channel_emojis_title: Emoxhi kanali +livechat_emojis_shortname: Emër i shkurtër +livechat_emojis_file_desc: "Kartela e emoji-t.\n" +action_export: Eksportoje +action_remove_entry_confirm: Jeni i sigurt se doni të hiqet ky zë? +loading_error: Ndodhi gabim teksa ngarkoheshin të dhëna. +token_password: Token fjalëkalimi +token_date: Datë +token_action_revoke: Hiqe token-in +token_default_label: Token i prodhuar nga ndërfaqja web +token_action_create: Krijoni një token të ri +token_action_revoke_confirm: Jeni i sigurt se doni të hiqet ky token? +livechat_configuration_channel_mute_anonymous_label: Heshto përdorues anonimë +livechat_configuration_channel_terms_label: Terma & kushte kanali fjalosjeje +new_poll: Krijoni një pyetësor të ri +poll_title: Pyetësor i ri +poll_question: Pyetje +poll_duration: Kohëzgjatje pyetësori (në minuta) +poll_anonymous_results: Përfundime anonime +poll_is_over: Ky pyetësor tanimë ka përfunduar. +poll_choice_invalid: Kjo zgjedhje s’është e vlefshme. +chat_behaviour_description:

    Sjellje fjalosjeje

    +room_type_label: Lloj dhome +auto_display_description: Kur shihet një video, dritarja e fjalosjes do të hapet vetvetiu. +open_blank_label: Shfaq butonin “hape në dritare të re” +all_lives_label: Aktivizo fjalosje për krejt të drejtpërdrejtat +converse_theme_description: Ju lutemi, zgjidhni temën converseJS që doni të përdoret. +prosody_port_label: Portë Prosody +prosody_muc_log_by_default_label: Regjistro ç’bëhet në dhomë, si parazgjedhje +prosody_room_allow_s2s_label: Aktivizoni lidhje te dhoma duke përdorur llogari të + jashtme XMPP +prosody_certificates_dir_label: Dosje dëshmish +livechat_configuration_channel_forbidden_words_label_label: Etiketë +task_delete: Fshije punën +avatar_set_option_bird: Zogj +autocolors_label: Pikasje e vetvetishme ngjyrash +help_builtin_prosody_label: Shërbyes Prosody +prosody_c2s_port_label: Klient Prosody te portë shërbyesi +prosody_components_list_label: Përbërës të jashtëm +prosody_components_port_label: Portë përbërësish Prosody të jashtëm +livechat_configuration_channel_command_cmd_label: Urdhër +livechat_configuration_channel_title: Mundësi kanali +prosody_muc_expiration_label: Skadim regjistrash dhome +livechat_configuration_channel_quote_label: Kohëmatës +livechat_configuration_channel_bot_nickname: Nofkë roboti +federation_no_remote_chat_label: Mos shfaq fjalosje nga larg +federation_no_remote_chat_description: "Duke i vënë shenjë këtij rregullimi, instanca + juaj s’do të shfaqë kurrë fjalosje prej videosh të largëta.\n" +federation_dont_publish_remotely_label: Mos boto hollësifjalosjeje +auto_display_label: Hape vetvetiu fjalosjen +livechat_emojis_file: Kartelë +action_import: Importoje +share_url_option_owner: Shfaq të zotin e videos +avatar_set_option_cat: Mace +share_chat_embed: Trupëzojeni +share_chat_peertube_tips: Kjo lidhje do ta hapë fjalosjen brenda ndërfaqes së Peertube-it. +auth_description: "

    Mirëfilltësim

    \n" +external_auth_google_oidc_label: Përdor Google +save: Ruaje +chat_title:

    Fjalosje

    +action_add_entry: Shtoni një zë +action_remove_entry: Hiqe këtë zë +token_label: Etiketë +poll: Pyetësor +poll_choice_n: 'Zgjedhje {{N}}:' +poll_end: 'Pyetësori përfundon më:' +link_copied: Lidhja u kopjua +error: Gabim +open: Hape +web: Web +online_help: Ndihmë në Internet +federation_description: "

    Federim

    \nRregulliemt vijuese kanë të bëjnë me federimin + me instanca të tjera\nPeertube dhe programe të tjera fediversi.\n" +invalid_value_file_too_big: 'Madhësia e kartelës është shumë e madhe (madhësi maksimum: + %s).' +all_non_lives_description: Në iu vëntë shenjë, fjalosja do të jetë e aktivizuar për + krejt videot që s’janë transmetimet e drejtpërdrejta. +external_auth_custom_oidc_title:

    OpenID Connect

    +external_auth_custom_oidc_label: Përdorni një shërbim OpenID Connect +external_auth_custom_oidc_button_label_description: Kjo etiketë do t’ju shfaqet përdoruesve, + si etiketa e butonit për kryerje mirëfilltësimi me këtë shërbim OIDC. +per_live_video_description: Në iu vëntë shenjë, krejt videot e transmetuara drejtpërdrejt + do të kenë një kutizë te vetitë e tyre, për aktivizim fjalosjeje. +livechat_configuration_channel_moderation_delay_desc: "Vlerë parazgjedhjeje vonese + moderimi:\n
      \n
    • 0: vonesë moderimi e çaktivizuar
    • \n
    • Çfarëdo numër + i plotë pozitiv: mesazhet do të vonohen për X sekonda për pjesëmarrës që s’janë + moderatorë, duke u lejuar moderatorëve të fshijnë mesazhe para se të mund t’i lexojë + cilido përdorues.
    • \n
    \n" +all_lives_description: Në iu vëntë shenjë, fjalosja do të jetë e aktivizuar për krejt + transmetimet e drejtpërdrejta. +all_non_lives_label: Aktivizo fjalosje për krejt transmetimet jo të drejtpërdrejta +room_type_description: Këtu mund të zgjidhni të keni dhoma më vete për çdo video, + ose t’i gruponi sipas kanalesh. +share_url_option_owner_moderators: Shfaqe për të zotin e videos dhe moderatorët e + instancës +poll_vote_instructions: 'Që të votoni, klikoni mbi zgjedhjen tuaj, ose dërgoni një + mesazh me një pikëçuditje pasuar nga numri që keni zgjedhur (Shembull: !1).' +external_auth_custom_oidc_description: "Mund të formësoni një shërbim të jashtëm OpenID + që mund të përdoret për të bërë hyrjen te fjalosja.\nJu lutemi, shihni te dokumentimi:\n + Rregullime.\n" +external_auth_google_oidc_description: "Aktivizimi i kësaj shton një buton “hyrje + me Google”.\nJu duhet të formësoni një aplikacion Google OAuth.\n" +external_auth_facebook_oidc_description: "Aktivizimi i kësaj shton një buton “hyrje + me Facebook”.\nJu duhet të formësoni një aplikacion Facebook OAuth.\n" +share_url_description: Do të ketë një buton për dhënien e URL-së së fjalosjes (mund + të përdoret për integrim OBS, për shembull). +avatar_set_description: "Avatarët parazgjedhje që do të përdoren për përdoruesit i + fjalosjes mund t’i zgjidhni nga disa grupe të ndryshme.\nJu lutemi, shihni te dokumentimi:\n + Rregullime.\n" +livechat_configuration_channel_mute_anonymous_desc: "Vlerë parazgjedhje për dhoma + të reja fjalosjeje.\nPër dhoma ekzistuese, mund të ndryshoni veçorinë te formulari + i formësimit të dhomave.\nKur kjo veçori është e aktivizuar, përdoruesit anonimë + vetëm se do të lexojnë fjalosjen dhe s’mund të dërgojnë mesazhe.\n" +transparent_background: Sfond i tejdukshëm (për integrim transmetimi, me OBS për shembull) +livechat_configuration_channel_emojis_desc: "Mund të formësoni emoxhi vetjake për + kanalin tuaj.\nKëto emoxhi do të jenë të përdorshëm që nga zgjedhësi i tyre.\nPërdoruesit + mund t’i përdoren edhe përmes emrit të shkurtër përkatës (për shembull, duke shkruar + \":emrineshkurtër:\").\n" +important_note_text: "Dokumentimin e shtojcës mund ta gjeni këtu:\n\n Dokumentim Shtojce Peertube Livechat\n.\n" +action_import_emojis_info: Nëse të dhënat e importuara janë në rregull, mos harroni + të ruani formularin. +livechat_configuration_channel_terms_desc: "Mund të formësoni një ndarje “terma & + kushte” që do t’u shfaqet përdoruesve që hyjnë në dhomat tuaja.\n" +poll_vote_instructions_xmpp: 'Që të votoni, dërgoni një mesazh me një pikëçuditje + pasuar nga numri që keni zgjedhur. Shembull: !1' +poll_anonymous_vote_ok: Vota juaj është marrë parasysh. Votat janë anonime, s’do t’u + shfaqen pjesëmarrësve të tjerë. +poll_vote_ok: Vota juaj është marrë parasysh, numëratorët do të përditësohen në çast. +moderator_notes: Shënime moderimi +chat: Fjalosje diff --git a/languages/sv.yml b/languages/sv.yml index f78c464e..3ed89487 100644 --- a/languages/sv.yml +++ b/languages/sv.yml @@ -28,7 +28,7 @@ room_type_description: Här kan du välja om du vill ha separata rum för varje theming_advanced_description:

    Utseende

    converse_theme_option_peertube: PeerTubes tema converse_theme_option_default: ConverseJS standardtema -converse_theme_option_concord: ConverseJS-temat concord +converse_theme_option_cyberpunk: ConverseJS-temat cyberpunk autocolors_label: Automatisk färgigenkänning save: Spara cancel: Avbryt diff --git a/languages/zh-Hant.yml b/languages/zh-Hant.yml index e69de29b..6f2e048d 100644 --- a/languages/zh-Hant.yml +++ b/languages/zh-Hant.yml @@ -0,0 +1,174 @@ +no_anonymous_description: "若勾選,匿名 Peertube 用戶將看不到聊天資訊。\n此功能仍處於實驗階段。\n如果您啟用了它,強烈建議您也勾選「不發布聊天訊息」。\n\ + 否則,某些第三方工具可能會嘗試開啟聊天,並出現不可預測的行為。\n" +external_auth_custom_oidc_description: "您可以設定可用於登入聊天的外部 OpenID Connect 提供者。\n請參考檔案:\n + 設定。\n" +room_type_option_video: 每個影片都有自己的網路聊天室 +login_external_auth_alert_message: 驗證失敗 +task_list_pick_empty: 現在沒有任何任務,請創建第一個 +task_list_pick_message: "選擇任務清單後,將建立新任務。\n若要查看任務,請使用頂部選單開啟任務應用程式。\n即時聊天外掛檔案中的更多資訊。\n" +livechat_configuration_channel_enable_bot_label: 啟用審核機器人 +login_remote_peertube_video_not_found: 該影片在此 Peertube 實例上不可用。 +menu_configuration_label: 聊天室 +livechat_configuration_title: 您的直播聊天室設定 +livechat_configuration_desc: 您可以在此處為與直播相關的聊天室設定一些進階選項。 +system_prosody_description: "警告:如果您不確定自己在做什麼,請不要檢查此設定。\n透過檢查此設置,您的 Peertube 將使用系統附帶的 + Prosody 伺服器,\n而不是嵌入的 AppImage。\n僅當您遇到嵌入式 Prosody 問題時才使用此選項。\n" +configuration_description: "

    頻道進階組態

    \n以下設定涉及進階頻道選項:\n使用者將能夠在他們的頻道上新增客製化,\n\ + 啟動審核機器人,...\n" +disable_websocket_label: 停用 Websocket +save: 儲存 +successfully_saved: 存檔成功 +livechat_configuration_please_select: 請在下面選擇您的頻道之一,以設定其聊天選項。 +livechat_configuration_channel_title: 頻道選項 +livechat_configuration_channel_desc: 您可以在此處為此頻道設定一些選項(審核策略,...)。 +livechat_configuration_channel_forbidden_words_label: 禁止使用的單字或句子 +livechat_configuration_channel_forbidden_words_desc: "您可以組態一些由機器人自動審核的單字(包含此類單字的訊息將立即刪除)。\n\ + 您也可以新增一個可選原因,該原因將顯示在已刪除郵件的位置。\n檔案頁面上提供了幾個範例。\n" +livechat_configuration_channel_forbidden_words_desc2: "每行只能一個單字或句子。如果將多個單字放在一行上,它將只配取到包含整行的訊息。\n" +livechat_configuration_channel_command_cmd_label: 命令 +livechat_configuration_channel_for_more_info: "有關如何設定此功能的更多資訊,請按一下幫助按鈕參考檔案。\n" +livechat_configuration_channel_banned_jids_label: 禁止的使用者和模式 +validation_error: 驗證時出現錯誤。 +invalid_value: 無效的值。 +invalid_value_missing: 該欄必填。 +invalid_value_wrong_type: 該欄不接受這種型別。 +invalid_value_wrong_format: 錯誤的格式。 +invalid_value_not_in_range: 值不在符合範圍內。 +invalid_value_file_too_big: '檔案太大(max size: %s).' +invalid_value_duplicate: 重覆值 +too_many_entries: 太多項目 +chatroom_not_accessible: 這個聊天室不存在或者您無法訪問。 +login_using_external_account: 使用外部帳戶登入 +login_remote_peertube: 使用另一個 Peertube 實例上的帳號登入: +login_remote_peertube_url: 您的Peertube實例網址 +login_remote_peertube_searching: 在 Peertube 實例上搜尋影片... +login_remote_peertube_video_not_found_try_anyway: 在某些情況下,如果您連接到遠端實例,仍然可以檢索視訊。 +login_remote_peertube_video_not_found_try_anyway_button: 無論如何嘗試在 Peertube 實例上打開影片 +login_remote_peertube_video_open_failed: 您的瀏覽器阻止了遠端實例的啟動,請嘗試手動開啟此連結: +tasks: 任務 +task_list_create: '創建新任務清單:' +task_list_create_error: 儲存任務清單時發生錯誤 +task_list_name: 任務清單名稱 +task_create: 創建新任務 +task_name: 任務名稱 +task_description: 任務用途 +task_delete: 刪除任務 +task_delete_confirm: 您確定要刪除此任務? +task_list_pick_title: 請選擇任務清單 +promote: 成為版主 +livechat_configuration_channel_emojis_title: 頻道emojis +livechat_configuration_channel_bot_options_title: 審核機器人選項 +livechat_configuration_channel_forbidden_words_reason_label: 原因 +livechat_configuration_channel_command_message_desc: 發送訊息。 +slow_mode_info: 限速模式已啟用,使用者可以每 %1$s 秒發送一則訊息。 +disable_channel_configuration_label: 停用進階頻道設定和聊天機器人 +cancel: 取消 +livechat_configuration_channel_forbidden_words_reason_desc: 除已刪除訊息外還顯示的原因 +error: 錯誤 +use_current_theme_color: 使用當前主題顏色 +chat_title:

    聊天

    +federation_no_remote_chat_description: "透過檢查此設置,您的實例將永遠不會顯示來自遠端視訊的聊天。\n" +federation_dont_publish_remotely_label: 不公開聊天資訊 +all_lives_label: 所有直播啟動聊天室 +no_anonymous_label: 隱藏匿名使用者的聊天 +converse_theme_label: ConverseJS 主題 +converse_theme_description: 請選擇您要使用的 converseJS 主題。 +converse_theme_option_default: 預設ConverseJS主題 +chat_style_label: 聊天 iframe 風格屬性 +prosody_peertube_uri_label: Peertube API呼叫網址 +task_list_delete: 刪除任務清單 +task_list_delete_confirm: 您確定要刪除此任務清單? +federation_description: "

    聯盟

    \n以下設定涉及與其他 Peertube 實例的聯合,\n和其他聯邦多元化軟體。\n" +chat_terms_label: 條款及條件 +list_rooms_label: 列出現有聊天室 +federation_no_remote_chat_label: 不顯示遠端聊天 +external_auth_description: "

    外部身份驗證

    \n對於沒有 Peertube 帳戶的用戶,您可以基於遠端身份驗證提供者啟用各種身份驗證模式。\n" +prosody_advanced_description:

    聊天伺服器進階設定

    +invalid_value_too_long: 值超出範圍 +login_remote_peertube_no_livechat: 此 Peertube 實例上未安裝即時聊天外掛程式。 +login_remote_peertube_url_invalid: 無效的Peertube網址。 +theming_advanced_description:

    主題

    +link_copied: 連結已複製 +show_scrollbarr: 顯示聊天捲軸 +transparent_background: 透明背景(用於串流媒體整合,例如OBS) +room_type_option_channel: 網路聊天室按頻道分組 +auto_display_label: 自動開啟聊天 +share_url_option_everyone: 任何人皆可看到 +share_url_option_owner: 只對影片擁有者顯示 +livechat_configuration_channel_slow_mode_label: 限速模式 +livechat_configuration_channel_slow_mode_desc: "限速模式預設值:\n
      \n
    • 0:停用限速模式
    • \n +
    • 任何正整數:使用者可以每 X 秒發送一條訊息(審核者不受限制)
    • \n
    \n" +prosody_firewall_name: 名字 +prosody_firewall_file_enabled: 啟用 +livechat_configuration_channel_emojis_desc: "您可以為您的頻道組態自訂表情符號。\n這些表情符號將在表情符號選擇器中提供。\n\ + 使用者也可以透過其短名稱來使用它們(例如透過編寫“:shortname:”)。\n" +livechat_emojis_shortname: 簡稱 +livechat_emojis_file: 檔案 +action_import: 匯入 +action_export: 匯出 +list_rooms_description: "列出聊天室\n" +autocolors_description: "嘗試自動偵測使用者目前主題的顏色。\n啟用此設定後,外掛程式會嘗試自動偵測顏色以套用至聊天主題。\n如果這對於您的某些 + Peertube 主題無法正常運作,您可以停用此選項。\n您可以向官方報告該錯誤\n\n 問題追蹤器\n。不要忘記指定哪個主題不起作用。\n" +prosody_firewall_content: 檔案內容 +prosody_firewall_disabled_warning: "警告:mod_firewall 在即時聊天外掛設定中被停用,如果您希望此組態生效,則必須啟用它予以考慮。\n" +disable_websocket_description: "當 Peertube >= 5.0.0 時,外掛嘗試使用 Websocket 連線進行聊天。\n如果使用者的瀏覽器或連線不相容,瀏覽器將自動轉而使用 + BOSH 協定。\n
    \n但在極少數情況下,這可能會失敗。例如,如果您在 Peertube 前面有一個反向代理,但它不\n允許外掛的 Websocket + 連線。\n在這種情況下,您可以檢查此設定以停用 Websocket 連線。\n" +prosody_firewall_name_desc: "只能包含:字母數字字元、底線和連字元。\n指令將按字母順序讀取。\n" +open_chat: 開始聊天 +copy: 複製 +federation_dont_publish_remotely_description: "透過檢查此設置,您的實例將不會在 fediverse 上發布聊天訊息。\n + 遠端 Peertube 實例不會意識到它們是與您的視訊關聯的聊天室。\n請注意:如果您已經進行過聊天,則該資訊可能已經發布。\n您必須等待下一次視訊更新,訊息才會取消發布。\n + 此外,如果您停用此設置,則必須等待視訊更新後才能顯示資訊。\n再次發布。當現場活動恢復或停止時,會發生此更新。\n請注意:此設定僅影響透過 ActivityPub + 協定發布資訊。\n它不會阻止遠端應用程式檢測聊天的存在並嘗試連接到它。\n" +auto_ban_anonymous_ip_description: "透過啟用此選項,每次匿名用戶被禁止進入聊天室時,其 IP 也將被聊天伺服器禁止。\n警告:如果您的執行個體開放註冊,任何使用者都可以建立陷阱房間、邀請使用者加入,並自動禁止所有匿名使用者的 + IP。\n禁止的IP清單不會被存儲,它會在伺服器重新啟動或更改某些外掛的設定時被清除。\n被禁止的IP會記錄在Prosody伺服器日誌檔案中,因此伺服器管理員最終可以使用一些外部工具(如fail2ban)來更廣泛地禁止IP。\n" +avatar_set_description: "您可以從多個不同的設定中選擇將用於聊天使用者的預設頭像。\n請參考檔案:\n設定。\n" +avatar_set_option_sepia: 棕褐色(Peertube 吉祥物) +converse_theme_option_peertube: Peertube主題 +autocolors_label: 自動色彩檢測 +open_chat_new_window: 在新視窗開啟聊天 +close_chat: 關閉聯天 +tips_for_streamers: "給直播主的提示:例如,要使用 OBS 將聊天嵌入到視訊直播中,\n產生唯讀連結並將其供瀏覽器使用。\n" +chat_terms_description: "這些條款和條件將在所有使用者加入聊天室時顯示。\n直播主還可以為其頻道配置條款和條件,這些條款和條件將立即顯示在這些全域條款和條件之後。\n" +auto_display_description: 觀看影片時,聊天視窗會自動開啟。 +open_blank_label: 顯示“在新視窗中開啟”按鈕 +open_blank_description: 此按鈕可在新視窗中開啟網路聊天。 +share_url_label: 顯示「共享聊天連結」按鈕 +share_url_description: 用於共享聊天 URL 的按鈕(例如,可用於 OBS 整合)。 +share_url_option_nobody: 無人可見 +share_url_option_owner_moderators: 只有影片擁有者與管理者可見 +auto_ban_anonymous_ip_label: 當用戶被禁止進入聊天室時,禁止匿名用戶的 IP +copied: 已複製 +generate_iframe: 產生 iframe 以將聊天嵌入到網站中 +chat_for_live_stream: '直播聊天:' +use_chat: 使用聊天功能 +use_chat_help: 如果啟用,影片旁邊將會出現聊天視窗。 +share_chat_link: 分享聊天連結 +read_only: 唯讀 +external_auth_custom_oidc_button_label_label: 連接按鈕的標籤 +external_auth_custom_oidc_button_label_description: 此標籤將作為向該 OIDC 提供者進行身份驗證的按鈕標籤顯示給使用者。 +external_auth_custom_oidc_discovery_url_label: OIDC_custom_dicovery_url +room_type_label: 聊天室類型 +room_type_description: 您可以在此處選擇為每個影片設定單獨的聊天室,或按頻道對它們進行分組。 +video: 影片 +channel: 頻道 +last_activity: 最後異動 +important_note_title:

    注意事項

    +online_help: 線上幫助 +not_found: 未找到 +important_note_text: "您可以在這裡找到外掛文件:\n\n Peertube 外掛即時聊天檔案\n。\n" +diagnostic: "在尋求協助之前,請使用診斷工具:\n啟動診斷\n(如果此按鈕沒有開啟新視窗,請嘗試重新整理頁面)。\n" +room_description: 聊天室說明 +room_name: 聊天室名稱 +per_live_video_label: 使用者在直播時可啟用聊天 +per_live_video_warning_description: "\n 您已啟用「使用者可以自已啟用聊天室」設定。\n 它與“啟動所有直播都有聊天室”設定是互斥的。\n\n" +all_lives_description: 若勾選,則所有直播都啟用聊天室。 diff --git a/package-lock.json b/package-lock.json index 0f02b0db..1137c37c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "peertube-plugin-livechat", - "version": "10.3.3", + "version": "11.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "peertube-plugin-livechat", - "version": "10.3.3", + "version": "11.0.1", "license": "AGPL-3.0", "dependencies": { "@xmpp/jid": "^0.13.1", @@ -56,7 +56,7 @@ "stylelint-config-recommended-scss": "^5.0.1", "stylelint-config-standard-scss": "^2.0.1", "svgo": "^2.8.0", - "typescript": "^4.3.5", + "typescript": "^4.9.5", "yaml": "^2.2.1" }, "engines": { @@ -85,989 +85,1102 @@ } }, "node_modules/@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", "dev": true, "dependencies": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, "node_modules/@aws-crypto/crc32c": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", - "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", "dev": true, "dependencies": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" } }, - "node_modules/@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", - "dev": true, - "dependencies": { - "tslib": "^1.11.1" - } + "node_modules/@aws-crypto/crc32c/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true }, "node_modules/@aws-crypto/sha1-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", - "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", "dev": true, "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha1-browser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, "node_modules/@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", "dev": true, "dependencies": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, "node_modules/@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", "dev": true, "dependencies": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, "node_modules/@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", "dev": true, "dependencies": { - "tslib": "^1.11.1" + "tslib": "^2.6.2" } }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, "node_modules/@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", "dev": true, "dependencies": { "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@aws-sdk/chunked-blob-reader": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.310.0.tgz", - "integrity": "sha512-CrJS3exo4mWaLnWxfCH+w88Ou0IcAZSIkk4QbmxiHl/5Dq705OLoxf4385MVyExpqpeVJYOYQ2WaD8i/pQZ2fg==", + "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/chunked-blob-reader/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "dependencies": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "dependencies": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/client-s3": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.363.0.tgz", - "integrity": "sha512-LNnfg/t8wG5Fqj6l+PSV/t+IXDq9r3Kj9jEHn84513+p7bewXYSSreSpmLjG8OcKuMfHc9EJGNQ3DkMyFaLoWg==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.637.0.tgz", + "integrity": "sha512-y6UC94fsMvhKbf0dzfnjVP1HePeGjplfcYfilZU1COIJLyTkMcUv4XcT4I407CGIrvgEafONHkiC09ygqUauNA==", "dev": true, "dependencies": { - "@aws-crypto/sha1-browser": "3.0.0", - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.363.0", - "@aws-sdk/credential-provider-node": "3.363.0", - "@aws-sdk/hash-blob-browser": "3.357.0", - "@aws-sdk/hash-stream-node": "3.357.0", - "@aws-sdk/md5-js": "3.357.0", - "@aws-sdk/middleware-bucket-endpoint": "3.363.0", - "@aws-sdk/middleware-expect-continue": "3.363.0", - "@aws-sdk/middleware-flexible-checksums": "3.363.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-location-constraint": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-sdk-s3": "3.363.0", - "@aws-sdk/middleware-signing": "3.363.0", - "@aws-sdk/middleware-ssec": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/signature-v4-multi-region": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@aws-sdk/xml-builder": "3.310.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/eventstream-serde-browser": "^1.0.1", - "@smithy/eventstream-serde-config-resolver": "^1.0.1", - "@smithy/eventstream-serde-node": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.2", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.0.1", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.0.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.2", - "@smithy/util-stream": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "@smithy/util-waiter": "^1.0.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.637.0", + "@aws-sdk/client-sts": "3.637.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.637.0", + "@aws-sdk/middleware-bucket-endpoint": "3.620.0", + "@aws-sdk/middleware-expect-continue": "3.620.0", + "@aws-sdk/middleware-flexible-checksums": "3.620.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-location-constraint": "3.609.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-sdk-s3": "3.635.0", + "@aws-sdk/middleware-ssec": "3.609.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/signature-v4-multi-region": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@aws-sdk/xml-builder": "3.609.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/eventstream-serde-browser": "^3.0.6", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.5", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-blob-browser": "^3.1.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/hash-stream-node": "^3.1.2", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/md5-js": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-stream": "^3.1.3", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.1.2", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/client-s3/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/client-sso": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.363.0.tgz", - "integrity": "sha512-PZ+HfKSgS4hlMnJzG+Ev8/mgHd/b/ETlJWPSWjC/f2NwVoBQkBnqHjdyEx7QjF6nksJozcVh5Q+kkYLKc/QwBQ==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.637.0.tgz", + "integrity": "sha512-+KjLvgX5yJYROWo3TQuwBJlHCY0zz9PsLuEolmXQn0BVK1L/m9GteZHtd+rEdAoDGBpE0Xqjy1oz5+SmtsaRUw==", "dev": true, "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.2", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.0.1", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.0.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.2", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.363.0.tgz", - "integrity": "sha512-V3Ebiq/zNtDS/O92HUWGBa7MY59RYSsqWd+E0XrXv6VYTA00RlMTbNcseivNgp2UghOgB9a20Nkz6EqAeIN+RQ==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.637.0.tgz", + "integrity": "sha512-27bHALN6Qb6m6KZmPvRieJ/QRlj1lyac/GT2Rn5kJpre8Mpp+yxrtvp3h9PjNBty4lCeFEENfY4dGNSozBuBcw==", "dev": true, "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.2", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.0.1", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.0.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.2", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.637.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.637.0" } }, "node_modules/@aws-sdk/client-sso-oidc/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/client-sso/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/client-sts": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.363.0.tgz", - "integrity": "sha512-0jj14WvBPJQ8xr72cL0mhlmQ90tF0O0wqXwSbtog6PsC8+KDE6Yf+WsxsumyI8E5O8u3eYijBL+KdqG07F/y/w==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.637.0.tgz", + "integrity": "sha512-xUi7x4qDubtA8QREtlblPuAcn91GS/09YVEY/RwU7xCY0aqGuFwgszAANlha4OUIqva8oVj2WO4gJuG+iaSnhw==", "dev": true, "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.363.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-sdk-sts": "3.363.0", - "@aws-sdk/middleware-signing": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.1", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.2", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.637.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.637.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/client-sts/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@aws-sdk/core": { + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.635.0.tgz", + "integrity": "sha512-i1x/E/sgA+liUE1XJ7rj1dhyXpAKO1UKFUcTTHXok2ARjWTvszHnSXMOsB77aPbmn0fUp1JTx2kHUAZ1LVt5Bg==", + "dev": true, + "dependencies": { + "@smithy/core": "^2.4.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.363.0.tgz", - "integrity": "sha512-VAQ3zITT2Q0acht0HezouYnMFKZ2vIOa20X4zQA3WI0HfaP4D6ga6KaenbDcb/4VFiqfqiRHfdyXHP0ThcDRMA==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", + "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-env/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.635.0.tgz", + "integrity": "sha512-iJyRgEjOCQlBMXqtwPLIKYc7Bsc6nqjrZybdMDenPDa+kmLg7xh8LxHsu9088e+2/wtLicE34FsJJIfzu3L82g==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.363.0.tgz", - "integrity": "sha512-ZYN+INoqyX5FVC3rqUxB6O8nOWkr0gHRRBm1suoOlmuFJ/WSlW/uUGthRBY5x1AQQnBF8cpdlxZzGHd41lFVNw==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.637.0.tgz", + "integrity": "sha512-h+PFCWfZ0Q3Dx84SppET/TFpcQHmxFW8/oV9ArEvMilw4EBN+IlxgbL0CnHwjHW64szcmrM0mbebjEfHf4FXmw==", "dev": true, "dependencies": { - "@aws-sdk/credential-provider-env": "3.363.0", - "@aws-sdk/credential-provider-process": "3.363.0", - "@aws-sdk/credential-provider-sso": "3.363.0", - "@aws-sdk/credential-provider-web-identity": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.635.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.637.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.637.0" } }, "node_modules/@aws-sdk/credential-provider-ini/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.363.0.tgz", - "integrity": "sha512-C1qXFIN2yMxD6pGgug0vR1UhScOki6VqdzuBHzXZAGu7MOjvgHNdscEcb3CpWnITHaPL2ztkiw75T1sZ7oIgQg==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.637.0.tgz", + "integrity": "sha512-yoEhoxJJfs7sPVQ6Is939BDQJZpZCoUgKr/ySse4YKOZ24t4VqgHA6+wV7rYh+7IW24Rd91UTvEzSuHYTlxlNA==", "dev": true, "dependencies": { - "@aws-sdk/credential-provider-env": "3.363.0", - "@aws-sdk/credential-provider-ini": "3.363.0", - "@aws-sdk/credential-provider-process": "3.363.0", - "@aws-sdk/credential-provider-sso": "3.363.0", - "@aws-sdk/credential-provider-web-identity": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.635.0", + "@aws-sdk/credential-provider-ini": "3.637.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.637.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.363.0.tgz", - "integrity": "sha512-fOKAINU7Rtj2T8pP13GdCt+u0Ml3gYynp8ki+1jMZIQ+Ju/MdDOqZpKMFKicMn3Z1ttUOgqr+grUdus6z8ceBQ==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", + "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-process/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.363.0.tgz", - "integrity": "sha512-5RUZ5oM0lwZSo3EehT0dXggOjgtxFogpT3cZvoLGtIwrPBvm8jOQPXQUlaqCj10ThF1sYltEyukz/ovtDwYGew==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.637.0.tgz", + "integrity": "sha512-Mvz+h+e62/tl+dVikLafhv+qkZJ9RUb8l2YN/LeKMWkxQylPT83CPk9aimVhCV89zth1zpREArl97+3xsfgQvA==", "dev": true, "dependencies": { - "@aws-sdk/client-sso": "3.363.0", - "@aws-sdk/token-providers": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/client-sso": "3.637.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.363.0.tgz", - "integrity": "sha512-Z6w7fjgy79pAax580wdixbStQw10xfyZ+hOYLcPudoYFKjoNx0NQBejg5SwBzCF/HQL23Ksm9kDfbXDX9fkPhA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", + "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.621.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/hash-blob-browser": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.357.0.tgz", - "integrity": "sha512-RDd6UgrGHDmleTnXM9LRSSVa69euSAG2mlNhZMEDWk3OFseXVYqBDaqroVbQ01rM2UAe8MeBFchlV9OmxuVgvw==", - "dev": true, - "dependencies": { - "@aws-sdk/chunked-blob-reader": "3.310.0", - "@aws-sdk/types": "3.357.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/hash-blob-browser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/hash-stream-node": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-stream-node/-/hash-stream-node-3.357.0.tgz", - "integrity": "sha512-KZjN1VAw1KHNp+xKVOWBGS+MpaYQTjZFD5f+7QQqW4TfbAkFFwIAEYIHq5Q8Gw+jVh0h61OrV/LyW3J2PVzc+w==", - "dev": true, - "dependencies": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-utf8": "3.310.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/hash-stream-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/is-array-buffer": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz", - "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==", - "dev": true, - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/is-array-buffer/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/md5-js": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.357.0.tgz", - "integrity": "sha512-to42sFAL7KgV/X9X40LLfEaNMHMGQL6/7mPMVCL/W2BZf3zw5OTl3lAaNyjXA+gO5Uo4lFEiQKAQVKNbr8b8Nw==", - "dev": true, - "dependencies": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-utf8": "3.310.0", - "tslib": "^2.5.0" - } - }, - "node_modules/@aws-sdk/md5-js/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.363.0.tgz", - "integrity": "sha512-kR8+0X50zslpzRW29q4JbpPMadE1z39ZfGwPaBLKpoWvSGt4x+75FaoK71TH7urPPoFyD2Y+XKGA6YRYTUNHSQ==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.620.0.tgz", + "integrity": "sha512-eGLL0W6L3HDb3OACyetZYOWpHJ+gLo0TehQKeQyy2G8vTYXqNTeqYhuI6up9HVjBzU9eQiULVQETmgQs7TFaRg==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-arn-parser": "3.310.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "@smithy/util-config-provider": "^1.0.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.363.0.tgz", - "integrity": "sha512-I88xneZp6jRwySmIl9uI7eZCcTsqRVnTDfUr1JiXt7zonqNNm80PVYMs6pwaw7t97ec1AQJcsONjuXZyCMnu5g==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.620.0.tgz", + "integrity": "sha512-QXeRFMLfyQ31nAHLbiTLtk0oHzG9QLMaof5jIfqcUwnOkO8YnQdeqzakrg1Alpy/VQ7aqzIi8qypkBe2KXZz0A==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-expect-continue/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.363.0.tgz", - "integrity": "sha512-FBYmrMRX01uNximNN0WLgpf97GN4xNTLaKsDlkjYRWKJ+J97ICkvLG0FcSu7+SNCpCdJJBeQ5tRVOPVpUu6nmA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.620.0.tgz", + "integrity": "sha512-ftz+NW7qka2sVuwnnO1IzBku5ccP+s5qZGeRTPgrKB7OzRW85gthvIo1vQR2w+OwHFk7WJbbhhWwbCbktnP4UA==", "dev": true, "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@aws-crypto/crc32c": "3.0.0", - "@aws-sdk/types": "3.357.0", - "@smithy/is-array-buffer": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-sdk/types": "3.609.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.363.0.tgz", - "integrity": "sha512-FobpclDCf5Y1ueyJDmb9MqguAdPssNMlnqWQpujhYVABq69KHu73fSCWSauFPUrw7YOpV8kG1uagDF0POSxHzA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", + "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-host-header/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.363.0.tgz", - "integrity": "sha512-piNzpNNI/fChSGOZxcq/2msN2qFUSEAbhqs91zbcpv8CEPekVLc4W9laXCG764BEMyfG97ZU8MtzwHeMhELhBA==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz", + "integrity": "sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-location-constraint/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.363.0.tgz", - "integrity": "sha512-SSGgthScYnFGTOw8EzbkvquqweFmvn7uJihkpFekbtBNGC/jGOGO+8ziHjTQ8t/iI/YKubEwv+LMi0f77HKSEg==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-logger/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.363.0.tgz", - "integrity": "sha512-MWD/57QgI/N7fG8rtzDTUdSqNpYohQfgj9XCFAoVeI/bU4usrkOrew43L4smJG4XrDxlNT8lSJlDtd64tuiUZA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", + "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-recursion-detection/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.363.0.tgz", - "integrity": "sha512-npC8vLCero+vULizrK0QPjNanWbgH4A/2Llc1nO8N005uvUe7co6WglILF2W3guZrFk/0uGEdX67OnLxUD97pw==", + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.635.0.tgz", + "integrity": "sha512-RLdYJPEV4JL/7NBoFUs7VlP90X++5FlJdxHz0DzCjmiD3qCviKy+Cym3qg1gBgHwucs5XisuClxDrGokhAdTQw==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-arn-parser": "3.310.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/core": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/core": "^2.4.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-stream": "^3.1.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.363.0.tgz", - "integrity": "sha512-1yy2Ac50FO8BrODaw5bPWvVrRhaVLqXTFH6iHB+dJLPUkwtY5zLM3Mp+9Ilm7kME+r7oIB1wuO6ZB1Lf4ZszIw==", - "dev": true, - "dependencies": { - "@aws-sdk/middleware-signing": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.363.0.tgz", - "integrity": "sha512-/7qia715pt9JKYIPDGu22WmdZxD8cfF/5xB+1kmILg7ZtjO0pPuTaCNJ7xiIuFd7Dn7JXp5lop08anX/GOhNRQ==", - "dev": true, - "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/signature-v4": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.363.0.tgz", - "integrity": "sha512-pN+QN1rMShYpJnTJSCIYnNRhD0S8xSZsTn6ThgcO559Xiwz5LMHFOfOXUCEyxtbVW5kMHLUh3w101AMUKae99A==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz", + "integrity": "sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-ssec/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.363.0.tgz", - "integrity": "sha512-ri8YaQvXP6odteVTMfxPqFR26Q0h9ejtqhUDv47P34FaKXedEM4nC6ix6o+5FEYj6l8syGyktftZ5O70NoEhug==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.637.0.tgz", + "integrity": "sha512-EYo0NE9/da/OY8STDsK2LvM4kNa79DBsf4YVtaG4P5pZ615IeFsD8xOHZeuJmUrSMlVQ8ywPRX7WMucUybsKug==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/middleware-user-agent/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", + "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", + "dev": true, + "dependencies": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.363.0.tgz", - "integrity": "sha512-iWamQSpaBKg88LKuiUq8xO/7iyxJ+ORkA3qDhAwUqyTJOg87ma47yFf4ycCKqINnflc3AIGLGzBHnkBc4cMF5g==", + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.635.0.tgz", + "integrity": "sha512-J6QY4/invOkpogCHjSaDON1hF03viPpOnsrzVuCvJMmclS/iG62R4EY0wq1alYll0YmSdmKlpJwHMWwGtqK63Q==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/signature-v4": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/middleware-sdk-s3": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@aws-sdk/signature-v4-crt": "^3.118.0" - }, - "peerDependenciesMeta": { - "@aws-sdk/signature-v4-crt": { - "optional": true - } + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/token-providers": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.363.0.tgz", - "integrity": "sha512-6+0aJ1zugNgsMmhTtW2LBWxOVSaXCUk2q3xyTchSXkNzallYaRiZMRkieW+pKNntnu0g5H1T0zyfCO0tbXwxEA==", + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", "dev": true, "dependencies": { - "@aws-sdk/client-sso-oidc": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.614.0" } }, "node_modules/@aws-sdk/token-providers/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/types": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.357.0.tgz", - "integrity": "sha512-/riCRaXg3p71BeWnShrai0y0QTdXcouPSM0Cn1olZbzTf7s71aLEewrc96qFrL70XhY4XvnxMpqQh+r43XIL3g==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/types/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz", - "integrity": "sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==", + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-arn-parser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/util-buffer-from": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz", - "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==", - "dev": true, - "dependencies": { - "@aws-sdk/is-array-buffer": "3.310.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-buffer-from/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.357.0.tgz", - "integrity": "sha512-XHKyS5JClT9su9hDif715jpZiWHQF9gKZXER8tW0gOizU3R9cyWc9EsJ2BRhFNhi7nt/JF/CLUEc5qDx3ETbUw==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.637.0.tgz", + "integrity": "sha512-pAqOKUHeVWHEXXDIp/qoMk/6jyxIb6GGjnK1/f8dKHtKIEs4tKsnnL563gceEvdad53OPXIt86uoevCcCzmBnw==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-endpoints/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", - "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/util-locate-window/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.363.0.tgz", - "integrity": "sha512-fk9ymBUIYbxiGm99Cn+kAAXmvMCWTf/cHAcB79oCXV4ELXdPa9lN5xQhZRFNxLUeXG4OAMEuCAUUuZEj8Fnc1Q==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-browser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.363.0.tgz", - "integrity": "sha512-Fli/dvgGA9hdnQUrYb1//wNSFlK2jAfdJcfNXA6SeBYzSeH5pVGYF4kXF0FCdnMA3Fef+Zn1zAP/hw9v8VJHWQ==", + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", "dev": true, "dependencies": { - "@aws-sdk/types": "3.357.0", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" }, "peerDependencies": { "aws-crt": ">=1.0.0" @@ -1079,61 +1192,28 @@ } }, "node_modules/@aws-sdk/util-user-agent-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - }, - "node_modules/@aws-sdk/util-utf8": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz", - "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==", - "dev": true, - "dependencies": { - "@aws-sdk/util-buffer-from": "3.310.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dev": true, - "dependencies": { - "tslib": "^2.3.1" - } - }, - "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "node_modules/@aws-sdk/util-utf8/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz", - "integrity": "sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz", + "integrity": "sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@aws-sdk/xml-builder/node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@babel/cli": { @@ -3071,838 +3151,1000 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.1.tgz", - "integrity": "sha512-An6irzp9NCji2JtJHhrEFlDbxLwHd6c6Y9fq3ZeomyUR8BIXlGXVTxsemUSZVVgOq3166iYbYs/CrPAmgRSFLw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/abort-controller/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dev": true, + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/chunked-blob-reader/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/config-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-1.0.1.tgz", - "integrity": "sha512-quj0xUiEVG/UHfY82EtthR/+S5/17p3IxXArC3NFSNqryMobWbG9oWgJy2s2cgUSVZLzxevjKKvxrilK7JEDaA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", + "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "@smithy/util-config-provider": "^1.0.1", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/config-resolver/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/core": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.0.tgz", + "integrity": "sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w==", + "dev": true, + "dependencies": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/core/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/credential-provider-imds": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-1.0.1.tgz", - "integrity": "sha512-hkRJoxVCh4CEt1zYOBElE+G/MV6lyx3g68hSJpesM4pwMT/bzEVo5E5XzXY+6dVq8yszeatWKbFuqCCBQte8tg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz", + "integrity": "sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA==", "dev": true, "dependencies": { - "@smithy/node-config-provider": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/credential-provider-imds/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/eventstream-codec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.0.1.tgz", - "integrity": "sha512-cpcTXQEOEs2wEvIyxW/iTHJ2m0RVqoEOTjjWEXD6SY8Gcs3FCFP6E8MXadC098tdH5ctMIUXc8POXyMpxzGnjw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", + "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", "dev": true, "dependencies": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^1.1.0", - "@smithy/util-hex-encoding": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/eventstream-codec/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-1.0.1.tgz", - "integrity": "sha512-oc8vxe+AU2RzvXH/Ehh0TzM/Nsw3I3ywu7V3qaCzqdkBIntAwK9JGZqcSDsqTK0WxZKBRgFIEwopcuZ2slVnFQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.6.tgz", + "integrity": "sha512-2hM54UWQUOrki4BtsUI1WzmD13/SeaqT/AB3EUJKbcver/WgKNaiJ5y5F5XXuVe6UekffVzuUDrBZVAA3AWRpQ==", "dev": true, "dependencies": { - "@smithy/eventstream-serde-universal": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/eventstream-serde-universal": "^3.0.5", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-browser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-1.0.1.tgz", - "integrity": "sha512-TJwaXima0djnNY819utO1j93qZHaheFH1bhHxBkMrImtEOuXY48Tjma/L2m8swkIq8dy8jFC9hrYOkD0eYHkFA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz", + "integrity": "sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-config-resolver/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/eventstream-serde-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-1.0.1.tgz", - "integrity": "sha512-JEj8w7IRs4l+kcwKxbv3pNuu8n7ORC4pMFrIOrM4rERzrRnI7vMNTRzvAPGYA53rqm/Y9tBA9dw4C+H6hLXcsA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.5.tgz", + "integrity": "sha512-+upXvnHNyZP095s11jF5dhGw/Ihzqwl5G+/KtMnoQOpdfC3B5HYCcDVG9EmgkhJMXJlM64PyN5gjJl0uXFQehQ==", "dev": true, "dependencies": { - "@smithy/eventstream-serde-universal": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/eventstream-serde-universal": "^3.0.5", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-1.0.1.tgz", - "integrity": "sha512-c6m9DH7m6D2S93dof4wSxysaGSQdauO20TNcSePzrgHd4rkTnz5pqZ1a7Pt22q2SKf09SvTugq5cV2Sy4r8zHw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.5.tgz", + "integrity": "sha512-5u/nXbyoh1s4QxrvNre9V6vfyoLWuiVvvd5TlZjGThIikc3G+uNiG9uOTCWweSRjv1asdDIWK7nOmN7le4RYHQ==", "dev": true, "dependencies": { - "@smithy/eventstream-codec": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/eventstream-codec": "^3.1.2", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/eventstream-serde-universal/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/fetch-http-handler": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-1.0.1.tgz", - "integrity": "sha512-/e2A8eOMk4FVZBQ0o6uF/ttLtFZcmsK5MIwDu1UE3crM4pCAIP19Ul8U9rdLlHhIu81X4AcJmSw55RDSpVRL/w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", "dev": true, "dependencies": { - "@smithy/protocol-http": "^1.1.0", - "@smithy/querystring-builder": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-base64": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/fetch-http-handler/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz", + "integrity": "sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg==", + "dev": true, + "dependencies": { + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-blob-browser/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/hash-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.0.1.tgz", - "integrity": "sha512-eCz08BySBcOjVObjbRAS/XMKUGY4ujnuS+GoWeEpzpCSKDnO8/YQ0rStRt4C0llRmhApizYc1tK9DiJwfvXcBg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", + "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "@smithy/util-buffer-from": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/hash-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/hash-stream-node": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz", + "integrity": "sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/invalid-dependency": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-1.0.1.tgz", - "integrity": "sha512-kib63GFlAzRn/wf8M0cRWrZA1cyOy5IvpTkLavCY782DPFMP0EaEeD6VrlNIOvD6ncf7uCJ68HqckhwK1qLT3g==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", + "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/invalid-dependency/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/is-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.0.1.tgz", - "integrity": "sha512-fHSTW70gANnzPYWNDcWkPXpp+QMbHhKozbQm/+Denkhp4gwSiPuAovWZRpJa9sXO+Q4dOnNzYN2max1vTCEroA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/is-array-buffer/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/md5-js": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.3.tgz", + "integrity": "sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q==", + "dev": true, + "dependencies": { + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/md5-js/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/middleware-content-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-1.0.1.tgz", - "integrity": "sha512-vWWigayk5i2cFp9xPX5vdzHyK+P0t/xZ3Ovp4Ss+c8JQ1Hlq2kpJZVWtTKsmdfND5rVo5lu0kD5wgAMUCcmuhw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", + "integrity": "sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw==", "dev": true, "dependencies": { - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-content-length/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/middleware-endpoint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.2.tgz", - "integrity": "sha512-F3CyXgjtDI4quGFkDmVNytt6KMwlzzeMxtopk6Edue4uKdKcMC1vUmoRS5xTbFzKDDp4XwpnEV7FshPaL3eCPw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", "dev": true, "dependencies": { - "@smithy/middleware-serde": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-endpoint/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/middleware-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-1.0.3.tgz", - "integrity": "sha512-ZRsjG8adtxQ456FULPqPFmWtrW44Fq8IgdQvQB+rC2RSho3OUzS+TiEIwb5Zs6rf2IoewITKtfdtsUZcxXO0ng==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz", + "integrity": "sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ==", "dev": true, "dependencies": { - "@smithy/protocol-http": "^1.1.0", - "@smithy/service-error-classification": "^1.0.2", - "@smithy/types": "^1.1.0", - "@smithy/util-middleware": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "tslib": "^2.5.0", - "uuid": "^8.3.2" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-retry/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@smithy/middleware-serde": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-1.0.1.tgz", - "integrity": "sha512-bn5lWk8UUeXFCQfkrNErz5SbeNd+2hgYegHMLsOLPt4URDIsyREar6wMsdsR+8UCdgR5s8udG3Zalgc7puizIQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-serde/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/middleware-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-1.0.1.tgz", - "integrity": "sha512-T6+gsAO1JYamOJqmORCrByDeQ/NB+ggjHb33UDOgdX4xIjXz/FB/3UqHgQu6PL1cSFrK+i4oteDIwqARDs/Szw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/middleware-stack/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/node-config-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-1.0.1.tgz", - "integrity": "sha512-FRxifH/J2SgOaVLihIqBFuGhiHR/NfzbZYp5nYO7BGgT/gc/f9nAuuRJcEy/hwO3aI6ThyG5apH4tGec6A2sCw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", "dev": true, "dependencies": { - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/node-config-provider/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/node-http-handler": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.2.tgz", - "integrity": "sha512-PzPrGRSt3kNuruLCeR4ffJp57ZLVnIukMXVL3Ppr65ZoxiE+HBsOVAa/Z/T+4HzjCM6RaXnnmB8YKfsDjlb0iA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", "dev": true, "dependencies": { - "@smithy/abort-controller": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/querystring-builder": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/node-http-handler/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/property-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-1.0.1.tgz", - "integrity": "sha512-3EG/61Ls1MrgEaafpltXBJHSqFPqmTzEX7QKO7lOEHuYGmGYzZ08t1SsTgd1vM74z0IihoZyGPynZ7WmXKvTeg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/property-provider/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/protocol-http": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.1.0.tgz", - "integrity": "sha512-H5y/kZOqfJSqRkwtcAoVbqONmhdXwSgYNJ1Glk5Ry8qlhVVy5qUzD9EklaCH8/XLnoCsLO/F/Giee8MIvaBRkg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/protocol-http/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/querystring-builder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.0.1.tgz", - "integrity": "sha512-J5Tzkw1PMtu01h6wl+tlN5vsyROmS6/z5lEfNlLo/L4ELHeVkQ4Q0PEIjDddPLfjVLCm8biQTESE5GCMixSRNQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "@smithy/util-uri-escape": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/querystring-builder/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/querystring-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-1.0.1.tgz", - "integrity": "sha512-zauxdMc3cwxoLitI5DZqH7xN6Fk0mwRxrUMAETbav2j6Se2U0UGak/55rZcDg2yGzOURaLYi5iOm1gHr98P+Bw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/querystring-parser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/service-error-classification": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-1.0.2.tgz", - "integrity": "sha512-Q5CCuzYL5FGo6Rr/O+lZxXHm2hrRgbmMn8MgyjqZUWZg20COg20DuNtIbho2iht6CoB7jOpmpBqhWizLlzUZgg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", "dev": true, + "dependencies": { + "@smithy/types": "^3.3.0" + }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.0.1.tgz", - "integrity": "sha512-EztziuIPoNronENGqh+MWVKJErA4rJpaPzJCPukzBeEoG2USka0/q4B5Mr/1zszOnrb49fPNh4u3u5LfiH7QzA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", "dev": true, "dependencies": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/shared-ini-file-loader/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/signature-v4": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.0.1.tgz", - "integrity": "sha512-2D69je14ou1vBTnAQeysSK4QVMm0j3WHS3MDg/DnHnFFcXRCzVl/xAARO7POD8+fpi4tMFPs8Z4hzo1Zw40L0Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.0.tgz", + "integrity": "sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag==", "dev": true, "dependencies": { - "@smithy/eventstream-codec": "^1.0.1", - "@smithy/is-array-buffer": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-hex-encoding": "^1.0.1", - "@smithy/util-middleware": "^1.0.1", - "@smithy/util-uri-escape": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/signature-v4/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/smithy-client": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-1.0.3.tgz", - "integrity": "sha512-Wh1mNP/1yUZK0uYkgCQ6NMxpBT3Fmc45TMdUfOlH1xD2zGYL7U4yDHFOhEZdi/suyjaelFobXB2p9pPIw6LjRQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.2.0.tgz", + "integrity": "sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw==", "dev": true, "dependencies": { - "@smithy/middleware-stack": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-stream": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/smithy-client/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.0.tgz", - "integrity": "sha512-KzmvisMmuwD2jZXuC9e65JrgsZM97y5NpDU7g347oB+Q+xQLU6hQZ5zFNNbEfwwOJHoOvEVTna+dk1h/lW7alw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/types/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/url-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-1.0.1.tgz", - "integrity": "sha512-33vWEtE6HzmwjEcEb4I58XMLRAchwPS93YhfDyXAXr1jwDCzfXmMayQwwpyW847rpWj0XJimxqia8q0z+k/ybw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", "dev": true, "dependencies": { - "@smithy/querystring-parser": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" } }, "node_modules/@smithy/url-parser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-base64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-1.0.1.tgz", - "integrity": "sha512-rJcpRi/yUi6TyCEkjdTH86/ExBuKlfctEXhG9/4gMJ3/cnPcHJJnr0mQ9evSEO+3DbpT/Nxq90bcTBdTIAmCig==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", "dev": true, "dependencies": { - "@smithy/util-buffer-from": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-base64/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-body-length-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-1.0.1.tgz", - "integrity": "sha512-Pdp744fmF7E1NWoSb7256Anhm8eYoCubvosdMwXzOnHuPRVbDa15pKUz2027K3+jrfGpXo1r+MnDerajME1Osw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" } }, "node_modules/@smithy/util-body-length-browser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-body-length-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-1.0.1.tgz", - "integrity": "sha512-4PIHjDFwG07SNensAiVq/CJmubEVuwclWSYOTNtzBNTvxOeGLznvygkGYgPzS3erByT8C4S9JvnLYgtrsVV3nQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-body-length-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-buffer-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.0.1.tgz", - "integrity": "sha512-363N7Wq0ceUgE5lLe6kaR6GlJs2/m4r9V6bRMfIszb6P1FZbbRRM2FQYUWWPFSsRymm9mJL18b3fjiVsIvhDGg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", "dev": true, "dependencies": { - "@smithy/is-array-buffer": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-buffer-from/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-config-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-1.0.1.tgz", - "integrity": "sha512-4Qy38Oy5/q43MpTwCLV1P+7NeaOp4W2etQDxMjgEeRlOyGGNlgttn0syi4g2rVSukFVqQ6FbeRs5xbnFmS6kaQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-config-provider/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-1.0.1.tgz", - "integrity": "sha512-/9ObwNch4Z/NJYfkO4AvqBWku60Ju+c2Ck32toPOLmWe/V6eI9FLn8C1abri+GxDRCkLIqvkaWU1lgZ3nWZIIw==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz", + "integrity": "sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg==", "dev": true, "dependencies": { - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@smithy/util-defaults-mode-browser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-1.0.1.tgz", - "integrity": "sha512-XQM3KvqRLgv7bwAzVkXTITkOmcOINoG9icJiGT8FA0zV35lY5UvyIsg5kHw01xigQS8ufa/33AwG3ZoXip+V5g==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz", + "integrity": "sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A==", "dev": true, "dependencies": { - "@smithy/config-resolver": "^1.0.1", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/config-resolver": "^3.0.5", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@smithy/util-defaults-mode-node/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "node_modules/@smithy/util-endpoints": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz", + "integrity": "sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg==", + "dev": true, + "dependencies": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-endpoints/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-hex-encoding": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.0.1.tgz", - "integrity": "sha512-FPTtMz/t02/rbfq5Pdll/TWUYP+GVFLCQNr+DgifrLzVRU0g8rdRjyFpDh8nPTdkDDusTTo9P1bepAYj68s0eA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-hex-encoding/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-middleware": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.0.1.tgz", - "integrity": "sha512-u9akN3Zmbr0vZH4F+2iehG7cFg+3fvDfnvS/hhsXH4UHuhqiQ+ADefibnLzPoz1pooY7rvwaQ/TVHyJmZHdLdQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-middleware/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-1.0.3.tgz", - "integrity": "sha512-gYQnZDD8I2XJFspVwUISyukjPWVikTzKR0IdG8hCWYPTpeULFl1o6yzXlT5SL63TBkuEYl0R1/93cdNtMiNnoA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", "dev": true, "dependencies": { - "@smithy/service-error-classification": "^1.0.2", - "tslib": "^2.5.0" + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-retry/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-1.0.1.tgz", - "integrity": "sha512-4aBCIz35aZAnt2Rbq341KrnUzGhWv2/Zu8HouJqYLvSWCzlrvsNCGlXP4e70Kjzcw8hSuuCNtdUICwQ5qUWLxg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", "dev": true, "dependencies": { - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/types": "^1.1.0", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-buffer-from": "^1.0.1", - "@smithy/util-hex-encoding": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-stream/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-uri-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.0.1.tgz", - "integrity": "sha512-IJUrRnXKEIc+PKnU1XzTsIENVR+60jUDPBP3iWX/EvuuT3Xfob47x1FGUe2c3yMXNuU6ax8VDk27hL5LKNoehQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-uri-escape/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-utf8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.0.1.tgz", - "integrity": "sha512-iX6XHpjh4DFEUIBSKp2tjy3pYnLQMsJ62zYi1BVAC0kobE6p8AVpiZnxsU3ZkgQatAsUaEspFHUZ7CL7oSqaPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dev": true, "dependencies": { - "@smithy/util-buffer-from": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-utf8/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@smithy/util-waiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-1.0.1.tgz", - "integrity": "sha512-dsn8O0s3pFIgxFzySLe1dv0w4tEQizEP6UqbgZ4r/Kar4n8pSdrPi6DJg8BzXwkwEIZpMtV4/nhSeGZ7HksDXA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.1.2.tgz", + "integrity": "sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw==", "dev": true, "dependencies": { - "@smithy/abort-controller": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^3.1.1", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@smithy/util-waiter/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true }, "node_modules/@socket.io/component-emitter": { @@ -7818,18 +8060,18 @@ "dev": true }, "node_modules/fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", "dev": true, "funding": [ - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - }, { "type": "github", "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" } ], "dependencies": { @@ -9954,12 +10196,12 @@ } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -13455,9 +13697,9 @@ "dev": true }, "node_modules/typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -14174,1013 +14416,1065 @@ } }, "@aws-crypto/crc32": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", - "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz", + "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==", "dev": true, "requires": { - "@aws-crypto/util": "^3.0.0", + "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "@aws-crypto/crc32c": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", - "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", - "dev": true, - "requires": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "@aws-crypto/ie11-detection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", - "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", - "dev": true, - "requires": { - "tslib": "^1.11.1" - } - }, - "@aws-crypto/sha1-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", - "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", - "dev": true, - "requires": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "@aws-crypto/sha256-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", - "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", - "dev": true, - "requires": { - "@aws-crypto/ie11-detection": "^3.0.0", - "@aws-crypto/sha256-js": "^3.0.0", - "@aws-crypto/supports-web-crypto": "^3.0.0", - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-locate-window": "^3.0.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "@aws-crypto/sha256-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", - "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", - "dev": true, - "requires": { - "@aws-crypto/util": "^3.0.0", - "@aws-sdk/types": "^3.222.0", - "tslib": "^1.11.1" - } - }, - "@aws-crypto/supports-web-crypto": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", - "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", - "dev": true, - "requires": { - "tslib": "^1.11.1" - } - }, - "@aws-crypto/util": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", - "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", - "dev": true, - "requires": { - "@aws-sdk/types": "^3.222.0", - "@aws-sdk/util-utf8-browser": "^3.0.0", - "tslib": "^1.11.1" - } - }, - "@aws-sdk/chunked-blob-reader": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/chunked-blob-reader/-/chunked-blob-reader-3.310.0.tgz", - "integrity": "sha512-CrJS3exo4mWaLnWxfCH+w88Ou0IcAZSIkk4QbmxiHl/5Dq705OLoxf4385MVyExpqpeVJYOYQ2WaD8i/pQZ2fg==", - "dev": true, - "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-crypto/crc32c": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz", + "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==", + "dev": true, + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-crypto/sha1-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz", + "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==", + "dev": true, + "requires": { + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-crypto/sha256-browser": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dev": true, + "requires": { + "@aws-crypto/sha256-js": "^5.2.0", + "@aws-crypto/supports-web-crypto": "^5.2.0", + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-crypto/sha256-js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz", + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dev": true, + "requires": { + "@aws-crypto/util": "^5.2.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-crypto/supports-web-crypto": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz", + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-crypto/util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz", + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dev": true, + "requires": { + "@aws-sdk/types": "^3.222.0", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "@smithy/is-array-buffer": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz", + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + } + }, + "@smithy/util-buffer-from": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz", + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dev": true, + "requires": { + "@smithy/is-array-buffer": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "@smithy/util-utf8": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz", + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dev": true, + "requires": { + "@smithy/util-buffer-from": "^2.2.0", + "tslib": "^2.6.2" + } + }, + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/client-s3": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.363.0.tgz", - "integrity": "sha512-LNnfg/t8wG5Fqj6l+PSV/t+IXDq9r3Kj9jEHn84513+p7bewXYSSreSpmLjG8OcKuMfHc9EJGNQ3DkMyFaLoWg==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.637.0.tgz", + "integrity": "sha512-y6UC94fsMvhKbf0dzfnjVP1HePeGjplfcYfilZU1COIJLyTkMcUv4XcT4I407CGIrvgEafONHkiC09ygqUauNA==", "dev": true, "requires": { - "@aws-crypto/sha1-browser": "3.0.0", - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.363.0", - "@aws-sdk/credential-provider-node": "3.363.0", - "@aws-sdk/hash-blob-browser": "3.357.0", - "@aws-sdk/hash-stream-node": "3.357.0", - "@aws-sdk/md5-js": "3.357.0", - "@aws-sdk/middleware-bucket-endpoint": "3.363.0", - "@aws-sdk/middleware-expect-continue": "3.363.0", - "@aws-sdk/middleware-flexible-checksums": "3.363.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-location-constraint": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-sdk-s3": "3.363.0", - "@aws-sdk/middleware-signing": "3.363.0", - "@aws-sdk/middleware-ssec": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/signature-v4-multi-region": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@aws-sdk/xml-builder": "3.310.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/eventstream-serde-browser": "^1.0.1", - "@smithy/eventstream-serde-config-resolver": "^1.0.1", - "@smithy/eventstream-serde-node": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.2", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.0.1", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.0.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.2", - "@smithy/util-stream": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "@smithy/util-waiter": "^1.0.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "@aws-crypto/sha1-browser": "5.2.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.637.0", + "@aws-sdk/client-sts": "3.637.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.637.0", + "@aws-sdk/middleware-bucket-endpoint": "3.620.0", + "@aws-sdk/middleware-expect-continue": "3.620.0", + "@aws-sdk/middleware-flexible-checksums": "3.620.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-location-constraint": "3.609.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-sdk-s3": "3.635.0", + "@aws-sdk/middleware-ssec": "3.609.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/signature-v4-multi-region": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@aws-sdk/xml-builder": "3.609.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/eventstream-serde-browser": "^3.0.6", + "@smithy/eventstream-serde-config-resolver": "^3.0.3", + "@smithy/eventstream-serde-node": "^3.0.5", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-blob-browser": "^3.1.2", + "@smithy/hash-node": "^3.0.3", + "@smithy/hash-stream-node": "^3.1.2", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/md5-js": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-stream": "^3.1.3", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.1.2", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/client-sso": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.363.0.tgz", - "integrity": "sha512-PZ+HfKSgS4hlMnJzG+Ev8/mgHd/b/ETlJWPSWjC/f2NwVoBQkBnqHjdyEx7QjF6nksJozcVh5Q+kkYLKc/QwBQ==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.637.0.tgz", + "integrity": "sha512-+KjLvgX5yJYROWo3TQuwBJlHCY0zz9PsLuEolmXQn0BVK1L/m9GteZHtd+rEdAoDGBpE0Xqjy1oz5+SmtsaRUw==", "dev": true, "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.2", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.0.1", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.0.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.2", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/client-sso-oidc": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.363.0.tgz", - "integrity": "sha512-V3Ebiq/zNtDS/O92HUWGBa7MY59RYSsqWd+E0XrXv6VYTA00RlMTbNcseivNgp2UghOgB9a20Nkz6EqAeIN+RQ==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.637.0.tgz", + "integrity": "sha512-27bHALN6Qb6m6KZmPvRieJ/QRlj1lyac/GT2Rn5kJpre8Mpp+yxrtvp3h9PjNBty4lCeFEENfY4dGNSozBuBcw==", "dev": true, "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.2", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/protocol-http": "^1.0.1", - "@smithy/smithy-client": "^1.0.3", - "@smithy/types": "^1.0.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.2", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.637.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/client-sts": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.363.0.tgz", - "integrity": "sha512-0jj14WvBPJQ8xr72cL0mhlmQ90tF0O0wqXwSbtog6PsC8+KDE6Yf+WsxsumyI8E5O8u3eYijBL+KdqG07F/y/w==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.637.0.tgz", + "integrity": "sha512-xUi7x4qDubtA8QREtlblPuAcn91GS/09YVEY/RwU7xCY0aqGuFwgszAANlha4OUIqva8oVj2WO4gJuG+iaSnhw==", "dev": true, "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/credential-provider-node": "3.363.0", - "@aws-sdk/middleware-host-header": "3.363.0", - "@aws-sdk/middleware-logger": "3.363.0", - "@aws-sdk/middleware-recursion-detection": "3.363.0", - "@aws-sdk/middleware-sdk-sts": "3.363.0", - "@aws-sdk/middleware-signing": "3.363.0", - "@aws-sdk/middleware-user-agent": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@aws-sdk/util-user-agent-browser": "3.363.0", - "@aws-sdk/util-user-agent-node": "3.363.0", - "@smithy/config-resolver": "^1.0.1", - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/hash-node": "^1.0.1", - "@smithy/invalid-dependency": "^1.0.1", - "@smithy/middleware-content-length": "^1.0.1", - "@smithy/middleware-endpoint": "^1.0.1", - "@smithy/middleware-retry": "^1.0.1", - "@smithy/middleware-serde": "^1.0.1", - "@smithy/middleware-stack": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/node-http-handler": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/smithy-client": "^1.0.2", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-body-length-browser": "^1.0.1", - "@smithy/util-body-length-node": "^1.0.1", - "@smithy/util-defaults-mode-browser": "^1.0.1", - "@smithy/util-defaults-mode-node": "^1.0.1", - "@smithy/util-retry": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "fast-xml-parser": "4.2.5", - "tslib": "^2.5.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/client-sso-oidc": "3.637.0", + "@aws-sdk/core": "3.635.0", + "@aws-sdk/credential-provider-node": "3.637.0", + "@aws-sdk/middleware-host-header": "3.620.0", + "@aws-sdk/middleware-logger": "3.609.0", + "@aws-sdk/middleware-recursion-detection": "3.620.0", + "@aws-sdk/middleware-user-agent": "3.637.0", + "@aws-sdk/region-config-resolver": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@aws-sdk/util-user-agent-browser": "3.609.0", + "@aws-sdk/util-user-agent-node": "3.614.0", + "@smithy/config-resolver": "^3.0.5", + "@smithy/core": "^2.4.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/hash-node": "^3.0.3", + "@smithy/invalid-dependency": "^3.0.3", + "@smithy/middleware-content-length": "^3.0.5", + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.15", + "@smithy/util-defaults-mode-node": "^3.0.15", + "@smithy/util-endpoints": "^2.0.5", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-sdk/core": { + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.635.0.tgz", + "integrity": "sha512-i1x/E/sgA+liUE1XJ7rj1dhyXpAKO1UKFUcTTHXok2ARjWTvszHnSXMOsB77aPbmn0fUp1JTx2kHUAZ1LVt5Bg==", + "dev": true, + "requires": { + "@smithy/core": "^2.4.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "fast-xml-parser": "4.4.1", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/credential-provider-env": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.363.0.tgz", - "integrity": "sha512-VAQ3zITT2Q0acht0HezouYnMFKZ2vIOa20X4zQA3WI0HfaP4D6ga6KaenbDcb/4VFiqfqiRHfdyXHP0ThcDRMA==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", + "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-sdk/credential-provider-http": { + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.635.0.tgz", + "integrity": "sha512-iJyRgEjOCQlBMXqtwPLIKYc7Bsc6nqjrZybdMDenPDa+kmLg7xh8LxHsu9088e+2/wtLicE34FsJJIfzu3L82g==", + "dev": true, + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/credential-provider-ini": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.363.0.tgz", - "integrity": "sha512-ZYN+INoqyX5FVC3rqUxB6O8nOWkr0gHRRBm1suoOlmuFJ/WSlW/uUGthRBY5x1AQQnBF8cpdlxZzGHd41lFVNw==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.637.0.tgz", + "integrity": "sha512-h+PFCWfZ0Q3Dx84SppET/TFpcQHmxFW8/oV9ArEvMilw4EBN+IlxgbL0CnHwjHW64szcmrM0mbebjEfHf4FXmw==", "dev": true, "requires": { - "@aws-sdk/credential-provider-env": "3.363.0", - "@aws-sdk/credential-provider-process": "3.363.0", - "@aws-sdk/credential-provider-sso": "3.363.0", - "@aws-sdk/credential-provider-web-identity": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.635.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.637.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/credential-provider-node": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.363.0.tgz", - "integrity": "sha512-C1qXFIN2yMxD6pGgug0vR1UhScOki6VqdzuBHzXZAGu7MOjvgHNdscEcb3CpWnITHaPL2ztkiw75T1sZ7oIgQg==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.637.0.tgz", + "integrity": "sha512-yoEhoxJJfs7sPVQ6Is939BDQJZpZCoUgKr/ySse4YKOZ24t4VqgHA6+wV7rYh+7IW24Rd91UTvEzSuHYTlxlNA==", "dev": true, "requires": { - "@aws-sdk/credential-provider-env": "3.363.0", - "@aws-sdk/credential-provider-ini": "3.363.0", - "@aws-sdk/credential-provider-process": "3.363.0", - "@aws-sdk/credential-provider-sso": "3.363.0", - "@aws-sdk/credential-provider-web-identity": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/credential-provider-env": "3.620.1", + "@aws-sdk/credential-provider-http": "3.635.0", + "@aws-sdk/credential-provider-ini": "3.637.0", + "@aws-sdk/credential-provider-process": "3.620.1", + "@aws-sdk/credential-provider-sso": "3.637.0", + "@aws-sdk/credential-provider-web-identity": "3.621.0", + "@aws-sdk/types": "3.609.0", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/credential-provider-process": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.363.0.tgz", - "integrity": "sha512-fOKAINU7Rtj2T8pP13GdCt+u0Ml3gYynp8ki+1jMZIQ+Ju/MdDOqZpKMFKicMn3Z1ttUOgqr+grUdus6z8ceBQ==", + "version": "3.620.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", + "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/credential-provider-sso": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.363.0.tgz", - "integrity": "sha512-5RUZ5oM0lwZSo3EehT0dXggOjgtxFogpT3cZvoLGtIwrPBvm8jOQPXQUlaqCj10ThF1sYltEyukz/ovtDwYGew==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.637.0.tgz", + "integrity": "sha512-Mvz+h+e62/tl+dVikLafhv+qkZJ9RUb8l2YN/LeKMWkxQylPT83CPk9aimVhCV89zth1zpREArl97+3xsfgQvA==", "dev": true, "requires": { - "@aws-sdk/client-sso": "3.363.0", - "@aws-sdk/token-providers": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/client-sso": "3.637.0", + "@aws-sdk/token-providers": "3.614.0", + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/credential-provider-web-identity": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.363.0.tgz", - "integrity": "sha512-Z6w7fjgy79pAax580wdixbStQw10xfyZ+hOYLcPudoYFKjoNx0NQBejg5SwBzCF/HQL23Ksm9kDfbXDX9fkPhA==", + "version": "3.621.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", + "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/hash-blob-browser": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-blob-browser/-/hash-blob-browser-3.357.0.tgz", - "integrity": "sha512-RDd6UgrGHDmleTnXM9LRSSVa69euSAG2mlNhZMEDWk3OFseXVYqBDaqroVbQ01rM2UAe8MeBFchlV9OmxuVgvw==", - "dev": true, - "requires": { - "@aws-sdk/chunked-blob-reader": "3.310.0", - "@aws-sdk/types": "3.357.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/hash-stream-node": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-stream-node/-/hash-stream-node-3.357.0.tgz", - "integrity": "sha512-KZjN1VAw1KHNp+xKVOWBGS+MpaYQTjZFD5f+7QQqW4TfbAkFFwIAEYIHq5Q8Gw+jVh0h61OrV/LyW3J2PVzc+w==", - "dev": true, - "requires": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-utf8": "3.310.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/is-array-buffer": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz", - "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==", - "dev": true, - "requires": { - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/md5-js": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/md5-js/-/md5-js-3.357.0.tgz", - "integrity": "sha512-to42sFAL7KgV/X9X40LLfEaNMHMGQL6/7mPMVCL/W2BZf3zw5OTl3lAaNyjXA+gO5Uo4lFEiQKAQVKNbr8b8Nw==", - "dev": true, - "requires": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-utf8": "3.310.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-bucket-endpoint": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.363.0.tgz", - "integrity": "sha512-kR8+0X50zslpzRW29q4JbpPMadE1z39ZfGwPaBLKpoWvSGt4x+75FaoK71TH7urPPoFyD2Y+XKGA6YRYTUNHSQ==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.620.0.tgz", + "integrity": "sha512-eGLL0W6L3HDb3OACyetZYOWpHJ+gLo0TehQKeQyy2G8vTYXqNTeqYhuI6up9HVjBzU9eQiULVQETmgQs7TFaRg==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-arn-parser": "3.310.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "@smithy/util-config-provider": "^1.0.1", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-expect-continue": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.363.0.tgz", - "integrity": "sha512-I88xneZp6jRwySmIl9uI7eZCcTsqRVnTDfUr1JiXt7zonqNNm80PVYMs6pwaw7t97ec1AQJcsONjuXZyCMnu5g==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.620.0.tgz", + "integrity": "sha512-QXeRFMLfyQ31nAHLbiTLtk0oHzG9QLMaof5jIfqcUwnOkO8YnQdeqzakrg1Alpy/VQ7aqzIi8qypkBe2KXZz0A==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-flexible-checksums": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.363.0.tgz", - "integrity": "sha512-FBYmrMRX01uNximNN0WLgpf97GN4xNTLaKsDlkjYRWKJ+J97ICkvLG0FcSu7+SNCpCdJJBeQ5tRVOPVpUu6nmA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.620.0.tgz", + "integrity": "sha512-ftz+NW7qka2sVuwnnO1IzBku5ccP+s5qZGeRTPgrKB7OzRW85gthvIo1vQR2w+OwHFk7WJbbhhWwbCbktnP4UA==", "dev": true, "requires": { - "@aws-crypto/crc32": "3.0.0", - "@aws-crypto/crc32c": "3.0.0", - "@aws-sdk/types": "3.357.0", - "@smithy/is-array-buffer": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/crc32": "5.2.0", + "@aws-crypto/crc32c": "5.2.0", + "@aws-sdk/types": "3.609.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-host-header": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.363.0.tgz", - "integrity": "sha512-FobpclDCf5Y1ueyJDmb9MqguAdPssNMlnqWQpujhYVABq69KHu73fSCWSauFPUrw7YOpV8kG1uagDF0POSxHzA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", + "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-location-constraint": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.363.0.tgz", - "integrity": "sha512-piNzpNNI/fChSGOZxcq/2msN2qFUSEAbhqs91zbcpv8CEPekVLc4W9laXCG764BEMyfG97ZU8MtzwHeMhELhBA==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz", + "integrity": "sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-logger": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.363.0.tgz", - "integrity": "sha512-SSGgthScYnFGTOw8EzbkvquqweFmvn7uJihkpFekbtBNGC/jGOGO+8ziHjTQ8t/iI/YKubEwv+LMi0f77HKSEg==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", + "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-recursion-detection": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.363.0.tgz", - "integrity": "sha512-MWD/57QgI/N7fG8rtzDTUdSqNpYohQfgj9XCFAoVeI/bU4usrkOrew43L4smJG4XrDxlNT8lSJlDtd64tuiUZA==", + "version": "3.620.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", + "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-sdk-s3": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.363.0.tgz", - "integrity": "sha512-npC8vLCero+vULizrK0QPjNanWbgH4A/2Llc1nO8N005uvUe7co6WglILF2W3guZrFk/0uGEdX67OnLxUD97pw==", + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.635.0.tgz", + "integrity": "sha512-RLdYJPEV4JL/7NBoFUs7VlP90X++5FlJdxHz0DzCjmiD3qCviKy+Cym3qg1gBgHwucs5XisuClxDrGokhAdTQw==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-arn-parser": "3.310.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/core": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/core": "^2.4.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-stream": "^3.1.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/middleware-sdk-sts": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.363.0.tgz", - "integrity": "sha512-1yy2Ac50FO8BrODaw5bPWvVrRhaVLqXTFH6iHB+dJLPUkwtY5zLM3Mp+9Ilm7kME+r7oIB1wuO6ZB1Lf4ZszIw==", - "dev": true, - "requires": { - "@aws-sdk/middleware-signing": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/middleware-signing": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.363.0.tgz", - "integrity": "sha512-/7qia715pt9JKYIPDGu22WmdZxD8cfF/5xB+1kmILg7ZtjO0pPuTaCNJ7xiIuFd7Dn7JXp5lop08anX/GOhNRQ==", - "dev": true, - "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/signature-v4": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-ssec": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.363.0.tgz", - "integrity": "sha512-pN+QN1rMShYpJnTJSCIYnNRhD0S8xSZsTn6ThgcO559Xiwz5LMHFOfOXUCEyxtbVW5kMHLUh3w101AMUKae99A==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz", + "integrity": "sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/middleware-user-agent": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.363.0.tgz", - "integrity": "sha512-ri8YaQvXP6odteVTMfxPqFR26Q0h9ejtqhUDv47P34FaKXedEM4nC6ix6o+5FEYj6l8syGyktftZ5O70NoEhug==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.637.0.tgz", + "integrity": "sha512-EYo0NE9/da/OY8STDsK2LvM4kNa79DBsf4YVtaG4P5pZ615IeFsD8xOHZeuJmUrSMlVQ8ywPRX7WMucUybsKug==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@aws-sdk/util-endpoints": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@aws-sdk/util-endpoints": "3.637.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@aws-sdk/region-config-resolver": { + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", + "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", + "dev": true, + "requires": { + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/signature-v4-multi-region": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.363.0.tgz", - "integrity": "sha512-iWamQSpaBKg88LKuiUq8xO/7iyxJ+ORkA3qDhAwUqyTJOg87ma47yFf4ycCKqINnflc3AIGLGzBHnkBc4cMF5g==", + "version": "3.635.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.635.0.tgz", + "integrity": "sha512-J6QY4/invOkpogCHjSaDON1hF03viPpOnsrzVuCvJMmclS/iG62R4EY0wq1alYll0YmSdmKlpJwHMWwGtqK63Q==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/protocol-http": "^1.1.0", - "@smithy/signature-v4": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/middleware-sdk-s3": "3.635.0", + "@aws-sdk/types": "3.609.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/signature-v4": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/token-providers": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.363.0.tgz", - "integrity": "sha512-6+0aJ1zugNgsMmhTtW2LBWxOVSaXCUk2q3xyTchSXkNzallYaRiZMRkieW+pKNntnu0g5H1T0zyfCO0tbXwxEA==", + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", + "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", "dev": true, "requires": { - "@aws-sdk/client-sso-oidc": "3.363.0", - "@aws-sdk/types": "3.357.0", - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/types": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.357.0.tgz", - "integrity": "sha512-/riCRaXg3p71BeWnShrai0y0QTdXcouPSM0Cn1olZbzTf7s71aLEewrc96qFrL70XhY4XvnxMpqQh+r43XIL3g==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.609.0.tgz", + "integrity": "sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q==", "dev": true, "requires": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/util-arn-parser": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz", - "integrity": "sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==", + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/util-buffer-from": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz", - "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==", - "dev": true, - "requires": { - "@aws-sdk/is-array-buffer": "3.310.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/util-endpoints": { - "version": "3.357.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.357.0.tgz", - "integrity": "sha512-XHKyS5JClT9su9hDif715jpZiWHQF9gKZXER8tW0gOizU3R9cyWc9EsJ2BRhFNhi7nt/JF/CLUEc5qDx3ETbUw==", + "version": "3.637.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.637.0.tgz", + "integrity": "sha512-pAqOKUHeVWHEXXDIp/qoMk/6jyxIb6GGjnK1/f8dKHtKIEs4tKsnnL563gceEvdad53OPXIt86uoevCcCzmBnw==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", + "@smithy/util-endpoints": "^2.0.5", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/util-locate-window": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", - "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/util-user-agent-browser": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.363.0.tgz", - "integrity": "sha512-fk9ymBUIYbxiGm99Cn+kAAXmvMCWTf/cHAcB79oCXV4ELXdPa9lN5xQhZRFNxLUeXG4OAMEuCAUUuZEj8Fnc1Q==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", + "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/types": "^1.1.0", + "@aws-sdk/types": "3.609.0", + "@smithy/types": "^3.3.0", "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/util-user-agent-node": { - "version": "3.363.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.363.0.tgz", - "integrity": "sha512-Fli/dvgGA9hdnQUrYb1//wNSFlK2jAfdJcfNXA6SeBYzSeH5pVGYF4kXF0FCdnMA3Fef+Zn1zAP/hw9v8VJHWQ==", + "version": "3.614.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", + "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", "dev": true, "requires": { - "@aws-sdk/types": "3.357.0", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@aws-sdk/types": "3.609.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/util-utf8": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz", - "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==", - "dev": true, - "requires": { - "@aws-sdk/util-buffer-from": "3.310.0", - "tslib": "^2.5.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", - "dev": true - } - } - }, - "@aws-sdk/util-utf8-browser": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", - "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", - "dev": true, - "requires": { - "tslib": "^2.3.1" - }, - "dependencies": { - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@aws-sdk/xml-builder": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz", - "integrity": "sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==", + "version": "3.609.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz", + "integrity": "sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA==", "dev": true, "requires": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } @@ -16350,806 +16644,966 @@ "integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==" }, "@smithy/abort-controller": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.1.tgz", - "integrity": "sha512-An6irzp9NCji2JtJHhrEFlDbxLwHd6c6Y9fq3ZeomyUR8BIXlGXVTxsemUSZVVgOq3166iYbYs/CrPAmgRSFLw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", + "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "dev": true, + "requires": { + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dev": true, + "requires": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/config-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-1.0.1.tgz", - "integrity": "sha512-quj0xUiEVG/UHfY82EtthR/+S5/17p3IxXArC3NFSNqryMobWbG9oWgJy2s2cgUSVZLzxevjKKvxrilK7JEDaA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", + "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "@smithy/util-config-provider": "^1.0.1", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/core": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.0.tgz", + "integrity": "sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w==", + "dev": true, + "requires": { + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-retry": "^3.0.15", + "@smithy/middleware-serde": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/credential-provider-imds": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-1.0.1.tgz", - "integrity": "sha512-hkRJoxVCh4CEt1zYOBElE+G/MV6lyx3g68hSJpesM4pwMT/bzEVo5E5XzXY+6dVq8yszeatWKbFuqCCBQte8tg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz", + "integrity": "sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA==", "dev": true, "requires": { - "@smithy/node-config-provider": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/eventstream-codec": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.0.1.tgz", - "integrity": "sha512-cpcTXQEOEs2wEvIyxW/iTHJ2m0RVqoEOTjjWEXD6SY8Gcs3FCFP6E8MXadC098tdH5ctMIUXc8POXyMpxzGnjw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz", + "integrity": "sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==", "dev": true, "requires": { - "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^1.1.0", - "@smithy/util-hex-encoding": "^1.0.1", - "tslib": "^2.5.0" + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/eventstream-serde-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-1.0.1.tgz", - "integrity": "sha512-oc8vxe+AU2RzvXH/Ehh0TzM/Nsw3I3ywu7V3qaCzqdkBIntAwK9JGZqcSDsqTK0WxZKBRgFIEwopcuZ2slVnFQ==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.6.tgz", + "integrity": "sha512-2hM54UWQUOrki4BtsUI1WzmD13/SeaqT/AB3EUJKbcver/WgKNaiJ5y5F5XXuVe6UekffVzuUDrBZVAA3AWRpQ==", "dev": true, "requires": { - "@smithy/eventstream-serde-universal": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/eventstream-serde-universal": "^3.0.5", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/eventstream-serde-config-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-1.0.1.tgz", - "integrity": "sha512-TJwaXima0djnNY819utO1j93qZHaheFH1bhHxBkMrImtEOuXY48Tjma/L2m8swkIq8dy8jFC9hrYOkD0eYHkFA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz", + "integrity": "sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/eventstream-serde-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-1.0.1.tgz", - "integrity": "sha512-JEj8w7IRs4l+kcwKxbv3pNuu8n7ORC4pMFrIOrM4rERzrRnI7vMNTRzvAPGYA53rqm/Y9tBA9dw4C+H6hLXcsA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.5.tgz", + "integrity": "sha512-+upXvnHNyZP095s11jF5dhGw/Ihzqwl5G+/KtMnoQOpdfC3B5HYCcDVG9EmgkhJMXJlM64PyN5gjJl0uXFQehQ==", "dev": true, "requires": { - "@smithy/eventstream-serde-universal": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/eventstream-serde-universal": "^3.0.5", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/eventstream-serde-universal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-1.0.1.tgz", - "integrity": "sha512-c6m9DH7m6D2S93dof4wSxysaGSQdauO20TNcSePzrgHd4rkTnz5pqZ1a7Pt22q2SKf09SvTugq5cV2Sy4r8zHw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.5.tgz", + "integrity": "sha512-5u/nXbyoh1s4QxrvNre9V6vfyoLWuiVvvd5TlZjGThIikc3G+uNiG9uOTCWweSRjv1asdDIWK7nOmN7le4RYHQ==", "dev": true, "requires": { - "@smithy/eventstream-codec": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/eventstream-codec": "^3.1.2", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/fetch-http-handler": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-1.0.1.tgz", - "integrity": "sha512-/e2A8eOMk4FVZBQ0o6uF/ttLtFZcmsK5MIwDu1UE3crM4pCAIP19Ul8U9rdLlHhIu81X4AcJmSw55RDSpVRL/w==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", + "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", "dev": true, "requires": { - "@smithy/protocol-http": "^1.1.0", - "@smithy/querystring-builder": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-base64": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/hash-blob-browser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz", + "integrity": "sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg==", + "dev": true, + "requires": { + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/hash-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.0.1.tgz", - "integrity": "sha512-eCz08BySBcOjVObjbRAS/XMKUGY4ujnuS+GoWeEpzpCSKDnO8/YQ0rStRt4C0llRmhApizYc1tK9DiJwfvXcBg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", + "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "@smithy/util-buffer-from": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/hash-stream-node": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz", + "integrity": "sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g==", + "dev": true, + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/invalid-dependency": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-1.0.1.tgz", - "integrity": "sha512-kib63GFlAzRn/wf8M0cRWrZA1cyOy5IvpTkLavCY782DPFMP0EaEeD6VrlNIOvD6ncf7uCJ68HqckhwK1qLT3g==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", + "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/is-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.0.1.tgz", - "integrity": "sha512-fHSTW70gANnzPYWNDcWkPXpp+QMbHhKozbQm/+Denkhp4gwSiPuAovWZRpJa9sXO+Q4dOnNzYN2max1vTCEroA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/md5-js": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.3.tgz", + "integrity": "sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q==", + "dev": true, + "requires": { + "@smithy/types": "^3.3.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/middleware-content-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-1.0.1.tgz", - "integrity": "sha512-vWWigayk5i2cFp9xPX5vdzHyK+P0t/xZ3Ovp4Ss+c8JQ1Hlq2kpJZVWtTKsmdfND5rVo5lu0kD5wgAMUCcmuhw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", + "integrity": "sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw==", "dev": true, "requires": { - "@smithy/protocol-http": "^1.1.0", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/middleware-endpoint": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.2.tgz", - "integrity": "sha512-F3CyXgjtDI4quGFkDmVNytt6KMwlzzeMxtopk6Edue4uKdKcMC1vUmoRS5xTbFzKDDp4XwpnEV7FshPaL3eCPw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", + "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", "dev": true, "requires": { - "@smithy/middleware-serde": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/url-parser": "^1.0.1", - "@smithy/util-middleware": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/middleware-serde": "^3.0.3", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/url-parser": "^3.0.3", + "@smithy/util-middleware": "^3.0.3", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/middleware-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-1.0.3.tgz", - "integrity": "sha512-ZRsjG8adtxQ456FULPqPFmWtrW44Fq8IgdQvQB+rC2RSho3OUzS+TiEIwb5Zs6rf2IoewITKtfdtsUZcxXO0ng==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz", + "integrity": "sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ==", "dev": true, "requires": { - "@smithy/protocol-http": "^1.1.0", - "@smithy/service-error-classification": "^1.0.2", - "@smithy/types": "^1.1.0", - "@smithy/util-middleware": "^1.0.1", - "@smithy/util-retry": "^1.0.3", - "tslib": "^2.5.0", - "uuid": "^8.3.2" + "@smithy/node-config-provider": "^3.1.4", + "@smithy/protocol-http": "^4.1.0", + "@smithy/service-error-classification": "^3.0.3", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-retry": "^3.0.3", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + }, + "uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", "dev": true } } }, "@smithy/middleware-serde": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-1.0.1.tgz", - "integrity": "sha512-bn5lWk8UUeXFCQfkrNErz5SbeNd+2hgYegHMLsOLPt4URDIsyREar6wMsdsR+8UCdgR5s8udG3Zalgc7puizIQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", + "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/middleware-stack": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-1.0.1.tgz", - "integrity": "sha512-T6+gsAO1JYamOJqmORCrByDeQ/NB+ggjHb33UDOgdX4xIjXz/FB/3UqHgQu6PL1cSFrK+i4oteDIwqARDs/Szw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", + "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", "dev": true, "requires": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/node-config-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-1.0.1.tgz", - "integrity": "sha512-FRxifH/J2SgOaVLihIqBFuGhiHR/NfzbZYp5nYO7BGgT/gc/f9nAuuRJcEy/hwO3aI6ThyG5apH4tGec6A2sCw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", + "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", "dev": true, "requires": { - "@smithy/property-provider": "^1.0.1", - "@smithy/shared-ini-file-loader": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/property-provider": "^3.1.3", + "@smithy/shared-ini-file-loader": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/node-http-handler": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.2.tgz", - "integrity": "sha512-PzPrGRSt3kNuruLCeR4ffJp57ZLVnIukMXVL3Ppr65ZoxiE+HBsOVAa/Z/T+4HzjCM6RaXnnmB8YKfsDjlb0iA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", + "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", "dev": true, "requires": { - "@smithy/abort-controller": "^1.0.1", - "@smithy/protocol-http": "^1.1.0", - "@smithy/querystring-builder": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^3.1.1", + "@smithy/protocol-http": "^4.1.0", + "@smithy/querystring-builder": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/property-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-1.0.1.tgz", - "integrity": "sha512-3EG/61Ls1MrgEaafpltXBJHSqFPqmTzEX7QKO7lOEHuYGmGYzZ08t1SsTgd1vM74z0IihoZyGPynZ7WmXKvTeg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", + "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/protocol-http": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.1.0.tgz", - "integrity": "sha512-H5y/kZOqfJSqRkwtcAoVbqONmhdXwSgYNJ1Glk5Ry8qlhVVy5qUzD9EklaCH8/XLnoCsLO/F/Giee8MIvaBRkg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", + "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/querystring-builder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.0.1.tgz", - "integrity": "sha512-J5Tzkw1PMtu01h6wl+tlN5vsyROmS6/z5lEfNlLo/L4ELHeVkQ4Q0PEIjDddPLfjVLCm8biQTESE5GCMixSRNQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", + "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "@smithy/util-uri-escape": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/querystring-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-1.0.1.tgz", - "integrity": "sha512-zauxdMc3cwxoLitI5DZqH7xN6Fk0mwRxrUMAETbav2j6Se2U0UGak/55rZcDg2yGzOURaLYi5iOm1gHr98P+Bw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", + "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/service-error-classification": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-1.0.2.tgz", - "integrity": "sha512-Q5CCuzYL5FGo6Rr/O+lZxXHm2hrRgbmMn8MgyjqZUWZg20COg20DuNtIbho2iht6CoB7jOpmpBqhWizLlzUZgg==", - "dev": true - }, - "@smithy/shared-ini-file-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.0.1.tgz", - "integrity": "sha512-EztziuIPoNronENGqh+MWVKJErA4rJpaPzJCPukzBeEoG2USka0/q4B5Mr/1zszOnrb49fPNh4u3u5LfiH7QzA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", + "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", "dev": true, "requires": { - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0" + } + }, + "@smithy/shared-ini-file-loader": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", + "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "dev": true, + "requires": { + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/signature-v4": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.0.1.tgz", - "integrity": "sha512-2D69je14ou1vBTnAQeysSK4QVMm0j3WHS3MDg/DnHnFFcXRCzVl/xAARO7POD8+fpi4tMFPs8Z4hzo1Zw40L0Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.0.tgz", + "integrity": "sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag==", "dev": true, "requires": { - "@smithy/eventstream-codec": "^1.0.1", - "@smithy/is-array-buffer": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-hex-encoding": "^1.0.1", - "@smithy/util-middleware": "^1.0.1", - "@smithy/util-uri-escape": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.3", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/smithy-client": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-1.0.3.tgz", - "integrity": "sha512-Wh1mNP/1yUZK0uYkgCQ6NMxpBT3Fmc45TMdUfOlH1xD2zGYL7U4yDHFOhEZdi/suyjaelFobXB2p9pPIw6LjRQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.2.0.tgz", + "integrity": "sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw==", "dev": true, "requires": { - "@smithy/middleware-stack": "^1.0.1", - "@smithy/types": "^1.1.0", - "@smithy/util-stream": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/middleware-endpoint": "^3.1.0", + "@smithy/middleware-stack": "^3.0.3", + "@smithy/protocol-http": "^4.1.0", + "@smithy/types": "^3.3.0", + "@smithy/util-stream": "^3.1.3", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.0.tgz", - "integrity": "sha512-KzmvisMmuwD2jZXuC9e65JrgsZM97y5NpDU7g347oB+Q+xQLU6hQZ5zFNNbEfwwOJHoOvEVTna+dk1h/lW7alw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", + "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/url-parser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-1.0.1.tgz", - "integrity": "sha512-33vWEtE6HzmwjEcEb4I58XMLRAchwPS93YhfDyXAXr1jwDCzfXmMayQwwpyW847rpWj0XJimxqia8q0z+k/ybw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", + "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", "dev": true, "requires": { - "@smithy/querystring-parser": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/querystring-parser": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-base64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-1.0.1.tgz", - "integrity": "sha512-rJcpRi/yUi6TyCEkjdTH86/ExBuKlfctEXhG9/4gMJ3/cnPcHJJnr0mQ9evSEO+3DbpT/Nxq90bcTBdTIAmCig==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", "dev": true, "requires": { - "@smithy/util-buffer-from": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-body-length-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-1.0.1.tgz", - "integrity": "sha512-Pdp744fmF7E1NWoSb7256Anhm8eYoCubvosdMwXzOnHuPRVbDa15pKUz2027K3+jrfGpXo1r+MnDerajME1Osw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-body-length-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-1.0.1.tgz", - "integrity": "sha512-4PIHjDFwG07SNensAiVq/CJmubEVuwclWSYOTNtzBNTvxOeGLznvygkGYgPzS3erByT8C4S9JvnLYgtrsVV3nQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-buffer-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.0.1.tgz", - "integrity": "sha512-363N7Wq0ceUgE5lLe6kaR6GlJs2/m4r9V6bRMfIszb6P1FZbbRRM2FQYUWWPFSsRymm9mJL18b3fjiVsIvhDGg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", "dev": true, "requires": { - "@smithy/is-array-buffer": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-config-provider": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-1.0.1.tgz", - "integrity": "sha512-4Qy38Oy5/q43MpTwCLV1P+7NeaOp4W2etQDxMjgEeRlOyGGNlgttn0syi4g2rVSukFVqQ6FbeRs5xbnFmS6kaQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-defaults-mode-browser": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-1.0.1.tgz", - "integrity": "sha512-/9ObwNch4Z/NJYfkO4AvqBWku60Ju+c2Ck32toPOLmWe/V6eI9FLn8C1abri+GxDRCkLIqvkaWU1lgZ3nWZIIw==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz", + "integrity": "sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg==", "dev": true, "requires": { - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", "bowser": "^2.11.0", - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-defaults-mode-node": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-1.0.1.tgz", - "integrity": "sha512-XQM3KvqRLgv7bwAzVkXTITkOmcOINoG9icJiGT8FA0zV35lY5UvyIsg5kHw01xigQS8ufa/33AwG3ZoXip+V5g==", + "version": "3.0.15", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz", + "integrity": "sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A==", "dev": true, "requires": { - "@smithy/config-resolver": "^1.0.1", - "@smithy/credential-provider-imds": "^1.0.1", - "@smithy/node-config-provider": "^1.0.1", - "@smithy/property-provider": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/config-resolver": "^3.0.5", + "@smithy/credential-provider-imds": "^3.2.0", + "@smithy/node-config-provider": "^3.1.4", + "@smithy/property-provider": "^3.1.3", + "@smithy/smithy-client": "^3.2.0", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "dev": true + } + } + }, + "@smithy/util-endpoints": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz", + "integrity": "sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg==", + "dev": true, + "requires": { + "@smithy/node-config-provider": "^3.1.4", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" + }, + "dependencies": { + "tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-hex-encoding": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.0.1.tgz", - "integrity": "sha512-FPTtMz/t02/rbfq5Pdll/TWUYP+GVFLCQNr+DgifrLzVRU0g8rdRjyFpDh8nPTdkDDusTTo9P1bepAYj68s0eA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-middleware": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.0.1.tgz", - "integrity": "sha512-u9akN3Zmbr0vZH4F+2iehG7cFg+3fvDfnvS/hhsXH4UHuhqiQ+ADefibnLzPoz1pooY7rvwaQ/TVHyJmZHdLdQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", + "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", "dev": true, "requires": { - "tslib": "^2.5.0" + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-retry": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-1.0.3.tgz", - "integrity": "sha512-gYQnZDD8I2XJFspVwUISyukjPWVikTzKR0IdG8hCWYPTpeULFl1o6yzXlT5SL63TBkuEYl0R1/93cdNtMiNnoA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", + "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", "dev": true, "requires": { - "@smithy/service-error-classification": "^1.0.2", - "tslib": "^2.5.0" + "@smithy/service-error-classification": "^3.0.3", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-1.0.1.tgz", - "integrity": "sha512-4aBCIz35aZAnt2Rbq341KrnUzGhWv2/Zu8HouJqYLvSWCzlrvsNCGlXP4e70Kjzcw8hSuuCNtdUICwQ5qUWLxg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", + "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", "dev": true, "requires": { - "@smithy/fetch-http-handler": "^1.0.1", - "@smithy/node-http-handler": "^1.0.2", - "@smithy/types": "^1.1.0", - "@smithy/util-base64": "^1.0.1", - "@smithy/util-buffer-from": "^1.0.1", - "@smithy/util-hex-encoding": "^1.0.1", - "@smithy/util-utf8": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/fetch-http-handler": "^3.2.4", + "@smithy/node-http-handler": "^3.1.4", + "@smithy/types": "^3.3.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-uri-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.0.1.tgz", - "integrity": "sha512-IJUrRnXKEIc+PKnU1XzTsIENVR+60jUDPBP3iWX/EvuuT3Xfob47x1FGUe2c3yMXNuU6ax8VDk27hL5LKNoehQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", "dev": true, "requires": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-utf8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.0.1.tgz", - "integrity": "sha512-iX6XHpjh4DFEUIBSKp2tjy3pYnLQMsJ62zYi1BVAC0kobE6p8AVpiZnxsU3ZkgQatAsUaEspFHUZ7CL7oSqaPQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", "dev": true, "requires": { - "@smithy/util-buffer-from": "^1.0.1", - "tslib": "^2.5.0" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } }, "@smithy/util-waiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-1.0.1.tgz", - "integrity": "sha512-dsn8O0s3pFIgxFzySLe1dv0w4tEQizEP6UqbgZ4r/Kar4n8pSdrPi6DJg8BzXwkwEIZpMtV4/nhSeGZ7HksDXA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.1.2.tgz", + "integrity": "sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw==", "dev": true, "requires": { - "@smithy/abort-controller": "^1.0.1", - "@smithy/types": "^1.1.0", - "tslib": "^2.5.0" + "@smithy/abort-controller": "^3.1.1", + "@smithy/types": "^3.3.0", + "tslib": "^2.6.2" }, "dependencies": { "tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true } } @@ -20148,9 +20602,9 @@ "dev": true }, "fast-xml-parser": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", - "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", "dev": true, "requires": { "strnum": "^1.0.5" @@ -21743,12 +22197,12 @@ "dev": true }, "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "requires": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" } }, @@ -24334,9 +24788,9 @@ "dev": true }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, "uid-safe": { diff --git a/package.json b/package.json index b90f9adb..7eecc0c3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "peertube-plugin-livechat", "description": "PeerTube plugin livechat: create chat rooms for your Peertube lives! Comes with many features: federation, moderation tools, chat bot, chat persistence, OBS integration, ...", - "version": "10.3.3", + "version": "11.0.1", "license": "AGPL-3.0", "author": { "name": "John Livingston", @@ -73,7 +73,7 @@ "stylelint-config-recommended-scss": "^5.0.1", "stylelint-config-standard-scss": "^2.0.1", "svgo": "^2.8.0", - "typescript": "^4.3.5", + "typescript": "^4.9.5", "yaml": "^2.2.1" }, "engine": { diff --git a/prosody-modules/mod_firewall/README.markdown b/prosody-modules/mod_firewall/README.markdown new file mode 100644 index 00000000..2c9048f2 --- /dev/null +++ b/prosody-modules/mod_firewall/README.markdown @@ -0,0 +1,820 @@ +--- +labels: +- 'Stage-Alpha' +summary: 'A rule-based stanza filtering module' +rockspec: + build: + modules: + mod_firewall.actions: actions.lib.lua + mod_firewall.conditions: conditions.lib.lua + mod_firewall.definitions: definitions.lib.lua + mod_firewall.marks: marks.lib.lua + mod_firewall.test: test.lib.lua + copy_directories: + - scripts +--- + +------------------------------------------------------------------------ + +**Note:** mod\_firewall is in its very early stages. This documentation +is liable to change, and some described functionality may be missing, +incomplete or contain bugs. + +------------------------------------------------------------------------ + +Introduction +============ + +A firewall is an invaluable tool in the sysadmin's toolbox. However +while low-level firewalls such as iptables and pf are incredibly good at +what they do, they are generally not able to handle application-layer +rules. + +The goal of mod\_firewall is to provide similar services at the XMPP +layer. Based on rule scripts it can efficiently block, bounce, drop, +forward, copy, redirect stanzas and more! Furthermore all rules can be +applied and updated dynamically at runtime without restarting the +server. + +Details +======= + +mod\_firewall loads one or more scripts, and compiles these to Lua code +that reacts to stanzas flowing through Prosody. The firewall script +syntax is unusual, but straightforward. + +A firewall script is dominated by rules. Each rule has two parts: +conditions, and actions. When a stanza matches all of the conditions, +all of the actions are executed in order. + +Here is a simple example to block stanzas from spammer@example.com: + + FROM: spammer@example.com + DROP. + +FROM is a condition, and DROP is an action. This is about as simple as +it gets. How about heading to the other extreme? Let's demonstrate +something more complex that mod\_firewall can do for you: + + %ZONE myorganisation: staff.myorg.example, support.myorg.example + + ENTERING: myorganisation + KIND: message + TIME: 12am-9am, 5pm-12am, Saturday, Sunday + REPLY=Sorry, I am afraid our office is closed at the moment. If you need assistance, please call our 24-hour support line on 123-456-789. + +This rule will reply with a short message whenever someone tries to send +a message to someone at any of the hosts defined in the 'myorganisation' +outside of office hours. + +Specifying rule sets +-------------------- + +Firewall rules should be written into text files, e.g. `ruleset.pfw` file. +One or more rule files can be specified in the configuration using: + + firewall_scripts = { "path/to/ruleset.pfw", "path/to/ruleset2.pfw" } + +If multiple files are specified and they both add rules to the same [chains](#chains), +each file's rules will be processed in order, but the order of files is undefined. + +Reloading Prosody's configuration also reloads firewall rules. + +Make sure that `firewall_scripts` is in the global section of the configuration file +and not below a virtual host or a component - unless you want per-vhost +firewall rules. + +Conditions +---------- + +All conditions must come before any action in a rule block. The +condition name is followed by a colon (':'), and the value to test for. + +A condition can be preceded or followed by `NOT` to negate its match. +For example: + + NOT FROM: user@example.com + KIND NOT: message + +Some conditions do not take parameters, and these should end with just a +question mark, like: + + IN ROSTER? + +### Zones + +A 'zone' is one or more hosts or JIDs. It is possible to match when a +stanza is entering or leaving a zone, while at the same time not +matching traffic passing between JIDs in the same zone. + +Zones are defined at the top of a script with the following syntax (they +are not part of a rule block): + + %ZONE myzone: host1, host2, user@host3, foo.bar.example + +There is an automatic zone named `$local`, which automatically includes +all of the current server's active hosts (including components). It can +be used to match stanzas entering or leaving the current server. + +A host listed in a zone also matches all users on that host (but not +subdomains). + +The following zone-matching conditions are supported: + + Condition Matches + ------------ ------------------------------------------ + `ENTERING` When a stanza is entering the named zone + `LEAVING` When a stanza is leaving the named zone + +### Lists + +It is possible to create or load lists of strings for use in scripts. For +example, you might load a list of blocked JIDs, malware URLs or simple words +that you want to filter messages on. + + List type Example + ----------- ----------------------- + memory %LIST spammers: memory + file %LIST spammers: file:/etc/spammers.txt + http %LIST spammers: http://example.com/spammers.txt + +#### List types +##### memory + +``` +%LIST name: memory (limit: number) +``` + +A memory-only list, with an optional limit. Supports addition and removal of items by scripts. + +If a limit is provided, the oldest item will be discarded to make room for a new item if the +list is full. The limit is useful to prevent infinite memory growth on busy servers. + +##### file + +``` +%LIST name: file:/path/to/file (missing: string) +``` + +Reads a list from a file. The list can be added to and removed from by scripts, but +these changes do not persist between restarts. + +If the file is missing, an error will be raised. The optional 'missing' parameter can be set +to 'ignore' (e.g. `(missing: ignore)`) to ignore a missing file. + +##### http + +``` +%LIST name: http://example.com/ (ttl: number, pattern: pat, hash: sha1, checkcerts: when-sni) +``` + +Fetches a list from a HTTP or HTTPS URL. The following options are accepted: + + Option Description + ------- ----------- + ttl Seconds to cache the list for. After expiry, it will be refetched. Default 3600 (1 hour). + pattern Optional pattern used to extract list entries from the response. Default is to treat each line as a single item. + hash Optional hash to be applied to items before looking them up in the list, e.g. sha1 or sha256. + checkcert Whether to verify HTTPS certificates. May be "always", "never" or "when-sni". Default "when-sni". + +The "when-sni" default disables certificate verification when Prosody's HTTP client API doesn't support SNI, +as in Prosody 0.11.6 and earlier. + +#### CHECK LIST + +Checks whether a simple [expression](#expressions) is found in a given list. + +Example: + + %LIST blocked_jids: file:/etc/prosody/blocked_jids.txt + + # Rule to block presence subscription requests from blocked JIDs + KIND: presence + TYPE: subscribe + CHECK LIST: blocked_jids contains $<@from> + BOUNCE=policy-violation (Your JID is blocked) + +#### SCAN + +SCAN allows you to search inside a stanza for a given pattern, and check each result against a list. For example, +you could scan a message body for words and check if any of the words are found in a given list. + +Before using SCAN, you need to define a search location and a pattern. The search location uses the same 'path' +format as documented under the 'INSPECT' condition. Patterns can be any valid Lua pattern. + +To use the above example: + + # Define a search location called 'body' which fetches the text of the 'body' element + %SEARCH body: body# + # Define a pattern called 'word' which matches any sequence of letters + %PATTERN word: [A-Za-z]+ + # Finally, we also need our list of "bad" words: + %LIST badwords: file:/etc/prosody/bad_words.txt + + # Now we can use these to SCAN incoming stanzas + # If it finds a match, bounce the stanza + SCAN: body for word in badwords + BOUNCE=policy-violation (This word is not allowed!) + +#### COUNT + +COUNT is similar to SCAN, in that it uses a defined SEARCH and breaks it up according to a PATTERN. Then it +counts the number of results. + +For example, to block every message with more than one URL: + + # Define a search location called 'body' which fetches the text of the 'body' element + %SEARCH body: body# + # Define a pattern called 'url' which matches HTTP links + %PATTERN url: https?://%S+ + + COUNT: url in body > 1 + BOUNCE=policy-violation (Up to one HTTP URL is allowed in messages) + +### Stanza matching + + Condition Matches + ----------- ------------------------------------------------------------------------------------------------------------------------------------------------------------ + `KIND` The kind of stanza. May be 'message', 'presence' or 'iq' + `TYPE` The type of stanza. This varies depending on the kind of stanza. See 'Stanza types' below for more information. + `PAYLOAD` The stanza contains a child with the given namespace. Useful for determining the type of an iq request, or whether a message contains a certain extension. + `INSPECT` The node at the specified path exists or matches a given string. This allows you to look anywhere inside a stanza. See below for examples and more. + +#### Stanza types + + Stanza Valid types + ---------- ------------------------------------------------------------------------------------------ + iq get, set, result, error + presence *available*, unavailable, probe, subscribe, subscribed, unsubscribe, unsubscribed, error + message normal, chat, groupchat, headline, error + +**Note:** The type 'available' for presence does not actually appear in +the protocol. Available presence is signalled by the omission of a type. +Similarly, a message stanza with no type is equivalent to one of type +'normal'. mod\_firewall handles these cases for you automatically. + +#### Sender/recipient matching + + Condition Matches + --------------- ------------------------------------------------------- + `FROM` The JID in the 'from' attribute matches the given JID. + `TO` The JID in the 'to' attribute matches the given JID. + `TO SELF` The stanza is sent by any of a user's resources to their own bare JID. + `TO FULL JID` The stanza is addressed to a **valid** full JID on the local server (full JIDs include a resource at the end, and only exist for the lifetime of a single session, therefore the recipient **must be online**, or this check will not match). + `FROM FULL JID` The stanza is from a full JID (unlike `TO FULL JID` this check is on the format of the JID only). + +The TO and FROM conditions both accept wildcards in the JID when it is +enclosed in angle brackets ('\<...\>'). For example: + + # All users at example.com + FROM: <*>@example.com + + # The user 'admin' on any subdomain of example.com + FROM: admin@<*.example.com> + +You can also use [Lua's pattern +matching](http://www.lua.org/manual/5.1/manual.html#5.4.1) for more +powerful matching abilities. Patterns are a lightweight +regular-expression alternative. Simply contain the pattern in double +angle brackets. The pattern is automatically anchored at the start and +end (so it must match the entire portion of the JID). + + # Match admin@example.com, and admin1@example.com, etc. + FROM: <>@example.com + +**Note:** It is important to know that 'example.com' is a valid JID on +its own, and does **not** match 'user@example.com'. To efficiently match +domains we recommend defining them as [Zones](#zones). + + Condition Matches + ---------------- --------------------------------------------------------------- + `FROM_EXACTLY` The JID in the 'from' attribute exactly matches the given JID + `TO_EXACTLY` The JID in the 'to' attribute exactly matches the given JID + +These additional conditions do not support pattern matching, but are +useful to match the exact to/from address on a stanza. For example, if +no resource is specified then only bare JIDs will be matched. TO and FROM +match all resources if no resource is specified to match. + +**Note:** Some chains execute before Prosody has performed any +normalisation or validity checks on the to/from JIDs on an incoming +stanza. It is not advisable to perform access control or similar rules +on JIDs in these chains (see the [chain documentation](#chains) for more info). + +#### GeoIP matching + + Condition Matches + ---------------- -------------------------------------------------------------- + `FROM COUNTRY` Two or three letter country code looked up in GeoIP database + +This condition uses a GeoIP database to look up the origin country of +the IP attached to the current session. + +For example: + + # 3 letter country code + FROM COUNTRY: SWE + + # or 2 letter + FROM COUNTRY: SE + + # Explicit + FROM COUNTRY: code=SE + FROM COUNTRY: code3=SWE + +**Note:** This requires that the `lua-geoip` and `geoip-database` +packages are installed (on Debian, package names may differ on other +operating systems). + +#### INSPECT + +INSPECT takes a 'path' through the stanza to get a string (an attribute +value or text content). An example is the best way to explain. Let's +check that a user is not trying to register an account with the username +'admin'. This stanza comes from [XEP-0077: In-band +Registration](http://xmpp.org/extensions/xep-0077.html#example-4): + +``` xml + + + bill + Calliope + bard@shakespeare.lit + + +``` + + KIND: iq + TYPE: set + PAYLOAD: jabber:iq:register + INSPECT: {jabber:iq:register}query/username#=admin + BOUNCE=not-allowed (The username 'admin' is reserved.) + +That weird string deserves some explanation. It is a path, divided into +segments by '/'. Each segment describes an element by its name, +optionally prefixed by its namespace in curly braces ('{...}'). If the +path ends with a '\#' then the text content of the last element will be +returned. If the path ends with '@name' then the value of the attribute +'name' will be returned. + +You can use INSPECT to test for the existence of an element or attribute, +or you can check if it matches a specific value, e.g. by appending `=VALUE` +(like in the example above, that checks if the content of username is 'admin'). + +#### INSPECT comparison operators + +As well as checking for an exact string match, there are some other modifiers +you can apply to the comparison: + + Comparison Matches when + ------------- ------------------------------------------------------- + `=` The value is exactly the given string. + `/=` The value is or *contains* the given string (e.g. `/=admin` would match `administrator` or `myadmin`). + `~=` The value matches the given [Lua pattern](https://www.lua.org/manual/5.2/manual.html#6.4.1). + +Finally, if the comparison operator is preceded by a `$` character, [expressions](#expressions) +will be interpreted in the string following the comparison operator. + +e.g. `INSPECT: {jabber:iq:register}query/username}$/=$(session.host)` would match +if the username of an account registration contained the session's current hostname +somewhere in it. + +#### INSPECT performance + +INSPECT can be somewhat slower than the other stanza matching conditions. To +minimise performance impact, always place it below other faster +condition checks where possible (e.g. in the example above we first checked KIND, +TYPE and PAYLOAD matched what we wanted before reaching the INSPECT rule). + +### Roster + +These conditions access the roster of the recipient (only). Therefore they cannot (currently) +be used in some [chains](#chains), such as for outgoing messages (the recipient may be on another server). + +Performance note: these checks can potentially cause storage access (especially if the recipient +is currently offline), so you may want to limit their use in high-traffic situations, and place rules +containing a roster check below other rules (such as a rate limiter). The storage access is +performed unconditionally just before evaluation of the first rule that contains a roster-based +condition, even if earlier conditions in that rule do not match. + +#### IN ROSTER + +Tests whether the sender is in the recipient's roster. + + IN ROSTER? + +#### IN ROSTER GROUP + +Tests whether the sender is in the recipient's roster, and in the named group. + + IN ROSTER GROUP: Friends + +#### SUBSCRIBED + +Tests whether the recipient is subscribed to the sender, ie will receive +presence updates from them. + +Note that this *does* work, regardless of direction and which [chain](#chain) is +used, since both the sender and the recipient will have mirrored roster +entries. + +### Groups + +Using Prosody's mod\_groups it is possible to define groups of users on the server. You can +match based on these groups in firewall rules. + + Condition Matches + ----------------- ---------------------------- + `FROM GROUP` When the stanza is being sent from a member of the named group + `TO GROUP` When the stanza is being sent to a member of the named group + `CROSSING GROUPS` When the stanza is being sent between users of different named groups + +#### CROSSING GROUPS + +The `CROSSING GROUPS` condition takes a comma-separated list of groups to check. If the +sender and recipient are not in the same group (only the listed groups are checked), then the +this condition matches and the stanza is deemed to be crossing between groups. + +For example, if you had three groups: Engineering, Marketing and Employees. All users are +members of the 'Employees' group, and the others are for employees of the named department only. + +To prevent employees in the marketing department from communicating with engineers, you could use +the following rule: + +``` +CROSSING GROUPS: Marketing, Engineering +BOUNCE=policy-violation (no communication between these groups is allowed!) +``` + +This works, even though both the users are in the 'Employees' group, because that group is not listed +in the condition. + +In the above example, a user who is member of both groups is not restricted. + +#### SENT DIRECTED PRESENCE TO SENDER + +This condition matches if the recipient of a stanza has previously sent directed presence to the sender of the stanza. This +is often done in XMPP to exchange presence information with JIDs that are not on your roster, such as MUC rooms. + +This condition does not take a parameter - end the condition name with a question mark: + + # Rule to bounce messages from senders not in the roster who haven't been sent directed presence + NOT IN ROSTER? + NOT SENT DIRECTED PRESENCE TO SENDER? + BOUNCE=service-unavailable + +### Permissions + +Rules can consult Prosody's internal role and permissions system to check whether a certain action may +be performed. The acting entity, their role, and appropriate context is automatically inferred. All you +need to do is provide the identifier of the permission that should be checked. + + Condition Description + ----------------------- -------------------------------------------------------------------- + `MAY=permission` Checks whether 'permission' is allowed in the current context. + +As with all other conditions, `MAY` can be combined with `NOT` to negate the result of the check. + +Example, blocking outgoing stanzas from users with roles that do not allow the 'xmpp:federate' permission: + +``` +::deliver_remote +MAY NOT: xmpp:federate +BOUNCE=policy-violation (You are not allowed access to the federation) +``` + +### Roles + + Condition Matches + ---------------- ------------------------------------------------------------------------------------- + `TO ROLE` When the recipient JID of the stanza has the named role + `FROM ROLE` When the sender JID of the stanza has the named role + +**Note:** In most cases, you should avoid checking for specific roles, and instead check for +permissions granted by those roles (using the 'MAY' condition). + +### Admins + +**Deprecated:** These conditions should no longer be used. Prefer 'MAY', 'TO ROLE' or 'FROM ROLE'. + +Prosody allows certain JIDs to be declared as administrators of a host, component or the whole server. + + Condition Matches + ---------------- ------------------------------------------------------------------------------------- + `TO ADMIN` When the recipient of the stanza is admin of the current host + `FROM ADMIN` When the sender of the stanza is admin of the current host + `FROM ADMIN OF` When the sender of the stanza is an admin of the named host on the current server + `TO ADMIN OF` When the recipient of the stanza is an admin of the named host on the current server + +### Time and date + +#### TIME + +Matches stanzas sent during certain time periods. + + Condition Matches + ----------- ------------------------------------------------------------------------------------------- + TIME When the current server local time is within one of the comma-separated time ranges given + + TIME: 10pm-6am, 14:00-15:00 + REPLY=Zzzz. + +#### DAY + +It is also possible to match only on certain days of the week. + + Condition Matches + ----------- ----------------------------------------------------------------------------------------------------- + DAY When the current day matches one, or falls within a rage, in the given comma-separated list of days + +Example: + + DAY: Sat-Sun, Wednesday + REPLY=Sorry, I'm out enjoying life! + +All times and dates are handled in the server's local time. + +### Rate-limiting + +It is possible to selectively rate-limit stanzas, and use rules to +decide what to do with stanzas when over the limit. + +First, you must define any rate limits that you are going to use in your +script. Here we create a limiter called 'normal' that will allow 2 +stanzas per second, and then we define a rule to bounce messages when +over this limit. Note that the `RATE` definition is not part of a rule +(multiple rules can share the same limiter). + + %RATE normal: 2 (burst 3) + + KIND: message + LIMIT: normal + BOUNCE=policy-violation (Sending too fast!) + +The 'burst' parameter on the rate limit allows you to spread the limit +check over a given time period. For example the definition shown above +will allow the limit to be temporarily surpassed, as long as it is +within the limit after 3 seconds. You will almost always want to specify +a burst factor. + +Both the rate and the burst can be fractional values. For example a rate +of 0.1 means only one event is allowed every 10 seconds. + +The LIMIT condition actually does two things; first it counts against +the given limiter, and then it checks to see if the limiter over its +limit yet. If it is, the condition matches, otherwise it will not. + + Condition Matches + ----------- -------------------------------------------------------------------------------------------------- + `LIMIT` When the named limit is 'used up'. Using this condition automatically counts against that limit. + +**Note:** Reloading mod\_firewall resets the current state of any +limiters. + +#### Dynamic limits + +Sometimes you may want to have multiple throttles in a single condition, using some property of the session or stanza +to determine which throttle to use. For example, you might have a limit for incoming stanzas, but you want to limit by +sending JID, instead of all incoming stanzas sharing the same limit. + +You can use the 'on' keyword for this, like so: + + LIMIT: normal on EXPRESSION + +For more information on [expressions](#expressions), see the section later in this document. + +Each value of 'EXPRESSION' has to be tracked individually in a table, which uses a small amount of memory. To prevent +memory exhaustion, the number of tracked values is limited to 1000 by default. You can override this by setting the +maximum number of table entries when you define the rate: + + %RATE normal: 2 (burst 3) (entries 4096) + +Old values are automatically removed from the tracking table. However if the tracking table becomes full, new entries +will be rejected - it will behave as if the rate limit was reached, even for values that have not been seen before. Since +this opens up a potential denial of service (innocent users may be affected if malicious users can fill up the tracking +table within the limit period). You can choose to instead "fail open", and allow the rate limit to be temporarily bypassed +when the table is full. To choose this behaviour, add `(allow overflow)` to the RATE definition. + +### Session marking + +It is possible to 'mark' sessions (see the MARK_ORIGIN action below). To match stanzas from marked sessions, use the +`ORIGIN_MARKED` condition. + + Condition Description + ------------------------------- --------------------------------------------------------------- + ORIGIN MARKED: markname Matches if the origin has been marked with 'markname'. + ORIGIN MARKED: markname (Xs) Matches if the origin has been marked with 'markname' within the past X seconds. + +Example usage: + + # This rule drops messages from sessions that have been marked as spammers in the past hour + ORIGIN MARKED: spammer (3600s) + DROP. + + # This rule marks the origin session as a spammer if they send a message to a honeypot JID + KIND: message + TO: honeypot@example.com + MARK ORIGIN=spammer + +Actions +------- + +Actions come after all conditions in a rule block. There must be at +least one action, though conditions are optional. + +An action without parameters ends with a full-stop/period ('.'), and one +with parameters uses an equals sign ('='): + + # An action with no parameters: + DROP. + + # An action with a parameter: + REPLY=Hello, this is a reply. + +### Route modification + +The following common actions modify the stanza's route in some way. These +rules will halt further processing of the stanza - no further actions will be +executed, and no further rules will be checked. + + Action Description + ----------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------- + `PASS.` Stop executing actions and rules on this stanza, and let it through this chain and any calling chains. + `DROP.` Stop executing actions and rules on this stanza, and discard it. + `DEFAULT.` Stop executing actions and rules on this stanza, prevent any other scripts/modules from handling it, to trigger the appropriate default "unhandled stanza" behaviour. Do not use in custom chains (it is treated as PASS). + `REDIRECT=jid` Redirect the stanza to the given JID. + `BOUNCE.` Bounce the stanza with the default error (usually service-unavailable) + `BOUNCE=error` Bounce the stanza with the given error (MUST be a defined XMPP stanza error, see [RFC6120](http://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions). + `BOUNCE=error (text)` As above, but include the supplied human-readable text with a description of the error + +**Note:** It is incorrect behaviour to reply to an 'error' stanza with another error, so BOUNCE will simply act the same as 'DROP' for stanzas that should not be bounced (error stanzas and iq results). + +### Replying and forwarding + +These actions cause a new stanza to be generated and sent somewhere. +Processing of the original stanza will continue beyond these actions. + + Action Description + ------------------------ --------------------------------------------------------------------------------------------------------------------------------------------------------- + `REPLY=text` Reply to the stanza (assumed to be a message) with the given text. + `COPY=jid` Make a copy of the stanza and send the copy to the specified JID. The copied stanza flows through Prosody's routing code, and as such is affected by firewall rules. Be careful to avoid loops. + `FORWARD=jid` Forward a copy of the stanza to the given JID (using XEP-0297). The stanza will be sent from the current host's JID. + +### Reporting + + Action Description + ------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------- + `REPORT TO=jid [reason] [text]` Forwards the full stanza to `jid` with a XEP-0377 abuse report attached. + +Only the `jid` is mandatory. The `reason` parameter should be either `abuse`, `spam` or a custom URI. If not specified, it defaults to `abuse`. +After the reason, some human-readable text may be included to explain the report. + +Example: + +``` +KIND: message +TO: honeypot@example.com +REPORT TO=antispam.example.com spam Caught by the honeypot! +DROP. +``` + +### Stanza modification + +These actions make it possible to modify the content and structure of a +stanza. + + Action Description + ------------------------ ------------------------------------------------------------------------ + `STRIP=name` Remove any child elements with the given name in the default namespace + `STRIP=name namespace` Remove any child elements with the given name and the given namespace + `INJECT=xml` Inject the given XML into the stanza as a child element + +### Sessions + +It is possible to mark sessions, and then use these marks to match rules later on. + + Action Description + ------------------------ -------------------------------------------------------------------------- + `MARK ORIGIN=mark` Marks the originating session with the given flag. + `UNMARK ORIGIN=mark` Removes the given mark from the origin session (if it is set). + +**Note:** Marks apply to sessions, not JIDs. E.g. if marking in a rule that matches a stanza received +over s2s, it is the s2s session that is marked. + +It is possible to have multiple marks on an origin at any given time. + +### Informational + + Action Description + --------------- ------------------------------------------------------------------------------------------------------------------------ + `LOG=message` Logs the given message to Prosody's log file. Optionally prefix it with a log level in square brackets, e.g. `[debug]` + +You can include [expressions](#expressions) in log messages, using `$(...)` syntax. For example, to log the stanza that matched the rule, +you can use `$(stanza)`, or to log just the top tag of the stanza, use `$(stanza:top_tag())`. To fetch the sender JID, use `$(stanza.attr.from)`. + +Example: + + # Log all stanzas to user@example.com: + TO: user@example.com + LOG=[debug] User received: $(stanza) + +More info about expressions can be found below. + +Chains +------ + +Rules are grouped into "chains", which are injected at particular points in Prosody's routing code. + +Available built-in chains are: + + Chain Description + -------------- ------------------------------------------------------------------------------------------- + deliver Applies to stanzas delivered to local recipients (regardless of the stanza's origin) + deliver_remote Applies to stanzas delivered to remote recipients (just before they leave the local server) + preroute Applies to incoming stanzas from local users, before any routing rules are applied + +A chain is begun by a line `::name` where 'name' is the name of the chain you want the following rules to be +inserted into. If no chain is specified, rules are put into the 'deliver' chain. + +It is possible to create custom chains (useful with the `JUMP CHAIN` action described below). User-created +chains must begin with "user/", e.g. "user/spam_filtering". + +Example of chain use: + + # example.com's firewall script + + # This line is optional, because 'deliver' is the default chain anyway: + ::deliver + + # This rule matches any stanzas delivered to our local user bob: + TO: bob@example.com + DROP. + + # Oops! This rule will never match, because alice is not a local user, + # and only stanzas to local users go through the 'deliver' chain: + TO: alice@remote.example.com + DROP. + + # Create a 'preroute' chain of rules (matched for incoming stanzas from local clients): + ::preroute + # These rules are matched for outgoing stanzas from local clients + + # This will match any stanzas sent to alice from a local user: + TO: alice@remote.example.com + DROP. + + Action Description + ------------------------ ------------------------------------------------------------------------ + `JUMP CHAIN=name` Switches chains, and passes the stanza through the rules in chain 'name'. If the new chain causes the stanza to be dropped/redirected, the current chain halts further processing. + `RETURN.` Stops executing the current chain and returns to the parent chain. For built-in chains, equivalent to PASS. RETURN is implicit at the end of every chain. + +It is possible to jump to chains defined by other scripts and modules. + +Expressions +----------- + +Some conditions and actions in rules support "expressions" in their parameters (their documentation will indicate if this is the case). Most parameters +are static once the firewall script is loaded and compiled internally, however parameters that allow expressions can be dynamically calculated when a +rule is being run. + +There are two kinds of expression that you can use: stanza expressions, and code expressions. + +### Stanza expressions + +Stanza expressions are of the form `$<...>`, where `...` is a stanza path. For syntax of stanza paths, see the documentation for the 'INSPECT' condition +above. + +Example: + + LOG=Matched a stanza from $<@from> to $<@to> + +There are built in functions which can be applied to the output of a stanza expression, by appending the pipe ('|') operator, followed by the function +name. These functions are: + + Function Description + ------------ --------------------------------------- + bare Given a JID, strip any resource + node Return the node ('user part') of a JID + host Return the host ('domain') part of a JID + resource Return the resource part of a JID + +For example, to apply a rate limit to stanzas per sender domain: + + LIMIT normal on $<@from|host> + +If the path does not match (e.g. the element isn't found, or the attribute doesn't exist) or any of the functions fail to produce an output (e.g. an invalid +JID was passed to a function that only handles valid JIDs) the expression will return the text ``. You can override this by ending the expression +with a double pipe ('||') followed by a quoted string to use as a default instead. E.g. to default to the string "normal" when there is no 'type' attribute: + + LOG=Stanza type is $<@type||"normal"> + +### Code expressions + +Code expressions use `$(...)` syntax. Code expressions are powerful, and allow unconstrained access to Prosody's internal environment. Therefore +code expressions are typically for advanced use-cases only. You may want to refer to Prosody's [developer documentation](https://prosody.im/doc/developers) +for more information. In particular, within code expressions you may access the 'session' object, which is the session object of the origin of the stanza, +and the 'stanza' object, which is the stanza being considered within the current rule. Whatever value the expression returns will be converted to a string. + +Example to limit stanzas per session type: + + LIMIT: normal on $(session.type) diff --git a/prosody-modules/mod_firewall/actions.lib.lua b/prosody-modules/mod_firewall/actions.lib.lua new file mode 100644 index 00000000..961a5c0e --- /dev/null +++ b/prosody-modules/mod_firewall/actions.lib.lua @@ -0,0 +1,280 @@ +local unpack = table.unpack or unpack; + +local interpolation = require "util.interpolation"; +local template = interpolation.new("%b$$", function (s) return ("%q"):format(s) end); + +--luacheck: globals meta idsafe +local action_handlers = {}; + + +-- Takes an XML string and returns a code string that builds that stanza +-- using st.stanza() +local function compile_xml(data) + local code = {}; + local first, short_close = true, nil; + for tagline, text in data:gmatch("<([^>]+)>([^<]*)") do + if tagline:sub(-1,-1) == "/" then + tagline = tagline:sub(1, -2); + short_close = true; + end + if tagline:sub(1,1) == "/" then + code[#code+1] = (":up()"); + else + local name, attr = tagline:match("^(%S*)%s*(.*)$"); + local attr_str = {}; + for k, _, v in attr:gmatch("(%S+)=([\"'])([^%2]-)%2") do + if #attr_str == 0 then + table.insert(attr_str, ", { "); + else + table.insert(attr_str, ", "); + end + if k:find("^%a%w*$") then + table.insert(attr_str, string.format("%s = %q", k, v)); + else + table.insert(attr_str, string.format("[%q] = %q", k, v)); + end + end + if #attr_str > 0 then + table.insert(attr_str, " }"); + end + if first then + code[#code+1] = (string.format("st.stanza(%q %s)", name, #attr_str>0 and table.concat(attr_str) or ", nil")); + first = nil; + else + code[#code+1] = (string.format(":tag(%q%s)", name, table.concat(attr_str))); + end + end + if text and text:find("%S") then + code[#code+1] = (string.format(":text(%q)", text)); + elseif short_close then + short_close = nil; + code[#code+1] = (":up()"); + end + end + return table.concat(code, ""); +end + +function action_handlers.PASS() + return "do return pass_return end" +end + +function action_handlers.DROP() + return "do return true end"; +end + +function action_handlers.DEFAULT() + return "do return false end"; +end + +function action_handlers.RETURN() + return "do return end" +end + +function action_handlers.STRIP(tag_desc) + local code = {}; + local name, xmlns = tag_desc:match("^(%S+) (.+)$"); + if not name then + name, xmlns = tag_desc, nil; + end + if name == "*" then + name = nil; + end + code[#code+1] = ("local stanza_xmlns = stanza.attr.xmlns; "); + code[#code+1] = "stanza:maptags(function (tag) if "; + if name then + code[#code+1] = ("tag.name == %q and "):format(name); + end + if xmlns then + code[#code+1] = ("(tag.attr.xmlns or stanza_xmlns) == %q "):format(xmlns); + else + code[#code+1] = ("tag.attr.xmlns == stanza_xmlns "); + end + code[#code+1] = "then return nil; end return tag; end );"; + return table.concat(code); +end + +function action_handlers.INJECT(tag) + return "stanza:add_child("..compile_xml(tag)..")", { "st" }; +end + +local error_types = { + ["bad-request"] = "modify"; + ["conflict"] = "cancel"; + ["feature-not-implemented"] = "cancel"; + ["forbidden"] = "auth"; + ["gone"] = "cancel"; + ["internal-server-error"] = "cancel"; + ["item-not-found"] = "cancel"; + ["jid-malformed"] = "modify"; + ["not-acceptable"] = "modify"; + ["not-allowed"] = "cancel"; + ["not-authorized"] = "auth"; + ["payment-required"] = "auth"; + ["policy-violation"] = "modify"; + ["recipient-unavailable"] = "wait"; + ["redirect"] = "modify"; + ["registration-required"] = "auth"; + ["remote-server-not-found"] = "cancel"; + ["remote-server-timeout"] = "wait"; + ["resource-constraint"] = "wait"; + ["service-unavailable"] = "cancel"; + ["subscription-required"] = "auth"; + ["undefined-condition"] = "cancel"; + ["unexpected-request"] = "wait"; +}; + + +local function route_modify(make_new, to, drop) + local reroute, deps = "session.send(newstanza)", { "st" }; + if to then + reroute = ("newstanza.attr.to = %q; core_post_stanza(session, newstanza)"):format(to); + deps[#deps+1] = "core_post_stanza"; + end + return ([[do local newstanza = st.%s; %s;%s end]]) + :format(make_new, reroute, drop and " return true" or ""), deps; +end + +function action_handlers.BOUNCE(with) + local error = with and with:match("^%S+") or "service-unavailable"; + local error_type = error:match(":(%S+)"); + if not error_type then + error_type = error_types[error] or "cancel"; + else + error = error:match("^[^:]+"); + end + error, error_type = string.format("%q", error), string.format("%q", error_type); + local text = with and with:match(" %((.+)%)$"); + if text then + text = string.format("%q", text); + else + text = "nil"; + end + local route_modify_code, deps = route_modify(("error_reply(stanza, %s, %s, %s)"):format(error_type, error, text), nil, true); + deps[#deps+1] = "type"; + deps[#deps+1] = "name"; + return [[if type == "error" or (name == "iq" and type == "result") then return true; end -- Don't reply to 'error' stanzas, or iq results + ]]..route_modify_code, deps; +end + +function action_handlers.REDIRECT(where) + return route_modify("clone(stanza)", where, true); +end + +function action_handlers.COPY(where) + return route_modify("clone(stanza)", where, false); +end + +function action_handlers.REPLY(with) + return route_modify(("reply(stanza):body(%q)"):format(with)); +end + +function action_handlers.FORWARD(where) + local code = [[ + local newstanza = st.stanza("message", { to = %q, from = current_host }):tag("forwarded", { xmlns = "urn:xmpp:forward:0" }); + local tmp_stanza = st.clone(stanza); tmp_stanza.attr.xmlns = "jabber:client"; newstanza:add_child(tmp_stanza); + core_post_stanza(session, newstanza); + ]]; + return code:format(where), { "core_post_stanza", "current_host" }; +end + +function action_handlers.LOG(string) + local level = string:match("^%[(%a+)%]") or "info"; + string = string:gsub("^%[%a+%] ?", ""); + local meta_deps = {}; + local code = meta(("(session.log or log)(%q, '%%s', %q);"):format(level, string), meta_deps); + return code, meta_deps; +end + +function action_handlers.RULEDEP(dep) + return "", { dep }; +end + +function action_handlers.EVENT(name) + return ("fire_event(%q, event)"):format(name); +end + +function action_handlers.JUMP_EVENT(name) + return ("do return fire_event(%q, event); end"):format(name); +end + +function action_handlers.JUMP_CHAIN(name) + return template([[do + local ret = fire_event($chain_event$, event); + if ret ~= nil then + if ret == false then + log("debug", "Chain %q accepted stanza (ret %s)", $chain_name$, tostring(ret)); + return pass_return; + end + log("debug", "Chain %q rejected stanza (ret %s)", $chain_name$, tostring(ret)); + return ret; + end + end]], { chain_event = "firewall/chains/"..name, chain_name = name }); +end + +function action_handlers.MARK_ORIGIN(name) + return [[session.firewall_marked_]]..idsafe(name)..[[ = current_timestamp;]], { "timestamp" }; +end + +function action_handlers.UNMARK_ORIGIN(name) + return [[session.firewall_marked_]]..idsafe(name)..[[ = nil;]] +end + +function action_handlers.MARK_USER(name) + return ([[if session.username and session.host == current_host then + fire_event("firewall/marked/user", { + username = session.username; + mark = %q; + timestamp = current_timestamp; + }); + else + log("warn", "Attempt to MARK a remote user - only local users may be marked"); + end]]):format(assert(idsafe(name), "Invalid characters in mark name: "..name)), { + "current_host"; + "timestamp"; + }; +end + +function action_handlers.UNMARK_USER(name) + return ([[if session.username and session.host == current_host then + fire_event("firewall/unmarked/user", { + username = session.username; + mark = %q; + }); + else + log("warn", "Attempt to UNMARK a remote user - only local users may be marked"); + end]]):format(assert(idsafe(name), "Invalid characters in mark name: "..name)); +end + +function action_handlers.ADD_TO(spec) + local list_name, value = spec:match("(%S+) (.+)"); + local meta_deps = {}; + value = meta(("%q"):format(value), meta_deps); + return ("list_%s:add(%s);"):format(list_name, value), { "list:"..list_name, unpack(meta_deps) }; +end + +function action_handlers.UNSUBSCRIBE_SENDER() + return "rostermanager.unsubscribed(to_node, to_host, bare_from);\ + rostermanager.roster_push(to_node, to_host, bare_from);\ + core_post_stanza(session, st.presence({ from = bare_to, to = bare_from, type = \"unsubscribed\" }));", + { "rostermanager", "core_post_stanza", "st", "split_to", "bare_to", "bare_from" }; +end + +function action_handlers.REPORT_TO(spec) + local where, reason, text = spec:match("^%s*(%S+) *(%S*) *(.*)$"); + if reason == "spam" then + reason = "urn:xmpp:reporting:spam"; + elseif reason == "abuse" or not reason or reason == "" then + reason = "urn:xmpp:reporting:abuse"; + end + local code = [[ + local newstanza = st.stanza("message", { to = %q, from = current_host, id = new_short_id() }):tag("forwarded", { xmlns = "urn:xmpp:forward:0" }); + local tmp_stanza = st.clone(stanza); tmp_stanza.attr.xmlns = "jabber:client"; newstanza:add_child(tmp_stanza):up(); + newstanza:tag("report", { xmlns = "urn:xmpp:reporting:1", reason = %q }) + do local text = %q; if text ~= "" then newstanza:text_tag("text", text); end end + newstanza:up(); + core_post_stanza(session, newstanza); + ]]; + return code:format(where, reason, text), { "core_post_stanza", "current_host", "st", "new_short_id" }; +end + +return action_handlers; diff --git a/prosody-modules/mod_firewall/conditions.lib.lua b/prosody-modules/mod_firewall/conditions.lib.lua new file mode 100644 index 00000000..718089de --- /dev/null +++ b/prosody-modules/mod_firewall/conditions.lib.lua @@ -0,0 +1,410 @@ +--luacheck: globals meta idsafe +local condition_handlers = {}; + +local jid = require "util.jid"; +local unpack = table.unpack or unpack; + +-- Helper to convert user-input strings (yes/true//no/false) to a bool +local function string_to_boolean(s) + s = s:lower(); + return s == "yes" or s == "true"; +end + +-- Return a code string for a condition that checks whether the contents +-- of variable with the name 'name' matches any of the values in the +-- comma/space/pipe delimited list 'values'. +local function compile_comparison_list(name, values) + local conditions = {}; + for value in values:gmatch("[^%s,|]+") do + table.insert(conditions, ("%s == %q"):format(name, value)); + end + return table.concat(conditions, " or "); +end + +function condition_handlers.KIND(kind) + assert(kind, "Expected stanza kind to match against"); + return compile_comparison_list("name", kind), { "name" }; +end + +local wildcard_equivs = { ["*"] = ".*", ["?"] = "." }; + +local function compile_jid_match_part(part, match) + if not match then + return part.." == nil"; + end + local pattern = match:match("^<(.*)>$"); + if pattern then + if pattern == "*" then + return part; + end + if pattern:find("^<.*>$") then + pattern = pattern:match("^<(.*)>$"); + else + pattern = pattern:gsub("%p", "%%%0"):gsub("%%(%p)", wildcard_equivs); + end + return ("(%s and %s:find(%q))"):format(part, part, "^"..pattern.."$"); + else + return ("%s == %q"):format(part, match); + end +end + +local function compile_jid_match(which, match_jid) + local match_node, match_host, match_resource = jid.split(match_jid); + local conditions = {}; + conditions[#conditions+1] = compile_jid_match_part(which.."_node", match_node); + conditions[#conditions+1] = compile_jid_match_part(which.."_host", match_host); + if match_resource then + conditions[#conditions+1] = compile_jid_match_part(which.."_resource", match_resource); + end + return table.concat(conditions, " and "); +end + +function condition_handlers.TO(to) + return compile_jid_match("to", to), { "split_to" }; +end + +function condition_handlers.FROM(from) + return compile_jid_match("from", from), { "split_from" }; +end + +function condition_handlers.FROM_FULL_JID() + return "not "..compile_jid_match_part("from_resource", nil), { "split_from" }; +end + +function condition_handlers.FROM_EXACTLY(from) + local metadeps = {}; + return ("from == %s"):format(metaq(from, metadeps)), { "from", unpack(metadeps) }; +end + +function condition_handlers.TO_EXACTLY(to) + local metadeps = {}; + return ("to == %s"):format(metaq(to, metadeps)), { "to", unpack(metadeps) }; +end + +function condition_handlers.TO_SELF() + -- Intentionally not using 'to' here, as that defaults to bare JID when nil + return ("stanza.attr.to == nil"); +end + +function condition_handlers.TYPE(type) + assert(type, "Expected 'type' value to match against"); + return compile_comparison_list("(type or (name == 'message' and 'normal') or (name == 'presence' and 'available'))", type), { "type", "name" }; +end + +local function zone_check(zone, which) + local zone_var = zone; + if zone == "$local" then zone_var = "_local" end + local which_not = which == "from" and "to" or "from"; + return ("(zone_%s[%s_host] or zone_%s[%s] or zone_%s[bare_%s]) " + .."and not(zone_%s[%s_host] or zone_%s[%s] or zone_%s[bare_%s])" + ) + :format(zone_var, which, zone_var, which, zone_var, which, + zone_var, which_not, zone_var, which_not, zone_var, which_not), { + "split_to", "split_from", "bare_to", "bare_from", "zone:"..zone + }; +end + +function condition_handlers.ENTERING(zone) + return zone_check(zone, "to"); +end + +function condition_handlers.LEAVING(zone) + return zone_check(zone, "from"); +end + +-- IN ROSTER? (parameter is deprecated) +function condition_handlers.IN_ROSTER(yes_no) + local in_roster_requirement = string_to_boolean(yes_no or "yes"); -- COMPAT w/ older scripts + return "not "..(in_roster_requirement and "not" or "").." roster_entry", { "roster_entry" }; +end + +function condition_handlers.IN_ROSTER_GROUP(group) + return ("not not (roster_entry and roster_entry.groups[%q])"):format(group), { "roster_entry" }; +end + +function condition_handlers.SUBSCRIBED() + return "(bare_to == bare_from or to_node and rostermanager.is_contact_subscribed(to_node, to_host, bare_from))", + { "rostermanager", "split_to", "bare_to", "bare_from" }; +end + +function condition_handlers.PENDING_SUBSCRIPTION_FROM_SENDER() + return "(bare_to == bare_from or to_node and rostermanager.is_contact_pending_in(to_node, to_host, bare_from))", + { "rostermanager", "split_to", "bare_to", "bare_from" }; +end + +function condition_handlers.PAYLOAD(payload_ns) + return ("stanza:get_child(nil, %q)"):format(payload_ns); +end + +function condition_handlers.INSPECT(path) + if path:find("=") then + local query, match_type, value = path:match("(.-)([~/$]*)=(.*)"); + if not(query:match("#$") or query:match("@[^/]+")) then + error("Stanza path does not return a string (append # for text content or @name for value of named attribute)", 0); + end + local meta_deps = {}; + local quoted_value = ("%q"):format(value); + if match_type:find("$", 1, true) then + match_type = match_type:gsub("%$", ""); + quoted_value = meta(quoted_value, meta_deps); + end + if match_type == "~" then -- Lua pattern match + return ("(stanza:find(%q) or ''):match(%s)"):format(query, quoted_value), meta_deps; + elseif match_type == "/" then -- find literal substring + return ("(stanza:find(%q) or ''):find(%s, 1, true)"):format(query, quoted_value), meta_deps; + elseif match_type == "" then -- exact match + return ("stanza:find(%q) == %s"):format(query, quoted_value), meta_deps; + else + error("Unrecognised comparison '"..match_type.."='", 0); + end + end + return ("stanza:find(%q)"):format(path); +end + +function condition_handlers.FROM_GROUP(group_name) + return ("group_contains(%q, bare_from)"):format(group_name), { "group_contains", "bare_from" }; +end + +function condition_handlers.TO_GROUP(group_name) + return ("group_contains(%q, bare_to)"):format(group_name), { "group_contains", "bare_to" }; +end + +function condition_handlers.CROSSING_GROUPS(group_names) + local code = {}; + for group_name in group_names:gmatch("([^, ][^,]+)") do + group_name = group_name:match("^%s*(.-)%s*$"); -- Trim leading/trailing whitespace + -- Just check that's it is crossing from outside group to inside group + table.insert(code, ("(group_contains(%q, bare_to) and group_contains(%q, bare_from))"):format(group_name, group_name)) + end + return "not "..table.concat(code, " or "), { "group_contains", "bare_to", "bare_from" }; +end + +-- COMPAT w/0.12: Deprecated +function condition_handlers.FROM_ADMIN_OF(host) + return ("is_admin(bare_from, %s)"):format(host ~= "*" and metaq(host) or nil), { "is_admin", "bare_from" }; +end + +-- COMPAT w/0.12: Deprecated +function condition_handlers.TO_ADMIN_OF(host) + return ("is_admin(bare_to, %s)"):format(host ~= "*" and metaq(host) or nil), { "is_admin", "bare_to" }; +end + +-- COMPAT w/0.12: Deprecated +function condition_handlers.FROM_ADMIN() + return ("is_admin(bare_from, current_host)"), { "is_admin", "bare_from", "current_host" }; +end + +-- COMPAT w/0.12: Deprecated +function condition_handlers.TO_ADMIN() + return ("is_admin(bare_to, current_host)"), { "is_admin", "bare_to", "current_host" }; +end + +-- MAY: permission_to_check +function condition_handlers.MAY(permission_to_check) + return ("module:may(%q, event)"):format(permission_to_check); +end + +function condition_handlers.TO_ROLE(role_name) + return ("recipient_role and recipient_role.name == %q"):format(role_name), { "recipient_role" }; +end + +function condition_handlers.FROM_ROLE(role_name) + return ("sender_role and sender_role.name == %q"):format(role_name), { "sender_role" }; +end + +local day_numbers = { sun = 0, mon = 2, tue = 3, wed = 4, thu = 5, fri = 6, sat = 7 }; + +local function current_time_check(op, hour, minute) + hour, minute = tonumber(hour), tonumber(minute); + local adj_op = op == "<" and "<" or ">="; -- Start time inclusive, end time exclusive + if minute == 0 then + return "(current_hour"..adj_op..hour..")"; + else + return "((current_hour"..op..hour..") or (current_hour == "..hour.." and current_minute"..adj_op..minute.."))"; + end +end + +local function resolve_day_number(day_name) + return assert(day_numbers[day_name:sub(1,3):lower()], "Unknown day name: "..day_name); +end + +function condition_handlers.DAY(days) + local conditions = {}; + for day_range in days:gmatch("[^,]+") do + local day_start, day_end = day_range:match("(%a+)%s*%-%s*(%a+)"); + if day_start and day_end then + local day_start_num, day_end_num = resolve_day_number(day_start), resolve_day_number(day_end); + local op = "and"; + if day_end_num < day_start_num then + op = "or"; + end + table.insert(conditions, ("current_day >= %d %s current_day <= %d"):format(day_start_num, op, day_end_num)); + elseif day_range:find("%a") then + local day = resolve_day_number(day_range:match("%a+")); + table.insert(conditions, "current_day == "..day); + else + error("Unable to parse day/day range: "..day_range); + end + end + assert(#conditions>0, "Expected a list of days or day ranges"); + return "("..table.concat(conditions, ") or (")..")", { "time:day" }; +end + +function condition_handlers.TIME(ranges) + local conditions = {}; + for range in ranges:gmatch("([^,]+)") do + local clause = {}; + range = range:lower() + :gsub("(%d+):?(%d*) *am", function (h, m) return tostring(tonumber(h)%12)..":"..(tonumber(m) or "00"); end) + :gsub("(%d+):?(%d*) *pm", function (h, m) return tostring(tonumber(h)%12+12)..":"..(tonumber(m) or "00"); end); + local start_hour, start_minute = range:match("(%d+):(%d+) *%-"); + local end_hour, end_minute = range:match("%- *(%d+):(%d+)"); + local op = tonumber(start_hour) > tonumber(end_hour) and " or " or " and "; + if start_hour and end_hour then + table.insert(clause, current_time_check(">", start_hour, start_minute)); + table.insert(clause, current_time_check("<", end_hour, end_minute)); + end + if #clause == 0 then + error("Unable to parse time range: "..range); + end + table.insert(conditions, "("..table.concat(clause, " "..op.." ")..")"); + end + return table.concat(conditions, " or "), { "time:hour,min" }; +end + +function condition_handlers.LIMIT(spec) + local name, param = spec:match("^(%w+) on (.+)$"); + local meta_deps = {}; + + if not name then + name = spec:match("^%w+$"); + if not name then + error("Unable to parse LIMIT specification"); + end + else + param = meta(("%q"):format(param), meta_deps); + end + + if not param then + return ("not global_throttle_%s:poll(1)"):format(name), { "globalthrottle:"..name, unpack(meta_deps) }; + end + return ("not multi_throttle_%s:poll_on(%s, 1)"):format(name, param), { "multithrottle:"..name, unpack(meta_deps) }; +end + +function condition_handlers.ORIGIN_MARKED(name_and_time) + local name, time = name_and_time:match("^%s*([%w_]+)%s+%(([^)]+)s%)%s*$"); + if not name then + name = name_and_time:match("^%s*([%w_]+)%s*$"); + end + if not name then + error("Error parsing mark name, see documentation for usage examples"); + end + if time then + return ("(current_timestamp - (session.firewall_marked_%s or 0)) < %d"):format(idsafe(name), tonumber(time)), { "timestamp" }; + end + return ("not not session.firewall_marked_"..idsafe(name)); +end + +function condition_handlers.USER_MARKED(name_and_time) + local name, time = name_and_time:match("^%s*([%w_]+)%s+%(([^)]+)s%)%s*$"); + if not name then + name = name_and_time:match("^%s*([%w_]+)%s*$"); + end + if not name then + error("Error parsing mark name, see documentation for usage examples"); + end + if time then + return ([[( + current_timestamp - (session.firewall_marks and session.firewall_marks.%s or 0) + ) < %d]]):format(idsafe(name), tonumber(time)), { "timestamp" }; + end + return ("not not (session.firewall_marks and session.firewall_marks."..idsafe(name)..")"); +end + +function condition_handlers.SENT_DIRECTED_PRESENCE_TO_SENDER() + return "not not (session.directed and session.directed[from])", { "from" }; +end + +-- TO FULL JID? +function condition_handlers.TO_FULL_JID() + return "not not full_sessions[to]", { "to", "full_sessions" }; +end + +-- CHECK LIST: spammers contains $<@from> +function condition_handlers.CHECK_LIST(list_condition) + local list_name, expr = list_condition:match("(%S+) contains (.+)$"); + if not (list_name and expr) then + error("Error parsing list check, syntax: LISTNAME contains EXPRESSION"); + end + local meta_deps = {}; + expr = meta(("%q"):format(expr), meta_deps); + return ("list_%s:contains(%s) == true"):format(list_name, expr), { "list:"..list_name, unpack(meta_deps) }; +end + +-- SCAN: body for word in badwords +function condition_handlers.SCAN(scan_expression) + local search_name, pattern_name, list_name = scan_expression:match("(%S+) for (%S+) in (%S+)$"); + if not (search_name) then + error("Error parsing SCAN expression, syntax: SEARCH for PATTERN in LIST"); + end + return ("scan_list(list_%s, %s)"):format( + list_name, + "tokens_"..search_name.."_"..pattern_name + ), { + "scan_list", + "tokens:"..search_name.."-"..pattern_name, "list:"..list_name + }; +end + +-- COUNT: lines in body < 10 +local valid_comp_ops = { [">"] = ">", ["<"] = "<", ["="] = "==", ["=="] = "==", ["<="] = "<=", [">="] = ">=" }; +function condition_handlers.COUNT(count_expression) + local pattern_name, search_name, comparator_expression = count_expression:match("(%S+) in (%S+) (.+)$"); + if not (pattern_name) then + error("Error parsing COUNT expression, syntax: PATTERN in SEARCH COMPARATOR"); + end + local value; + comparator_expression = comparator_expression:gsub("%d+", function (value_string) + value = tonumber(value_string); + return ""; + end); + if not value then + error("Error parsing COUNT expression, expected value"); + end + local comp_op = comparator_expression:gsub("%s+", ""); + assert(valid_comp_ops[comp_op], "Error parsing COUNT expression, unknown comparison operator: "..comp_op); + return ("it_count(search_%s:gmatch(pattern_%s)) %s %d"):format( + search_name, pattern_name, comp_op, value + ), { + "it_count", + "search:"..search_name, "pattern:"..pattern_name + }; +end + +-- FROM COUNTRY: SE +-- FROM COUNTRY: code=SE +-- FROM COUNTRY: SWE +-- FROM COUNTRY: code3=SWE +-- FROM COUNTRY: continent=EU +-- FROM COUNTRY? --> NOT FROM COUNTRY: -- (for unknown/invalid) +-- TODO list support? +function condition_handlers.FROM_COUNTRY(geoip_spec) + local condition = "=="; + if not geoip_spec then + geoip_spec = "--"; + condition = "~="; + end + local field, country = geoip_spec:match("(%w+)=(%w+)"); + if not field then + if #geoip_spec == 3 then + field, country = "code3", geoip_spec; + elseif #geoip_spec == 2 then + field, country = "code", geoip_spec; + else + error("Unknown country code type"); + end + end + return ("get_geoip(session.ip, %q) %s %q"):format(field:lower(), condition, country:upper()), { "geoip_country" }; +end + +return condition_handlers; diff --git a/prosody-modules/mod_firewall/definitions.lib.lua b/prosody-modules/mod_firewall/definitions.lib.lua new file mode 100644 index 00000000..a35ba804 --- /dev/null +++ b/prosody-modules/mod_firewall/definitions.lib.lua @@ -0,0 +1,335 @@ + +-- Name arguments are unused here +-- luacheck: ignore 212 + +local definition_handlers = {}; + +local http = require "net.http"; +local timer = require "util.timer"; +local set = require"util.set"; +local new_throttle = require "util.throttle".create; +local hashes = require "util.hashes"; +local jid = require "util.jid"; +local lfs = require "lfs"; + +local multirate_cache_size = module:get_option_number("firewall_multirate_cache_limit", 1000); + +function definition_handlers.ZONE(zone_name, zone_members) + local zone_member_list = {}; + for member in zone_members:gmatch("[^, ]+") do + zone_member_list[#zone_member_list+1] = member; + end + return set.new(zone_member_list)._items; +end + +-- Helper function used by RATE handler +local function evict_only_unthrottled(name, throttle) + throttle:update(); + -- Check whether the throttle is at max balance (i.e. totally safe to forget about it) + if throttle.balance < throttle.max then + -- Not safe to forget + return false; + end +end + +function definition_handlers.RATE(name, line) + local rate = assert(tonumber(line:match("([%d.]+)")), "Unable to parse rate"); + local burst = tonumber(line:match("%(%s*burst%s+([%d.]+)%s*%)")) or 1; + local max_throttles = tonumber(line:match("%(%s*entries%s+([%d]+)%s*%)")) or multirate_cache_size; + local deny_when_full = not line:match("%(allow overflow%)"); + return { + single = function () + return new_throttle(rate*burst, burst); + end; + + multi = function () + local cache = require "util.cache".new(max_throttles, deny_when_full and evict_only_unthrottled or nil); + return { + poll_on = function (_, key, amount) + assert(key, "no key"); + local throttle = cache:get(key); + if not throttle then + throttle = new_throttle(rate*burst, burst); + if not cache:set(key, throttle) then + module:log("warn", "Multirate '%s' has hit its maximum number of active throttles (%d), denying new events", name, max_throttles); + return false; + end + end + return throttle:poll(amount); + end; + } + end; + }; +end + +local list_backends = { + -- %LIST name: memory (limit: number) + memory = { + init = function (self, type, opts) + if opts.limit then + local have_cache_lib, cache_lib = pcall(require, "util.cache"); + if not have_cache_lib then + error("In-memory lists with a size limit require Prosody 0.10"); + end + self.cache = cache_lib.new((assert(tonumber(opts.limit), "Invalid list limit"))); + if not self.cache.table then + error("In-memory lists with a size limit require a newer version of Prosody 0.10"); + end + self.items = self.cache:table(); + else + self.items = {}; + end + end; + add = function (self, item) + self.items[item] = true; + end; + remove = function (self, item) + self.items[item] = nil; + end; + contains = function (self, item) + return self.items[item] == true; + end; + }; + + -- %LIST name: http://example.com/ (ttl: number, pattern: pat, hash: sha1) + http = { + init = function (self, url, opts) + local poll_interval = assert(tonumber(opts.ttl or "3600"), "invalid ttl for <"..url.."> (expected number of seconds)"); + local pattern = opts.pattern or "([^\r\n]+)\r?\n"; + assert(pcall(string.match, "", pattern), "invalid pattern for <"..url..">"); + if opts.hash then + assert(opts.hash:match("^%w+$") and type(hashes[opts.hash]) == "function", "invalid hash function: "..opts.hash); + self.hash_function = hashes[opts.hash]; + end + local etag; + local failure_count = 0; + local retry_intervals = { 60, 120, 300 }; + -- By default only check the certificate if net.http supports SNI + local sni_supported = http.feature and http.features.sni; + local insecure = false; + if opts.checkcert == "never" then + insecure = true; + elseif (opts.checkcert == nil or opts.checkcert == "when-sni") and not sni_supported then + insecure = false; + end + local function update_list() + http.request(url, { + insecure = insecure; + headers = { + ["If-None-Match"] = etag; + }; + }, function (body, code, response) + local next_poll = poll_interval; + if code == 200 and body then + etag = response.headers.etag; + local items = {}; + for entry in body:gmatch(pattern) do + items[entry] = true; + end + self.items = items; + module:log("debug", "Fetched updated list from <%s>", url); + elseif code == 304 then + module:log("debug", "List at <%s> is unchanged", url); + elseif code == 0 or (code >= 400 and code <=599) then + module:log("warn", "Failed to fetch list from <%s>: %d %s", url, code, tostring(body)); + failure_count = failure_count + 1; + next_poll = retry_intervals[failure_count] or retry_intervals[#retry_intervals]; + end + if next_poll > 0 then + timer.add_task(next_poll+math.random(0, 60), update_list); + end + end); + end + update_list(); + end; + add = function () + end; + remove = function () + end; + contains = function (self, item) + if self.hash_function then + item = self.hash_function(item); + end + return self.items and self.items[item] == true; + end; + }; + + -- %LIST: file:/path/to/file + file = { + init = function (self, file_spec, opts) + local n, items = 0, {}; + self.items = items; + local filename = file_spec:gsub("^file:", ""); + if opts.missing == "ignore" and not lfs.attributes(filename, "mode") then + module:log("debug", "Ignoring missing list file: %s", filename); + return; + end + local file, err = io.open(filename); + if not file then + module:log("warn", "Failed to open list from %s: %s", filename, err); + return; + else + for line in file:lines() do + if not items[line] then + n = n + 1; + items[line] = true; + end + end + end + module:log("debug", "Loaded %d items from %s", n, filename); + end; + add = function (self, item) + self.items[item] = true; + end; + remove = function (self, item) + self.items[item] = nil; + end; + contains = function (self, item) + return self.items and self.items[item] == true; + end; + }; + + -- %LIST: pubsub:pubsub.example.com/node + -- TODO or the actual URI scheme? Bit overkill maybe? + -- TODO Publish items back to the service? + -- Step 1: Receiving pubsub events and storing them in the list + -- We'll start by using only the item id. + -- TODO Invent some custom schema for this? Needed for just a set of strings? + pubsubitemid = { + init = function(self, pubsub_spec, opts) + local service_addr, node = pubsub_spec:match("^pubsubitemid:([^/]*)/(.*)"); + if not service_addr then + module:log("warn", "Invalid list specification (expected 'pubsubitemid:/', got: '%s')", pubsub_spec); + return; + end + module:depends("pubsub_subscription"); + module:add_item("pubsub-subscription", { + service = service_addr; + node = node; + on_subscribed = function () + self.items = {}; + end; + on_item = function (event) + self:add(event.item.attr.id); + end; + on_retract = function (event) + self:remove(event.item.attr.id); + end; + on_purge = function () + self.items = {}; + end; + on_unsubscribed = function () + self.items = nil; + end; + on_delete= function () + self.items = nil; + end; + }); + -- TODO Initial fetch? Or should mod_pubsub_subscription do this? + end; + add = function (self, item) + if self.items then + self.items[item] = true; + end + end; + remove = function (self, item) + if self.items then + self.items[item] = nil; + end + end; + contains = function (self, item) + return self.items and self.items[item] == true; + end; + }; +}; +list_backends.https = list_backends.http; + +local normalize_functions = { + upper = string.upper, lower = string.lower; + md5 = hashes.md5, sha1 = hashes.sha1, sha256 = hashes.sha256; + prep = jid.prep, bare = jid.bare; +}; + +local function wrap_list_method(list_method, filter) + return function (self, item) + return list_method(self, filter(item)); + end +end + +local function create_list(list_backend, list_def, opts) + if not list_backends[list_backend] then + error("Unknown list type '"..list_backend.."'", 0); + end + local list = setmetatable({}, { __index = list_backends[list_backend] }); + if list.init then + list:init(list_def, opts); + end + if opts.filter then + local filters = {}; + for func_name in opts.filter:gmatch("[%w_]+") do + if func_name == "log" then + table.insert(filters, function (s) + --print("&&&&&", s); + module:log("debug", "Checking list <%s> for: %s", list_def, s); + return s; + end); + else + assert(normalize_functions[func_name], "Unknown list filter: "..func_name); + table.insert(filters, normalize_functions[func_name]); + end + end + + local filter; + local n = #filters; + if n == 1 then + filter = filters[1]; + else + function filter(s) + for i = 1, n do + s = filters[i](s or ""); + end + return s; + end + end + + list.add = wrap_list_method(list.add, filter); + list.remove = wrap_list_method(list.remove, filter); + list.contains = wrap_list_method(list.contains, filter); + end + return list; +end + +--[[ +%LIST spammers: memory (source: /etc/spammers.txt) + +%LIST spammers: memory (source: /etc/spammers.txt) + + +%LIST spammers: http://example.com/blacklist.txt +]] + +function definition_handlers.LIST(list_name, list_definition) + local list_backend = list_definition:match("^%w+"); + local opts = {}; + local opt_string = list_definition:match("^%S+%s+%((.+)%)"); + if opt_string then + for opt_k, opt_v in opt_string:gmatch("(%w+): ?([^,]+)") do + opts[opt_k] = opt_v; + end + end + return create_list(list_backend, list_definition:match("^%S+"), opts); +end + +function definition_handlers.PATTERN(name, pattern) + local ok, err = pcall(string.match, "", pattern); + if not ok then + error("Invalid pattern '"..name.."': "..err); + end + return pattern; +end + +function definition_handlers.SEARCH(name, pattern) + return pattern; +end + +return definition_handlers; diff --git a/prosody-modules/mod_firewall/marks.lib.lua b/prosody-modules/mod_firewall/marks.lib.lua new file mode 100644 index 00000000..3c9bbb06 --- /dev/null +++ b/prosody-modules/mod_firewall/marks.lib.lua @@ -0,0 +1,35 @@ +local mark_storage = module:open_store("firewall_marks"); +local mark_map_storage = module:open_store("firewall_marks", "map"); + +local user_sessions = prosody.hosts[module.host].sessions; + +module:hook("firewall/marked/user", function (event) + local user = user_sessions[event.username]; + local marks = user and user.firewall_marks; + if user and not marks then + -- Load marks from storage to cache on the user object + marks = mark_storage:get(event.username) or {}; + user.firewall_marks = marks; --luacheck: ignore 122 + end + if marks then + marks[event.mark] = event.timestamp; + end + local ok, err = mark_map_storage:set(event.username, event.mark, event.timestamp); + if not ok then + module:log("error", "Failed to mark user %q with %q: %s", event.username, event.mark, err); + end + return true; +end, -1); + +module:hook("firewall/unmarked/user", function (event) + local user = user_sessions[event.username]; + local marks = user and user.firewall_marks; + if marks then + marks[event.mark] = nil; + end + local ok, err = mark_map_storage:set(event.username, event.mark, nil); + if not ok then + module:log("error", "Failed to unmark user %q with %q: %s", event.username, event.mark, err); + end + return true; +end, -1); diff --git a/prosody-modules/mod_firewall/mod_firewall.lua b/prosody-modules/mod_firewall/mod_firewall.lua new file mode 100644 index 00000000..62cfdbd7 --- /dev/null +++ b/prosody-modules/mod_firewall/mod_firewall.lua @@ -0,0 +1,863 @@ + +local lfs = require "lfs"; +local resolve_relative_path = require "core.configmanager".resolve_relative_path; +local envload = require "util.envload".envload; +local logger = require "util.logger".init; +local it = require "util.iterators"; +local set = require "util.set"; + +local have_features, features = pcall(require, "core.features"); +features = have_features and features.available or set.new(); + +-- [definition_type] = definition_factory(param) +local definitions = module:shared("definitions"); + +-- When a definition instance has been instantiated, it lives here +-- [definition_type][definition_name] = definition_object +local active_definitions = { + ZONE = { + -- Default zone that includes all local hosts + ["$local"] = setmetatable({}, { __index = prosody.hosts }); + }; +}; + +local default_chains = { + preroute = { + type = "event"; + priority = 0.1; + "pre-message/bare", "pre-message/full", "pre-message/host"; + "pre-presence/bare", "pre-presence/full", "pre-presence/host"; + "pre-iq/bare", "pre-iq/full", "pre-iq/host"; + }; + deliver = { + type = "event"; + priority = 0.1; + "message/bare", "message/full", "message/host"; + "presence/bare", "presence/full", "presence/host"; + "iq/bare", "iq/full", "iq/host"; + }; + deliver_remote = { + type = "event"; "route/remote"; + priority = 0.1; + }; +}; + +local extra_chains = module:get_option("firewall_extra_chains", {}); + +local chains = {}; +for k,v in pairs(default_chains) do + chains[k] = v; +end +for k,v in pairs(extra_chains) do + chains[k] = v; +end + +-- Returns the input if it is safe to be used as a variable name, otherwise nil +function idsafe(name) + return name:match("^%a[%w_]*$"); +end + +local meta_funcs = { + bare = function (code) + return "jid_bare("..code..")", {"jid_bare"}; + end; + node = function (code) + return "(jid_split("..code.."))", {"jid_split"}; + end; + host = function (code) + return "(select(2, jid_split("..code..")))", {"jid_split"}; + end; + resource = function (code) + return "(select(3, jid_split("..code..")))", {"jid_split"}; + end; +}; + +-- Run quoted (%q) strings through this to allow them to contain code. e.g.: LOG=Received: $(stanza:top_tag()) +function meta(s, deps, extra) + return (s:gsub("$(%b())", function (expr) + expr = expr:gsub("\\(.)", "%1"); + return [["..tostring(]]..expr..[[).."]]; + end) + :gsub("$(%b<>)", function (expr) + expr = expr:sub(2,-2); + local default = ""; + expr = expr:gsub("||(%b\"\")$", function (default_string) + default = stripslashes(default_string:sub(2,-2)); + return ""; + end); + local func_chain = expr:match("|[%w|]+$"); + if func_chain then + expr = expr:sub(1, -1-#func_chain); + end + local code; + if expr:match("^@") then + -- Skip stanza:find() for simple attribute lookup + local attr_name = expr:sub(2); + if deps and (attr_name == "to" or attr_name == "from" or attr_name == "type") then + -- These attributes may be cached in locals + code = attr_name; + table.insert(deps, attr_name); + else + code = "stanza.attr["..("%q"):format(attr_name).."]"; + end + elseif expr:match("^%w+#$") then + code = ("stanza:get_child_text(%q)"):format(expr:sub(1, -2)); + else + code = ("stanza:find(%q)"):format(expr); + end + if func_chain then + for func_name in func_chain:gmatch("|(%w+)") do + -- to/from are already available in local variables, use those if possible + if (code == "to" or code == "from") and func_name == "bare" then + code = "bare_"..code; + table.insert(deps, code); + elseif (code == "to" or code == "from") and (func_name == "node" or func_name == "host" or func_name == "resource") then + table.insert(deps, "split_"..code); + code = code.."_"..func_name; + else + assert(meta_funcs[func_name], "unknown function: "..func_name); + local new_code, new_deps = meta_funcs[func_name](code); + code = new_code; + if new_deps and #new_deps > 0 then + assert(deps, "function not supported here: "..func_name); + for _, dep in ipairs(new_deps) do + table.insert(deps, dep); + end + end + end + end + end + return "\"..tostring("..code.." or "..("%q"):format(default)..")..\""; + end) + :gsub("$$(%a+)", extra or {}) + :gsub([[^""%.%.]], "") + :gsub([[%.%.""$]], "")); +end + +function metaq(s, ...) + return meta(("%q"):format(s), ...); +end + +local escape_chars = { + a = "\a", b = "\b", f = "\f", n = "\n", r = "\r", t = "\t", + v = "\v", ["\\"] = "\\", ["\""] = "\"", ["\'"] = "\'" +}; +function stripslashes(s) + return (s:gsub("\\(.)", escape_chars)); +end + +-- Dependency locations: +-- +-- +-- function handler() +-- +-- if then +-- +-- end +-- end + +local available_deps = { + st = { global_code = [[local st = require "util.stanza";]]}; + it = { global_code = [[local it = require "util.iterators";]]}; + it_count = { global_code = [[local it_count = it.count;]], depends = { "it" } }; + current_host = { global_code = [[local current_host = module.host;]] }; + jid_split = { + global_code = [[local jid_split = require "util.jid".split;]]; + }; + jid_bare = { + global_code = [[local jid_bare = require "util.jid".bare;]]; + }; + to = { local_code = [[local to = stanza.attr.to or jid_bare(session.full_jid);]]; depends = { "jid_bare" } }; + from = { local_code = [[local from = stanza.attr.from;]] }; + type = { local_code = [[local type = stanza.attr.type;]] }; + name = { local_code = [[local name = stanza.name;]] }; + split_to = { -- The stanza's split to address + depends = { "jid_split", "to" }; + local_code = [[local to_node, to_host, to_resource = jid_split(to);]]; + }; + split_from = { -- The stanza's split from address + depends = { "jid_split", "from" }; + local_code = [[local from_node, from_host, from_resource = jid_split(from);]]; + }; + bare_to = { depends = { "jid_bare", "to" }, local_code = "local bare_to = jid_bare(to)"}; + bare_from = { depends = { "jid_bare", "from" }, local_code = "local bare_from = jid_bare(from)"}; + group_contains = { + global_code = [[local group_contains = module:depends("groups").group_contains]]; + }; + is_admin = require"core.usermanager".is_admin and { global_code = [[local is_admin = require "core.usermanager".is_admin;]]} or nil; + get_jid_role = require "core.usermanager".get_jid_role and { global_code = [[local get_jid_role = require "core.usermanager".get_jid_role;]] } or nil; + core_post_stanza = { global_code = [[local core_post_stanza = prosody.core_post_stanza;]] }; + zone = { global_code = function (zone) + local var = zone; + if var == "$local" then + var = "_local"; -- See #1090 + else + assert(idsafe(var), "Invalid zone name: "..zone); + end + return ("local zone_%s = zones[%q] or {};"):format(var, zone); + end }; + date_time = { global_code = [[local os_date = os.date]]; local_code = [[local current_date_time = os_date("*t");]] }; + time = { local_code = function (what) + local defs = {}; + for field in what:gmatch("%a+") do + table.insert(defs, ("local current_%s = current_date_time.%s;"):format(field, field)); + end + return table.concat(defs, " "); + end, depends = { "date_time" }; }; + timestamp = { global_code = [[local get_time = require "socket".gettime;]]; local_code = [[local current_timestamp = get_time();]]; }; + globalthrottle = { + global_code = function (throttle) + assert(idsafe(throttle), "Invalid rate limit name: "..throttle); + assert(active_definitions.RATE[throttle], "Unknown rate limit: "..throttle); + return ("local global_throttle_%s = rates.%s:single();"):format(throttle, throttle); + end; + }; + multithrottle = { + global_code = function (throttle) + assert(pcall(require, "util.cache"), "Using LIMIT with 'on' requires Prosody 0.10 or higher"); + assert(idsafe(throttle), "Invalid rate limit name: "..throttle); + assert(active_definitions.RATE[throttle], "Unknown rate limit: "..throttle); + return ("local multi_throttle_%s = rates.%s:multi();"):format(throttle, throttle); + end; + }; + full_sessions = { + global_code = [[local full_sessions = prosody.full_sessions;]]; + }; + rostermanager = { + global_code = [[local rostermanager = require "core.rostermanager";]]; + }; + roster_entry = { + local_code = [[local roster_entry = (to_node and rostermanager.load_roster(to_node, to_host) or {})[bare_from];]]; + depends = { "rostermanager", "split_to", "bare_from" }; + }; + list = { global_code = function (list) + assert(idsafe(list), "Invalid list name: "..list); + assert(active_definitions.LIST[list], "Unknown list: "..list); + return ("local list_%s = lists[%q];"):format(list, list); + end + }; + search = { + local_code = function (search_name) + local search_path = assert(active_definitions.SEARCH[search_name], "Undefined search path: "..search_name); + return ("local search_%s = tostring(stanza:find(%q) or \"\")"):format(search_name, search_path); + end; + }; + pattern = { + local_code = function (pattern_name) + local pattern = assert(active_definitions.PATTERN[pattern_name], "Undefined pattern: "..pattern_name); + return ("local pattern_%s = %q"):format(pattern_name, pattern); + end; + }; + tokens = { + local_code = function (search_and_pattern) + local search_name, pattern_name = search_and_pattern:match("^([^%-]+)-(.+)$"); + local code = ([[local tokens_%s_%s = {}; + if search_%s then + for s in search_%s:gmatch(pattern_%s) do + tokens_%s_%s[s] = true; + end + end + ]]):format(search_name, pattern_name, search_name, search_name, pattern_name, search_name, pattern_name); + return code, { "search:"..search_name, "pattern:"..pattern_name }; + end; + }; + sender_role = { + local_code = [[local sender_role = get_jid_role(bare_from, current_host)]]; + depends = { "bare_from", "current_host", "get_jid_role" }; + }; + recipient_role = { + local_code = [[local recipient_role = get_jid_role(bare_to, current_host)]]; + depends = { "bare_to", "current_host", "get_jid_role" }; + }; + scan_list = { + global_code = [[local function scan_list(list, items) for item in pairs(items) do if list:contains(item) then return true; end end end]]; + }; + iplib = { + global_code = [[local iplib = require "util.ip";]]; + }; + geoip_country = { + global_code = [[ +local geoip_country = require "geoip.country"; +local geov4 = geoip_country.open(module:get_option_string("geoip_ipv4_country", "/usr/share/GeoIP/GeoIP.dat")); +local geov6 = geoip_country.open(module:get_option_string("geoip_ipv6_country", "/usr/share/GeoIP/GeoIPv6.dat")); +local function get_geoip(ips, what) + if not ips then + return "--"; + end + local ip = iplib.new_ip(ips); + if not ip then + return "--"; + end + if ip.proto == "IPv6" and geov6 then + local geoinfo = geoinfo:query_by_addr6(ip.addr); + if geoinfo then + return geoinfo[what or "code"]; + end + elseif ip.proto == "IPv4" and geov4 then + local geoinfo = geoinfo:query_by_addr(ip.addr); + if geoinfo then + return geoinfo[what or "code"]; + end + end + return "--"; +end + ]]; + depends = { + "iplib" + } + }; + new_short_id = { + global_code = [[local new_short_id = require "util.id".short;]]; + }; + new_medium_id = { + global_code = [[local new_medium_id = require "util.id".medium;]]; + }; + new_long_id = { + global_code = [[local new_long_id = require "util.id".long;]]; + }; + + trace = { + global_code = [[local trace_init = module:require("trace").init;]]; + }; +}; + +local function include_dep(dependency, code) + local dep, dep_param = dependency:match("^([^:]+):?(.*)$"); + local dep_info = available_deps[dep]; + if not dep_info then + module:log("error", "Dependency not found: %s", dep); + return; + end + if code.included_deps[dependency] ~= nil then + if code.included_deps[dependency] ~= true then + module:log("error", "Circular dependency on %s", dep); + end + return; + end + code.included_deps[dependency] = false; -- Pending flag (used to detect circular references) + for _, dep_dep in ipairs(dep_info.depends or {}) do + include_dep(dep_dep, code); + end + if dep_info.global_code then + if dep_param ~= "" then + local global_code, deps = dep_info.global_code(dep_param); + if deps then + for _, dep_dep in ipairs(deps) do + include_dep(dep_dep, code); + end + end + table.insert(code.global_header, global_code); + else + table.insert(code.global_header, dep_info.global_code); + end + end + if dep_info.local_code then + if dep_param ~= "" then + local local_code, deps = dep_info.local_code(dep_param); + if deps then + for _, dep_dep in ipairs(deps) do + include_dep(dep_dep, code); + end + end + table.insert(code, "\n\t\t-- "..dep.."\n\t\t"..local_code.."\n"); + else + table.insert(code, "\n\t\t-- "..dep.."\n\t\t"..dep_info.local_code.."\n"); + end + end + code.included_deps[dependency] = true; +end + +local definition_handlers = module:require("definitions"); +local condition_handlers = module:require("conditions"); +local action_handlers = module:require("actions"); + +if module:get_option_boolean("firewall_experimental_user_marks", true) then + module:require"marks"; +end + +local function new_rule(ruleset, chain, line_no) + assert(chain, "no chain specified"); + local rule = { conditions = {}, actions = {}, deps = {}, line_no = line_no }; + table.insert(ruleset[chain], rule); + return rule; +end + +local function parse_firewall_rules(filename) + local line_no = 0; + + local function errmsg(err) + return "Error compiling "..filename.." on line "..line_no..": "..err; + end + + local metadata = { debug = {} }; + local ruleset = { + deliver = {}; + }; + + local chain = "deliver"; -- Default chain + local rule; + + local file, err = io.open(filename); + if not file then return nil, err; end + + local state; -- nil -> "rules" -> "actions" -> nil -> ... + + local line_hold; + for line in file:lines() do + line = line:match("^%s*(.-)%s*$"); + if line_hold and line:sub(-1,-1) ~= "\\" then + line = line_hold..line; + line_hold = nil; + elseif line:sub(-1,-1) == "\\" then + line_hold = (line_hold or "")..line:sub(1,-2); + end + line_no = line_no + 1; + + if line_hold or line:find("^[#;]") then -- luacheck: ignore 542 + -- No action; comment or partial line + elseif line == "" then + if state == "rules" then + return nil, ("Expected an action on line %d for preceding criteria") + :format(line_no); + end + state = nil; + elseif not(state) and line:sub(1, 2) == "::" then + chain = line:gsub("^::%s*", ""); + local chain_info = chains[chain]; + if not chain_info then + if chain:match("^user/") then + chains[chain] = { type = "event", priority = 1, pass_return = false }; + else + return nil, errmsg("Unknown chain: "..chain); + end + elseif chain_info.type ~= "event" then + return nil, errmsg("Only event chains supported at the moment"); + end + ruleset[chain] = ruleset[chain] or {}; + elseif not(state) and line:sub(1, 2) == "@@" then + local k, v = line:match("^@@%s*([^%s=]+)%s*=%s*(.+)$"); + if not k then + return nil, errmsg("Unable to parse metadata assignment (expected '@@ key = value')"); + end + metadata[k] = v; + elseif not(state) and line:sub(1,1) == "%" then -- Definition (zone, limit, etc.) + local what, name = line:match("^%%%s*([%w_]+) +([^ :]+)"); + if not definition_handlers[what] then + return nil, errmsg("Definition of unknown object: "..what); + elseif not name or not idsafe(name) then + return nil, errmsg("Invalid "..what.." name"); + end + + local val = line:match(": ?(.*)$"); + if not val and line:find(":<") then -- Read from file + local fn = line:match(":< ?(.-)%s*$"); + if not fn then + return nil, errmsg("Unable to parse filename"); + end + local f, err = io.open(fn); + if not f then return nil, errmsg(err); end + val = f:read("*a"):gsub("\r?\n", " "):gsub("%s+$", ""); + end + if not val then + return nil, errmsg("No value given for definition"); + end + val = stripslashes(val); + local ok, ret = pcall(definition_handlers[what], name, val); + if not ok then + return nil, errmsg(ret); + end + + if not active_definitions[what] then + active_definitions[what] = {}; + end + active_definitions[what][name] = ret; + elseif line:find("^[%w_ ]+[%.=]") then + -- Action + if state == nil then + -- This is a standalone action with no conditions + rule = new_rule(ruleset, chain); + end + state = "actions"; + -- Action handlers? + local action = line:match("^[%w_ ]+"):upper():gsub(" ", "_"); + if not action_handlers[action] then + return nil, ("Unknown action on line %d: %s"):format(line_no, action or ""); + end + table.insert(rule.actions, "-- "..line) + local ok, action_string, action_deps = pcall(action_handlers[action], line:match("=(.+)$")); + if not ok then + return nil, errmsg(action_string); + end + table.insert(rule.actions, action_string); + for _, dep in ipairs(action_deps or {}) do + table.insert(rule.deps, dep); + end + elseif state == "actions" then -- state is actions but action pattern did not match + state = nil; -- Awaiting next rule, etc. + table.insert(ruleset[chain], rule); -- FIXME: Is this a bug? Rule should have already been inserted by new_rule()? + rule = nil; + else + -- Condition + if not state then -- Starting a new rule block? + state = "rules"; + rule = new_rule(ruleset, chain, line_no); + end + -- Check standard modifiers for the condition (e.g. NOT) + local negated; + local condition = line:match("^[^:=%.?]*"); + if condition:find("%f[%w]NOT%f[^%w]") then + local s, e = condition:match("%f[%w]()NOT()%f[^%w]"); + condition = (condition:sub(1,s-1)..condition:sub(e+1, -1)):match("^%s*(.-)%s*$"); + negated = true; + end + condition = condition:gsub(" ", "_"); + if not condition_handlers[condition] then + return nil, ("Unknown condition on line %d: %s"):format(line_no, (condition:gsub("_", " "))); + end + -- Get the code for this condition + local ok, condition_code, condition_deps = pcall(condition_handlers[condition], line:match(":%s?(.+)$")); + if not ok then + return nil, errmsg(condition_code); + end + if negated then condition_code = "not("..condition_code..")"; end + table.insert(rule.conditions, condition_code); + for _, dep in ipairs(condition_deps or {}) do + table.insert(rule.deps, dep); + end + end + end + return ruleset, metadata; +end + +local function process_firewall_rules(ruleset, metadata) + -- Compile ruleset and return complete code + + local chain_handlers = {}; + + -- Loop through the chains in the parsed ruleset (e.g. incoming, outgoing) + for chain_name, rules in pairs(ruleset) do + local code = { included_deps = {}, global_header = {} }; + local condition_uses = {}; + -- This inner loop assumes chain is an event-based, not a filter-based + -- chain (filter-based will be added later) + for _, rule in ipairs(rules) do + for _, condition in ipairs(rule.conditions) do + if condition:find("^not%(.+%)$") then + condition = condition:match("^not%((.+)%)$"); + end + condition_uses[condition] = (condition_uses[condition] or 0) + 1; + end + end + + if metadata.trace then + include_dep("trace", code); + table.insert(code, ("local trace = trace_init(%q, %q);"):format(metadata.filename, chain_name)) + end + + local condition_cache, n_conditions = {}, 0; + for rule_n, rule in ipairs(rules) do + for _, dep in ipairs(rule.deps) do + include_dep(dep, code); + end + table.insert(code, "\n\t\t"); + local rule_code; + if #rule.conditions > 0 then + for i, condition in ipairs(rule.conditions) do + local negated = condition:match("^not%(.+%)$"); + if negated then + condition = condition:match("^not%((.+)%)$"); + end + if condition_uses[condition] > 1 then + local name = condition_cache[condition]; + if not name then + n_conditions = n_conditions + 1; + name = "condition"..n_conditions; + condition_cache[condition] = name; + table.insert(code, "local "..name.." = "..condition..";\n\t\t"); + end + rule.conditions[i] = (negated and "not(" or "")..name..(negated and ")" or ""); + else + rule.conditions[i] = (negated and "not(" or "(")..condition..")"; + end + + if metadata.trace then + -- Wrap each condition in a tracer + rule.conditions[i] = ("trace(%d, %d, %s)"):format(rule_n, i, rule.conditions[i]); + end + end + + if metadata.trace then + -- Trace overall action + table.insert(rule.actions, 1, ("trace(%d, nil, true)"):format(rule_n)); + table.insert(rule.actions, ("else trace(%d, nil, false)"):format(rule_n)); + end + + rule_code = "if "..table.concat(rule.conditions, " and ").." then\n\t\t\t" + ..table.concat(rule.actions, "\n\t\t\t") + .."\n\t\tend\n"; + else + rule_code = table.concat(rule.actions, "\n\t\t"); + end + table.insert(code, rule_code); + end + + for name in pairs(definition_handlers) do + table.insert(code.global_header, 1, "local "..name:lower().."s = definitions."..name..";"); + end + + local code_string = "return function (definitions, fire_event, log, module, pass_return)\n\t" + ..table.concat(code.global_header, "\n\t") + .."\n\tlocal db = require 'util.debug';\n\n\t" + .."return function (event)\n\t\t" + .."local stanza, session = event.stanza, event.origin;\n" + ..table.concat(code, "") + .."\n\tend;\nend"; + + chain_handlers[chain_name] = code_string; + end + + return chain_handlers; +end + +local function compile_firewall_rules(filename) + local ruleset, metadata = parse_firewall_rules(filename); + if not ruleset then return nil, metadata; end + local chain_handlers = process_firewall_rules(ruleset, metadata); + return chain_handlers; +end + +-- Compile handler code into a factory that produces a valid event handler. Factory accepts +-- a value to be returned on PASS +local function compile_handler(code_string, filename) + -- Prepare event handler function + local chunk, err = envload(code_string, "="..filename, _G); + if not chunk then + return nil, "Error compiling (probably a compiler bug, please report): "..err; + end + local function fire_event(name, data) + return module:fire_event(name, data); + end + local init_ok, initialized_chunk = pcall(chunk); + if not init_ok then + return nil, "Error initializing compiled rules: "..initialized_chunk; + end + return function (pass_return) + return initialized_chunk(active_definitions, fire_event, logger(filename), module, pass_return); -- Returns event handler with upvalues + end +end + +local function resolve_script_path(script_path) + local relative_to = prosody.paths.config; + if script_path:match("^module:") then + relative_to = module:get_directory(); + script_path = script_path:match("^module:(.+)$"); + end + return resolve_relative_path(relative_to, script_path); +end + +-- [filename] = { last_modified = ..., events_hooked = { [name] = handler } } +local loaded_scripts = {}; + +function load_script(script) + script = resolve_script_path(script); + local last_modified = (lfs.attributes(script) or {}).modification or os.time(); + if loaded_scripts[script] then + if loaded_scripts[script].last_modified == last_modified then + return; -- Already loaded, and source file hasn't changed + end + module:log("debug", "Reloading %s", script); + -- Already loaded, but the source file has changed + -- unload it now, and we'll load the new version below + unload_script(script, true); + end + local chain_functions, err = compile_firewall_rules(script); + + if not chain_functions then + module:log("error", "Error compiling %s: %s", script, err or "unknown error"); + return; + end + + -- Loop through the chains in the script, and for each chain attach the compiled code to the + -- relevant events, keeping track in events_hooked so we can cleanly unload later + local events_hooked = {}; + for chain, handler_code in pairs(chain_functions) do + local new_handler, err = compile_handler(handler_code, "mod_firewall::"..chain); + if not new_handler then + module:log("error", "Compilation error for %s: %s", script, err); + else + local chain_definition = chains[chain]; + if chain_definition and chain_definition.type == "event" then + local handler = new_handler(chain_definition.pass_return); + for _, event_name in ipairs(chain_definition) do + events_hooked[event_name] = handler; + module:hook(event_name, handler, chain_definition.priority); + end + elseif not chain:sub(1, 5) == "user/" then + module:log("warn", "Unknown chain %q", chain); + end + local event_name, handler = "firewall/chains/"..chain, new_handler(false); + events_hooked[event_name] = handler; + module:hook(event_name, handler); + end + end + loaded_scripts[script] = { last_modified = last_modified, events_hooked = events_hooked }; + module:log("debug", "Loaded %s", script); +end + +--COMPAT w/0.9 (no module:unhook()!) +local function module_unhook(event, handler) + return module:unhook_object_event((hosts[module.host] or prosody).events, event, handler); +end + +function unload_script(script, is_reload) + script = resolve_script_path(script); + local script_info = loaded_scripts[script]; + if not script_info then + return; -- Script not loaded + end + local events_hooked = script_info.events_hooked; + for event_name, event_handler in pairs(events_hooked) do + module_unhook(event_name, event_handler); + events_hooked[event_name] = nil; + end + loaded_scripts[script] = nil; + if not is_reload then + module:log("debug", "Unloaded %s", script); + end +end + +-- Given a set of scripts (e.g. from config) figure out which ones need to +-- be loaded, which are already loaded but need unloading, and which to reload +function load_unload_scripts(script_list) + local wanted_scripts = script_list / resolve_script_path; + local currently_loaded = set.new(it.to_array(it.keys(loaded_scripts))); + local scripts_to_unload = currently_loaded - wanted_scripts; + for script in wanted_scripts do + -- If the script is already loaded, this is fine - it will + -- reload the script for us if the file has changed + load_script(script); + end + for script in scripts_to_unload do + unload_script(script); + end +end + +function module.load() + if not prosody.arg then return end -- Don't run in prosodyctl + local firewall_scripts = module:get_option_set("firewall_scripts", {}); + load_unload_scripts(firewall_scripts); + -- Replace contents of definitions table (shared) with active definitions + for k in it.keys(definitions) do definitions[k] = nil; end + for k,v in pairs(active_definitions) do definitions[k] = v; end +end + +function module.save() + return { active_definitions = active_definitions, loaded_scripts = loaded_scripts }; +end + +function module.restore(state) + active_definitions = state.active_definitions; + loaded_scripts = state.loaded_scripts; +end + +module:hook_global("config-reloaded", function () + load_unload_scripts(module:get_option_set("firewall_scripts", {})); +end); + +function module.command(arg) + if not arg[1] or arg[1] == "--help" then + require"util.prosodyctl".show_usage([[mod_firewall ]], [[Compile files with firewall rules to Lua code]]); + return 1; + end + local verbose = arg[1] == "-v"; + if verbose then table.remove(arg, 1); end + + if arg[1] == "test" then + table.remove(arg, 1); + return module:require("test")(arg); + end + + local serialize = require "util.serialization".serialize; + if verbose then + print("local logger = require \"util.logger\".init;"); + print(); + print("local function fire_event(name, data)\n\tmodule:fire_event(name, data)\nend"); + print(); + end + + for _, filename in ipairs(arg) do + filename = resolve_script_path(filename); + print("do -- File "..filename); + local chain_functions = assert(compile_firewall_rules(filename)); + if verbose then + print(); + print("local active_definitions = "..serialize(active_definitions)..";"); + print(); + end + local c = 0; + for chain, handler_code in pairs(chain_functions) do + c = c + 1; + print("---- Chain "..chain:gsub("_", " ")); + local chain_func_name = "chain_"..tostring(c).."_"..chain:gsub("%p", "_"); + if not verbose then + print(("%s = %s;"):format(chain_func_name, handler_code:sub(8))); + else + + print(("local %s = (%s)(active_definitions, fire_event, logger(%q));"):format(chain_func_name, handler_code:sub(8), filename)); + print(); + + local chain_definition = chains[chain]; + if chain_definition and chain_definition.type == "event" then + for _, event_name in ipairs(chain_definition) do + print(("module:hook(%q, %s, %d);"):format(event_name, chain_func_name, chain_definition.priority or 0)); + end + end + print(("module:hook(%q, %s, %d);"):format("firewall/chains/"..chain, chain_func_name, chain_definition.priority or 0)); + end + + print("---- End of chain "..chain); + print(); + end + print("end -- End of file "..filename); + end +end + + +-- Console + +local console_env = module:shared("/*/admin_shell/env"); + +console_env.firewall = {}; + +function console_env.firewall:mark(user_jid, mark_name) + local username, host = jid.split(user_jid); + if not username or not hosts[host] then + return nil, "Invalid JID supplied"; + elseif not idsafe(mark_name) then + return nil, "Invalid characters in mark name"; + end + if not module:context(host):fire_event("firewall/marked/user", { + username = session.username; + mark = mark_name; + timestamp = os.time(); + }) then + return nil, "Mark not set - is mod_firewall loaded on that host?"; + end + return true, "User marked"; +end + +function console_env.firewall:unmark(jid, mark_name) + local username, host = jid.split(user_jid); + if not username or not hosts[host] then + return nil, "Invalid JID supplied"; + elseif not idsafe(mark_name) then + return nil, "Invalid characters in mark name"; + end + if not module:context(host):fire_event("firewall/unmarked/user", { + username = session.username; + mark = mark_name; + }) then + return nil, "Mark not removed - is mod_firewall loaded on that host?"; + end + return true, "User unmarked"; +end diff --git a/prosody-modules/mod_firewall/scripts/jabberspam-simple-blocklist.pfw b/prosody-modules/mod_firewall/scripts/jabberspam-simple-blocklist.pfw new file mode 100644 index 00000000..bbc1c8f8 --- /dev/null +++ b/prosody-modules/mod_firewall/scripts/jabberspam-simple-blocklist.pfw @@ -0,0 +1,17 @@ +# This is a simple ruleset to block all traffic from servers +# on the JabberSPAM blocklist. Even traffic from existing user +# contacts will be blocked. +# +# Example config (make sure "firewall" is in modules_enabled): +# +# firewall_scripts = { "module:scripts/jabberspam-simple-blocklist.pfw" } +# +# For a more advanced ruleset, consider using spam-blocking.pfw +# and spam-blocklists.pfw. + +%LIST blocklist: https://cdn.jsdelivr.net/gh/jabberspam/blacklist/blacklist.txt + +::deliver + +CHECK LIST: blocklist contains $<@from|host> +BOUNCE=policy-violation (Your server is blocked due to spam) diff --git a/prosody-modules/mod_firewall/scripts/spam-blocking.pfw b/prosody-modules/mod_firewall/scripts/spam-blocking.pfw new file mode 100644 index 00000000..ed6d8e30 --- /dev/null +++ b/prosody-modules/mod_firewall/scripts/spam-blocking.pfw @@ -0,0 +1,182 @@ +#### Anti-spam ruleset ########################################### +# +# This script provides some foundational anti-spam rules. It aims +# to PASS stanzas that are definitely not spam, and DROP stanzas +# that are very likely spam. +# +# It does not do any form of content filtering, +# but this can be implemented by other scripts and +# modules as desired using the chains documented below. +# +# +# The following chains are available as extension +# points: +# +# ::user/spam_check_custom +# Apply additional rules to all stanzas before they are checked. +# Mainly useful to PASS stanzas that you do not want to be +# filtered. +# +# ::user/spam_check_message_custom +# Apply additional rules to messages from strangers, aiming to +# PASS stanzas that are not spam and jump to ::user/spam_reject +# for stanzas that are considered spam. +# +# ::user/spam_check_message_content_custom +# Apply additional rules to messages that may be spam, based on +# message content rules. These may contain more intensive rules, +# so are executed after all other checks. Rules should jump to +# ::user/spam_reject if a message is considered spam. +# +# ::user/spam_check_presence_custom +# Apply additional rules to presence that may be spam. +# +# ::user/spam_check_subscription_request_custom +# Apply additional rules to subscription requests. +# +# ::user/spam_handle_unknown_custom +# Override default handling of stanzas that weren't explicitly +# passed or rejected by the anti-spam checks. +# +# ::user/spam_reject_custom +# Override default handling of stanzas that have +# been recognised as spam (default is to bounce +# a policy-violation error). +# +################################################################## + +#### Entry point for all incoming stanzas ######################## +::deliver + +# Override this if you want to prevent certain stanzas going through +# the normal spam_check chain +JUMP_CHAIN=user/spam_check_custom + +# Run the default spam_check chain +JUMP_CHAIN=user/spam_check + +################################################################## + +#### General spam-checking rules (all stanzas) ################### +::user/spam_check + +# Pass stanzas that a user sends to their own account +TO SELF? +PASS. + +# Pass stanzas that are addressed to a valid full JID +TO FULL JID? +PASS. + +# Pass stanzas from contacts +SUBSCRIBED? +PASS. + +# Run extra rules that apply to messages only +KIND: message +JUMP CHAIN=user/spam_check_message + +# Run extra rules that apply to presence stanzas only +KIND: presence +JUMP CHAIN=user/spam_check_presence + +JUMP CHAIN=user/spam_handle_unknown + +# Default is to allow, override this with +# the 'user/spam_handle_unknown' chain +PASS. + +#### Rules for messages ########################################## +::user/spam_check_message + +JUMP CHAIN=user/spam_check_message_custom + +# Type 'groupchat' messages addressed to an offline full JID are harmless, +# and should be routed normally to handle MUC 'ghosts' correctly +TO: <*>@<*>/<*> +TYPE: groupchat +PASS. + +# Mediated MUC invitations are naturally from 'strangers' and have special +# handling. We lean towards accepting them, unless overridden by custom rules. +NOT FROM FULL JID? +INSPECT: {http://jabber.org/protocol/muc#user}x/invite +JUMP CHAIN=user/spam_check_muc_invite + +# Non-chat message types often generate pop-ups in clients, +# so we won't accept them from strangers +NOT TYPE: chat +JUMP CHAIN=user/spam_reject + +JUMP CHAIN=user/spam_check_message_content + +# This chain can be used by other scripts +# and modules that analyze message content +JUMP CHAIN=user/spam_check_message_content_custom + +################################################################## + +#### Rules for presence stanzas ################################## +::user/spam_check_presence + +JUMP CHAIN=user/spam_check_presence_custom + +# Presence to offline full JIDs is harmless, and should be routed +# normally to handle MUC 'ghosts' correctly +TO: <*>@<*>/<*> +PASS. + +# These may be received if rosters get out of sync and are harmless +# because they will not be routed to the client unless necessary +TYPE: unsubscribe|unsubscribed +PASS. + +# We don't want to receive presence from random strangers, +# but still allow subscription requests +NOT TYPE: subscribe|subscribed +DROP. + +# This chain can be used by other scripts +# and modules to filter subscription requests +JUMP CHAIN=user/spam_check_subscription_request + +JUMP CHAIN=user/spam_check_subscription_request_custom + +################################################################## + +#### Rules for MUC invitations ################################### + +::user/spam_check_muc_invite + +# This chain can be used to inspect the invitation and determine +# the appropriate action. Otherwise, we proceed with the default +# action below. +JUMP CHAIN=user/spam_check_muc_invite_custom + +# Allow mediated MUC invitations by default +PASS. + +#### Stanzas reaching this chain will be rejected ################ +::user/spam_reject + +# This chain can be used by other scripts +# and modules to override the default behaviour +# when rejecting spam stanzas +JUMP CHAIN=user/spam_reject_custom + +LOG=Rejecting suspected spam: $(stanza:top_tag()) +BOUNCE=policy-violation + +################################################################## + +#### Stanzas that may be spam, but we're not sure either way ##### +::user/spam_handle_unknown + +# This chain can be used by other scripts +# and modules to apply additional checks, or to +# override the default behaviour +JUMP CHAIN=user/spam_handle_unknown_custom + +#LOG=[debug] Spam check allowing: $(stanza:top_tag()) + +################################################################## diff --git a/prosody-modules/mod_firewall/scripts/spam-blocklists.pfw b/prosody-modules/mod_firewall/scripts/spam-blocklists.pfw new file mode 100644 index 00000000..e6f94b99 --- /dev/null +++ b/prosody-modules/mod_firewall/scripts/spam-blocklists.pfw @@ -0,0 +1,20 @@ +# This script depends on spam-blocking.pfw also being loaded +# Any traffic that is not explicitly blocked or allowed by other +# rules will be checked against the JabberSPAM server blocklist + +%LIST blocklist: https://cdn.jsdelivr.net/gh/jabberspam/blacklist/blacklist.txt + +::user/spam_handle_unknown_custom + +CHECK LIST: blocklist contains $<@from|host> +BOUNCE=policy-violation (Your server is blocked due to spam) + +::user/spam_check_muc_invite_custom + +# Check the server we received the invitation from +CHECK LIST: blocklist contains $<@from|host> +BOUNCE=policy-violation (Your server is blocked due to spam) + +# Check the inviter's JID against the blocklist, too +CHECK LIST: blocklist contains $<{http://jabber.org/protocol/muc#user}x/invite@from|host> +BOUNCE=policy-violation (Your server is blocked due to spam) diff --git a/prosody-modules/mod_firewall/scripts/spam-strip-xhtml.pfw b/prosody-modules/mod_firewall/scripts/spam-strip-xhtml.pfw new file mode 100644 index 00000000..38ca00f5 --- /dev/null +++ b/prosody-modules/mod_firewall/scripts/spam-strip-xhtml.pfw @@ -0,0 +1,5 @@ +# Strip XHTML-IM from messages received from strangers + +::user/spam_check_message_custom + +STRIP=html http://jabber.org/protocol/xhtml-im diff --git a/prosody-modules/mod_firewall/test.lib.lua b/prosody-modules/mod_firewall/test.lib.lua new file mode 100644 index 00000000..a72b0215 --- /dev/null +++ b/prosody-modules/mod_firewall/test.lib.lua @@ -0,0 +1,75 @@ +-- luacheck: globals load_unload_scripts +local set = require "util.set"; +local ltn12 = require "ltn12"; + +local xmppstream = require "util.xmppstream"; + +local function stderr(...) + io.stderr:write("** ", table.concat({...}, "\t", 1, select("#", ...)), "\n"); +end + +return function (arg) + require "net.http".request = function (url, ex, cb) + stderr("Making HTTP request to "..url); + local body_table = {}; + local ok, response_status, response_headers = require "ssl.https".request({ + url = url; + headers = ex.headers; + method = ex.body and "POST" or "GET"; + sink = ltn12.sink.table(body_table); + source = ex.body and ltn12.source.string(ex.body) or nil; + }); + stderr("HTTP response "..response_status); + cb(table.concat(body_table), response_status, { headers = response_headers }); + return true; + end; + + local stats_dropped, stats_passed = 0, 0; + + load_unload_scripts(set.new(arg)); + local stream_callbacks = { default_ns = "jabber:client" }; + + function stream_callbacks.streamopened(session) + session.notopen = nil; + end + function stream_callbacks.streamclosed() + end + function stream_callbacks.error(session, error_name, error_message) -- luacheck: ignore 212/session + stderr("Fatal error parsing XML stream: "..error_name..": "..tostring(error_message)) + assert(false); + end + function stream_callbacks.handlestanza(session, stanza) + if not module:fire_event("firewall/chains/deliver", { origin = session, stanza = stanza }) then + stats_passed = stats_passed + 1; + print(stanza); + print(""); + else + stats_dropped = stats_dropped + 1; + end + end + + local session = { notopen = true }; + function session.send(stanza) + stderr("Reply:", "\n"..tostring(stanza).."\n"); + end + local stream = xmppstream.new(session, stream_callbacks); + stream:feed(""); + local line_count = 0; + for line in io.lines() do + line_count = line_count + 1; + local ok, err = stream:feed(line.."\n"); + if not ok then + stderr("Fatal XML parse error on line "..line_count..": "..err); + return 1; + end + end + + stderr("Summary"); + stderr("-------"); + stderr(""); + stderr(stats_dropped + stats_passed, "processed"); + stderr(stats_passed, "passed"); + stderr(stats_dropped, "dropped"); + stderr(line_count, "input lines"); + stderr(""); +end diff --git a/prosody-modules/mod_muc_anonymize_moderation_actions/README.markdown b/prosody-modules/mod_muc_anonymize_moderation_actions/README.markdown new file mode 100644 index 00000000..62a1b323 --- /dev/null +++ b/prosody-modules/mod_muc_anonymize_moderation_actions/README.markdown @@ -0,0 +1,32 @@ + +# mod_muc_anonymize_moderation_actions + +This modules allows to anonymize affiliation and role changes in MUC rooms. + +Enabling this module on a MUC Virtualhost will add a settings in the roomconfig form. +When the feature is enabled, when a moderator changes the role or affiliation of an occupant (kick, ban, ...) their name will be removed from the broadcasted message, to not disclose who did the moderation action. + +This is particularly usefull to prevent some revenge when a moderator bans someone. + +This module is under AGPL-3.0 license. + +It was tested on Prosody 0.12.x. + +## Configuration + +Just enable the module on your MUC VirtualHost. +The feature will be accessible throught the room configuration form. + +You can tweak the position of the settings in the MUC configuration form using `anonymize_moderation_actions_form_position`. +This value will be passed as priority for the "muc-config-form" hook, so you can move field up by increasing the value, or down by decreasing the value. + +By default, the field will be between muc#roomconfig_changesubject and muc#roomconfig_moderatedroom (default value is `78`). + +``` lua +VirtualHost "muc.example.com" + modules_enabled = { "muc_anonymize_moderation_actions" } + anonymize_moderation_actions_form_position = 96 +``` diff --git a/prosody-modules/mod_muc_anonymize_moderation_actions/mod_muc_anonymize_moderation_actions.lua b/prosody-modules/mod_muc_anonymize_moderation_actions/mod_muc_anonymize_moderation_actions.lua new file mode 100644 index 00000000..89a41cc7 --- /dev/null +++ b/prosody-modules/mod_muc_anonymize_moderation_actions/mod_muc_anonymize_moderation_actions.lua @@ -0,0 +1,76 @@ +-- mod_muc_anonymize_moderation_actions +-- +-- SPDX-FileCopyrightText: 2024 John Livingston +-- SPDX-License-Identifier: AGPL-3.0-only + +-- form_position: the position in the room config form (this value will be passed as priority for the "muc-config-form" hook). +-- By default, field will be between muc#roomconfig_changesubject and muc#roomconfig_moderatedroom +local form_position = module:get_option_number("anonymize_moderation_actions_form_position") or 80-2; + +local function get_anonymize_moderation_actions(room) + return room._data.anonymize_moderation_actions or false; +end + +local function set_anonymize_moderation_actions(room, anonymize_moderation_actions) + anonymize_moderation_actions = anonymize_moderation_actions and true or nil; + if get_anonymize_moderation_actions(room) == anonymize_moderation_actions then return false; end + room._data.anonymize_moderation_actions = anonymize_moderation_actions; + return true; +end + +-- Config form declaration +local function add_form_option(event) + table.insert(event.form, { + name = "muc#roomconfig_anonymize_moderation_actions"; + type = "boolean"; + label = "Anonymize moderation actions"; + desc = "When this is enabled, moderation actions will be anonymized, to avoid disclosing who is banning/kicking/… occupants."; + value = get_anonymize_moderation_actions(event.room); + }); +end + +local function config_submitted(event) + set_anonymize_moderation_actions(event.room, event.value); +end + +local function remove_actor(event) + if (event.room and get_anonymize_moderation_actions(event.room)) then + event.actor = nil; + end +end + +local function remove_moderate_actor(event) + local room, announcement, tombstone = event.room, event.announcement, event.tombstone; + if not get_anonymize_moderation_actions(room) then + return; + end + + local moderated = announcement:find("{urn:xmpp:fasten:0}apply-to/{urn:xmpp:message-moderate:0}moderated"); + if moderated then + module:log("debug", "We must anonymize the moderation announcement for stanza %s", event.stanza_id); + -- FIXME: XEP-0245 has changed. + -- urn:xmpp:message-moderate:0 requires a "by" attribute + -- urn:xmpp:message-moderate:1 do not require the "by" attribute + -- So, for now, settings the room jid, as we only implement urn:xmpp:message-moderate:0. + moderated.attr.by = room.jid; + moderated:remove_children("occupant-id", "urn:xmpp:occupant-id:0"); + end + + if tombstone then + local moderated = tombstone:get_child("moderated", "urn:xmpp:message-moderate:0"); + if moderated then + module:log("debug", "We must anonymize the moderation tombstone for stanza %s", event.stanza_id); + -- FIXME: XEP-0245 has changed. + -- urn:xmpp:message-moderate:0 requires a "by" attribute + -- urn:xmpp:message-moderate:1 do not require the "by" attribute + -- So, for now, settings the room jid, as we only implement urn:xmpp:message-moderate:0. + moderated.attr.by = room.jid; + moderated:remove_children("occupant-id", "urn:xmpp:occupant-id:0"); + end + end +end + +module:hook("muc-config-submitted/muc#roomconfig_anonymize_moderation_actions", config_submitted); +module:hook("muc-config-form", add_form_option, form_position); +module:hook("muc-broadcast-presence", remove_actor); +module:hook("muc-moderate-message", remove_moderate_actor); diff --git a/prosody-modules/mod_muc_http_defaults/mod_muc_http_defaults.lua b/prosody-modules/mod_muc_http_defaults/mod_muc_http_defaults.lua index 1a217671..771498ad 100644 --- a/prosody-modules/mod_muc_http_defaults/mod_muc_http_defaults.lua +++ b/prosody-modules/mod_muc_http_defaults/mod_muc_http_defaults.lua @@ -8,6 +8,7 @@ -- * "slow_mode_duration" -- * "mute_anonymous" -- * "moderation_delay" +-- * "anonymize_moderation_actions" -- These options are introduced in the Peertube livechat plugin. -- -- The "slow_mode_duration" comes with mod_muc_slow_mode. @@ -132,6 +133,9 @@ local function apply_config(room, settings) -- (and thus we don't need to broadcast changes) room._data.livechat_muc_terms = config.livechat_muc_terms; end + if (type(config.anonymize_moderation_actions) == "boolean") then + room._data.anonymize_moderation_actions = config.anonymize_moderation_actions; + end elseif config ~= nil then module:log("error", "Invalid config returned from API for %s: %q", room.jid, config); return nil, "format", { field = "config" }; diff --git a/prosody-modules/mod_muc_mam_search/README.markdown b/prosody-modules/mod_muc_mam_search/README.markdown new file mode 100644 index 00000000..0ca73b79 --- /dev/null +++ b/prosody-modules/mod_muc_mam_search/README.markdown @@ -0,0 +1,23 @@ + +# mod_muc_mam_search + +With this module you can make some advanced search in MAM (MUC Archive Management - XEP-0313). + +This module is part of peertube-plugin-livechat, and is under AGPL-3.0.-only license. +This module can work on any Prosody server (version >= 0.12.x). +This module is still experimental. + +## Configuration + +Just enable the module on your MUC component. + +The feature will be announced using Service Discovery (XEP-0030). + +TODO: document the Disco namespace. + +You can then query archives using query similar to those for XEP-0313. + +TODO: document available queries. diff --git a/prosody-modules/mod_muc_mam_search/archive.lib.lua b/prosody-modules/mod_muc_mam_search/archive.lib.lua new file mode 100644 index 00000000..d26be1e6 --- /dev/null +++ b/prosody-modules/mod_muc_mam_search/archive.lib.lua @@ -0,0 +1,25 @@ +-- SPDX-FileCopyrightText: 2024 John Livingston +-- SPDX-License-Identifier: AGPL-3.0-only + +-- FIXME: these imports are copied from mod_muc_mam, we should avoid that. +local log_all_rooms = module:get_option_boolean("muc_log_all_rooms", false); +local log_by_default = module:get_option_boolean("muc_log_by_default", true); + +-- FIXME: this function is copied from mod_muc_mam. We should not do so, and use directly the original function. +local function archiving_enabled(room) + if log_all_rooms then + module:log("debug", "Archiving all rooms"); + return true; + end + local enabled = room._data.archiving; + if enabled == nil then + module:log("debug", "Default is %s (for %s)", log_by_default, room.jid); + return log_by_default; + end + module:log("debug", "Logging in room %s is %s", room.jid, enabled); + return enabled; +end + +return { + archiving_enabled = archiving_enabled; +}; diff --git a/prosody-modules/mod_muc_mam_search/filter.lib.lua b/prosody-modules/mod_muc_mam_search/filter.lib.lua new file mode 100644 index 00000000..e202c54f --- /dev/null +++ b/prosody-modules/mod_muc_mam_search/filter.lib.lua @@ -0,0 +1,24 @@ +-- SPDX-FileCopyrightText: 2024 John Livingston +-- SPDX-License-Identifier: AGPL-3.0-only + +-- Perform the search criteria. +-- Returns true if the item match. +-- Note: there is a logical OR between search_from and search_occupant_id +local function item_match(id, item, search_from, search_occupant_id) + if (search_from ~= nil) then + if (search_from == item.attr.from) then + return true; + end + end + if (search_occupant_id ~= nil) then + local occupant_id = item:get_child("occupant-id", "urn:xmpp:occupant-id:0"); + if (occupant_id and occupant_id.attr.id == search_occupant_id) then + return true; + end + end + return false; +end + +return { + item_match = item_match; +}; diff --git a/prosody-modules/mod_muc_mam_search/mod_muc_mam_search.lua b/prosody-modules/mod_muc_mam_search/mod_muc_mam_search.lua new file mode 100644 index 00000000..6a92c2aa --- /dev/null +++ b/prosody-modules/mod_muc_mam_search/mod_muc_mam_search.lua @@ -0,0 +1,154 @@ +-- mod_muc_mam_search +-- +-- SPDX-FileCopyrightText: 2024 John Livingston +-- SPDX-License-Identifier: AGPL-3.0-only +-- + +local archiving_enabled = module:require("archive").archiving_enabled; +local item_match = module:require("filter").item_match; +local jid_split = require "util.jid".split; +local jid_bare = require "util.jid".bare; +local st = require "util.stanza"; +local datetime = require"util.datetime"; +local dataform = require "util.dataforms".new; +local get_form_type = require "util.dataforms".get_type; + +local mod_muc = module:depends"muc"; +local get_room_from_jid = mod_muc.get_room_from_jid; +local muc_log_archive = module:open_store("muc_log", "archive"); + +local xmlns_mam = "urn:xmpp:mam:2"; +local xmlns_mam_search = "urn:xmpp:mam:2#x-search"; +local xmlns_delay = "urn:xmpp:delay"; +local xmlns_forward = "urn:xmpp:forward:0"; + +module:hook("muc-disco#info", function(event) + if archiving_enabled(event.room) then + event.reply:tag("feature", {var=xmlns_mam_search}):up(); + end +end); + +local query_form = dataform { + { name = "FORM_TYPE"; type = "hidden"; value = xmlns_mam_search }; + { name = "from"; type = "jid-single" }; + { name = "occupant_id"; type = "text-single" }; +}; + +-- Serve form +module:hook("iq-get/bare/"..xmlns_mam_search..":query", function(event) + local origin, stanza = event.origin, event.stanza; + origin.send(st.reply(stanza):query(xmlns_mam_search):add_child(query_form:form())); + return true; +end); + +-- Handle archive queries +module:hook("iq-set/bare/"..xmlns_mam_search..":query", function(event) + local origin, stanza = event.origin, event.stanza; + local room_jid = stanza.attr.to; + local room_node = jid_split(room_jid); + local orig_from = stanza.attr.from; + local query = stanza.tags[1]; + + local room = get_room_from_jid(room_jid); + if not room then + origin.send(st.error_reply(stanza, "cancel", "item-not-found")) + return true; + end + local from = jid_bare(orig_from); + + -- Must be room admin or owner. + local from_affiliation = room:get_affiliation(from); + if (from_affiliation ~= "owner" and from_affiliation ~= "admin") then + origin.send(st.error_reply(stanza, "auth", "forbidden")) + return true; + end + + local qid = query.attr.queryid; + + -- Search query parameters + local search_from; + local search_occupant_id; + local form = query:get_child("x", "jabber:x:data"); + if form then + local form_type, err = get_form_type(form); + if not form_type then + origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid dataform: "..err)); + return true; + elseif form_type ~= xmlns_mam_search then + origin.send(st.error_reply(stanza, "modify", "bad-request", "Unexpected FORM_TYPE, expected '"..xmlns_mam_search.."'")); + return true; + end + form, err = query_form:data(form); + if err then + origin.send(st.error_reply(stanza, "modify", "bad-request", select(2, next(err)))); + return true; + end + + search_from = form["from"]; + search_occupant_id = form["occupant_id"]; + else + module:log("debug", "Missing query form, forbidden.") + origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing dataform")); + return true; + end + + -- TODO: handle RSM (pagination)? + module:log("debug", "Archive query by %s id=%s", from, qid); + + -- Load all the data! + local data, err = muc_log_archive:find(room_node, { + start = nil; ["end"] = nil; + with = "message tag, containing the original senders JID, unless the room makes this public. + -- but we only allow this feature to owner and admin, so we don't need to remove this. + + item.attr.to = nil; + item.attr.xmlns = "jabber:client"; + fwd_st:add_child(item); + + origin.send(fwd_st); + end + end + + origin.send(st.reply(stanza) + -- The result uses xmlns_mam and not xmlns_mam_search, so that the frontend handles this in the same way than xmlns_mam. + :tag("fin", { xmlns = xmlns_mam, complete = "true" })); + + -- That's all folks! + module:log("debug", "Archive query id=%s completed, %d items returned", qid or stanza.attr.id, count); + return true; +end); diff --git a/prosody-modules/mod_muc_moderation/README.markdown b/prosody-modules/mod_muc_moderation/README.markdown index 6c914443..4abb1f66 100644 --- a/prosody-modules/mod_muc_moderation/README.markdown +++ b/prosody-modules/mod_muc_moderation/README.markdown @@ -1,7 +1,9 @@ - +summary: Let moderators remove spam and abuse messages +--- + # Introduction This module implements [XEP-0425: Message Moderation]. @@ -16,7 +18,7 @@ role in the channel / group chat. Example [MUC component][doc:chatrooms] configuration: ``` {.lua} -VirtualHost "channels.example.com" "muc" +Component "channels.example.com" "muc" modules_enabled = { "muc_mam", "muc_moderation", @@ -25,20 +27,19 @@ modules_enabled = { # Compatibility -- Should work with Prosody 0.11.x and later. -- Tested with trunk rev `52c6dfa04dba`. -- Message tombstones requires a compatible storage module implementing - a new message replacement API. +- Basic functionality with Prosody 0.11.x and later +- Full functionality with Prosody 0.12.x and `internal` or `sql` + storage^[Replacing moderated messages with tombstones requires new storage API methods.] +- Works with [mod_storage_xmlarchive] ## Clients -- Tested with [Converse.js](https://conversejs.org/) - [v6.0.1](https://github.com/conversejs/converse.js/releases/tag/v6.0.1) +- [Converse.js](https://conversejs.org/) +- [Gajim](https://dev.gajim.org/gajim/gajim/-/issues/10107) +- [clix](https://code.zash.se/clix/rev/6c1953fbe0fa) ### Feature requests -- [Conv](https://github.com/iNPUTmice/Conversations/issues/3722)[ersa](https://github.com/iNPUTmice/Conversations/issues/3920)[tions](https://github.com/iNPUTmice/Conversations/issues/4227) -- [Dino](https://github.com/dino/dino/issues/1133) -- [Gajim](https://dev.gajim.org/gajim/gajim/-/issues/10107) -- [Poezio](https://lab.louiz.org/poezio/poezio/-/issues/3543) -- [Profanity](https://github.com/profanity-im/profanity/issues/1336) +- [Conversations](https://codeberg.org/iNPUTmice/Conversations/issues/20) +- [Dino](https://github.com/dino/dino/issues/1133) +- [Profanity](https://github.com/profanity-im/profanity/issues/1336) diff --git a/prosody-modules/mod_muc_moderation/mod_muc_moderation.lua b/prosody-modules/mod_muc_moderation/mod_muc_moderation.lua index 318175be..1e794841 100644 --- a/prosody-modules/mod_muc_moderation/mod_muc_moderation.lua +++ b/prosody-modules/mod_muc_moderation/mod_muc_moderation.lua @@ -27,6 +27,7 @@ end -- Namespaces local xmlns_fasten = "urn:xmpp:fasten:0"; local xmlns_moderate = "urn:xmpp:message-moderate:0"; +local xmlns_occupant_id = "urn:xmpp:occupant-id:0"; local xmlns_retract = "urn:xmpp:message-retract:0"; -- Discovering support @@ -34,36 +35,17 @@ module:hook("muc-disco#info", function (event) event.reply:tag("feature", { var = xmlns_moderate }):up(); end); --- Main handling -module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) - local stanza, origin = event.stanza, event.origin; +-- TODO error registry, requires Prosody 0.12+ - -- Collect info we need - local apply_to = stanza.tags[1]; - local moderate_tag = apply_to:get_child("moderate", xmlns_moderate); - if not moderate_tag then return end -- some other kind of fastening? - - local reason = moderate_tag:get_child_text("reason"); - local retract = moderate_tag:get_child("retract", xmlns_retract); - - local room_jid = stanza.attr.to; +-- moderate : function (string, string, string, boolean, string) : boolean, enum, enum, string +local function moderate(actor, room_jid, stanza_id, retract, reason) local room_node = jid.split(room_jid); local room = mod_muc.get_room_from_jid(room_jid); - local stanza_id = apply_to.attr.id; - - -- Permissions - local actor = stanza.attr.from; + -- Permissions is based on role, which is a property of a current occupant, + -- so check if the actor is an occupant, otherwise if they have a reserved + -- nickname that can be used to retrieve the role. local actor_nick = room:get_occupant_jid(actor); - local affiliation = room:get_affiliation(actor); - -- Retrieve their current role, iff they are in the room, otherwise what they - -- would have based on affiliation. - local role = room:get_role(actor_nick) or room:get_default_role(affiliation); - if valid_roles[role or "none"] < valid_roles.moderator then - origin.send(st.error_reply(stanza, "auth", "forbidden", "You need a role of at least 'moderator'")); - return true; - end - if not actor_nick then local reserved_nickname = room:get_affiliation_data(jid.bare(actor), "reserved_nickname"); if reserved_nickname then @@ -71,6 +53,14 @@ module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) end end + -- Retrieve their current role, iff they are in the room, otherwise what they + -- would have based on affiliation. + local affiliation = room:get_affiliation(actor); + local role = room:get_role(actor_nick) or room:get_default_role(affiliation); + if valid_roles[role or "none"] < valid_roles.moderator then + return false, "auth", "forbidden", "You need a role of at least 'moderator'"; + end + -- Original stanza to base tombstone on local original, err; if muc_log_archive.get then @@ -84,20 +74,26 @@ module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) end end end + if not original then if err == "item-not-found" then - origin.send(st.error_reply(stanza, "modify", "item-not-found")); + return false, "modify", "item-not-found"; else - origin.send(st.error_reply(stanza, "wait", "internal-server-error")); + return false, "wait", "internal-server-error"; end - return true; end + local actor_occupant = room:get_occupant_by_real_jid(actor) or room:new_occupant(jid.bare(actor), actor_nick); local announcement = st.message({ from = room_jid, type = "groupchat", id = id.medium(), }) :tag("apply-to", { xmlns = xmlns_fasten, id = stanza_id }) :tag("moderated", { xmlns = xmlns_moderate, by = actor_nick }) + if room.get_occupant_id then + -- This isn't a regular broadcast message going through the events occupant_id.lib hooks so we do this here + announcement:add_child(st.stanza("occupant-id", { xmlns = xmlns_occupant_id; id = room:get_occupant_id(actor_occupant) })); + end + if retract then announcement:tag("retract", { xmlns = xmlns_retract }):up(); end @@ -106,8 +102,16 @@ module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) announcement:text_tag("reason", reason); end + local moderated_occupant_id = original:get_child("occupant-id", xmlns_occupant_id); + if room.get_occupant_id and moderated_occupant_id then + announcement:add_direct_child(moderated_occupant_id); + end + + announcement:reset(); + + local tombstone = nil; if muc_log_archive.set and retract then - local tombstone = st.message({ from = original.attr.from, type = "groupchat", id = original.attr.id }) + tombstone = st.message({ from = original.attr.from, type = "groupchat", id = original.attr.id }) :tag("moderated", { xmlns = xmlns_moderate, by = actor_nick }) :tag("retracted", { xmlns = xmlns_retract, stamp = dt.datetime() }):up(); @@ -115,10 +119,39 @@ module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) tombstone:text_tag("reason", reason); end + if room.get_occupant_id then + if actor_occupant then + tombstone:add_child(st.stanza("occupant-id", { xmlns = xmlns_occupant_id; id = room:get_occupant_id(actor_occupant) })); + end + + if moderated_occupant_id then + -- Copy occupant id from moderated message + tombstone:add_direct_child(moderated_occupant_id); + end + end + tombstone:reset(); + end + + -- fire an event, that can be used to cancel the moderation, or modify stanzas. + local event = { + room = room; + announcement = announcement; + tombstone = tombstone; + stanza_id = stanza_id; + retract = retract; + reason = reason; + actor = actor; + actor_nick = actor_nick; + }; + if module:fire_event("muc-moderate-message", event) then + -- TODO: allow to change the error message? + return false, "wait", "internal-server-error"; + end + + if tombstone then local was_replaced = muc_log_archive:set(room_node, stanza_id, tombstone); if not was_replaced then - origin.send(st.error_reply(stanza, "wait", "internal-server-error")); - return true; + return false, "wait", "internal-server-error"; end end @@ -126,6 +159,32 @@ module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) module:log("info", "Message with id '%s' in room %s moderated by %s, reason: %s", stanza_id, room_jid, actor, reason); room:broadcast_message(announcement); + return true; +end + +-- Main handling +module:hook("iq-set/bare/" .. xmlns_fasten .. ":apply-to", function (event) + local stanza, origin = event.stanza, event.origin; + + local actor = stanza.attr.from; + local room_jid = stanza.attr.to; + + -- Collect info we need + local apply_to = stanza.tags[1]; + local moderate_tag = apply_to:get_child("moderate", xmlns_moderate); + if not moderate_tag then return end -- some other kind of fastening? + + local reason = moderate_tag:get_child_text("reason"); + local retract = moderate_tag:get_child("retract", xmlns_retract); + + local stanza_id = apply_to.attr.id; + + local ok, error_type, error_condition, error_text = moderate(actor, room_jid, stanza_id, retract, reason); + if not ok then + origin.send(st.error_reply(stanza, error_type, error_condition, error_text)); + return true; + end + origin.send(st.reply(stanza)); return true; end); diff --git a/prosody-modules/mod_muc_moderation_delay/README.md b/prosody-modules/mod_muc_moderation_delay/README.markdown similarity index 93% rename from prosody-modules/mod_muc_moderation_delay/README.md rename to prosody-modules/mod_muc_moderation_delay/README.markdown index 7c831885..2b1d7812 100644 --- a/prosody-modules/mod_muc_moderation_delay/README.md +++ b/prosody-modules/mod_muc_moderation_delay/README.markdown @@ -6,8 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only With this module, you can apply a delay to groupchat messages delivery, so that room moderators can moderate them before other participants receives them. -This module is part of peertube-plugin-livechat, and is under the same LICENSE. +This module is part of peertube-plugin-livechat, and is under AGPL-3.0.-only license. This module can work on any Prosody server (version >= 0.12.x). +This module is still experimental. ## Configuration diff --git a/prosody-modules/mod_muc_poll/README.md b/prosody-modules/mod_muc_poll/README.md index 072a19a2..be61bb41 100644 --- a/prosody-modules/mod_muc_poll/README.md +++ b/prosody-modules/mod_muc_poll/README.md @@ -13,16 +13,16 @@ There will probably be a XEP proposal for this module behaviour. When done, this ## Configuration Just enable the module on your MUC component. -All above configurations are optional. +All following configurations are optional. -## poll_groupchat_votes_priority +### poll_groupchat_votes_priority The priority for the hook that will take into account votes. You can change this, if you have some specific hook that should be done after/before counting votes (slow mode, firewall, ...). Default: 40 (Prosody checks visitor role with priority of 50, we want this to be after). -## Strings +### Strings You can change some defaults strings, if you want for example to localize the poll messages. Here are the existing strings and default values: diff --git a/prosody-modules/mod_muc_slow_mode/README.md b/prosody-modules/mod_muc_slow_mode/README.markdown similarity index 100% rename from prosody-modules/mod_muc_slow_mode/README.md rename to prosody-modules/mod_muc_slow_mode/README.markdown diff --git a/prosody-modules/mod_pubsub_peertubelivechat/README.md b/prosody-modules/mod_pubsub_peertubelivechat/README.md index b0525942..62d143cc 100644 --- a/prosody-modules/mod_pubsub_peertubelivechat/README.md +++ b/prosody-modules/mod_pubsub_peertubelivechat/README.md @@ -7,13 +7,16 @@ SPDX-License-Identifier: AGPL-3.0-only This module is a custom module that provide some pubsub services associated to a MUC room. This module is entended to be used in the peertube-plugin-livechat project. -For each MUC room, there will be an associated pubsub node. -This node in only accessible by the ROOM admin/owner. +For each MUC room, there will be a associated pubsub nodes. +These nodes are only accessible by the ROOM admins/owners. -This node can contains various objects: +Here are a description of existing nodes, and objects they can contain: -* task lists -* tasks +* livechat-tasks: + * task lists + * tasks +* livechat-notes: + * notes * ... (more to come) These objects are meant te be shared between admin/owner. diff --git a/prosody-modules/mod_pubsub_peertubelivechat/mod_pubsub_peertubelivechat.lua b/prosody-modules/mod_pubsub_peertubelivechat/mod_pubsub_peertubelivechat.lua index 95465bf1..95afee23 100644 --- a/prosody-modules/mod_pubsub_peertubelivechat/mod_pubsub_peertubelivechat.lua +++ b/prosody-modules/mod_pubsub_peertubelivechat/mod_pubsub_peertubelivechat.lua @@ -15,6 +15,7 @@ -- Implemented nodes: -- * livechat-tasks: contains tasklist and task items, specific to livechat plugin. +-- * livechat-notes: contains notes, specific to livechat plugin. -- There are some other tricks in this module: -- * unsubscribing users that have left the room (the front-end will subscribe again when needed) @@ -39,16 +40,14 @@ local xmlns_pubsub = "http://jabber.org/protocol/pubsub"; local xmlns_pubsub_event = "http://jabber.org/protocol/pubsub#event"; local xmlns_pubsub_owner = "http://jabber.org/protocol/pubsub#owner"; local xmlns_tasklist = "urn:peertube-plugin-livechat:tasklist"; -local xmlns_task = "urn:peertube-plugin-livechat:task" +local xmlns_task = "urn:peertube-plugin-livechat:task"; +local xmlns_note = "urn:peertube-plugin-livechat:note"; local lib_pubsub = module:require "pubsub"; local mod_muc = module:depends"muc"; local get_room_from_jid = mod_muc.get_room_from_jid; -local muc_util = module:require "muc/util"; -local valid_roles = muc_util.valid_roles; - -- room_jid => object passed to module:add_items() local mep_service_items = {}; @@ -389,4 +388,5 @@ end); module:hook("muc-disco#info", function (event) event.reply:tag("feature", { var = xmlns_task }):up(); event.reply:tag("feature", { var = xmlns_tasklist }):up(); + event.reply:tag("feature", { var = xmlns_note }):up(); end); diff --git a/server/lib/configuration/channel/sanitize.ts b/server/lib/configuration/channel/sanitize.ts index 3aa45480..8a72f9ed 100644 --- a/server/lib/configuration/channel/sanitize.ts +++ b/server/lib/configuration/channel/sanitize.ts @@ -38,6 +38,7 @@ async function sanitizeChannelConfigurationOptions ( const moderationData = data.moderation ?? {} // comes with livechat 10.3.0 moderationData.delay ??= 0 + moderationData.anonymize ??= false // comes with livechat 11.0.0 // mute not present in livechat <= 10.2.0 const mute = data.mute ?? {} @@ -73,7 +74,8 @@ async function sanitizeChannelConfigurationOptions ( anonymous: _readBoolean(mute, 'anonymous') }, moderation: { - delay: _readInteger(moderationData, 'delay', 0, 60) + delay: _readInteger(moderationData, 'delay', 0, 60), + anonymize: _readBoolean(moderationData, 'anonymize') } } if (terms !== undefined) { diff --git a/server/lib/configuration/channel/storage.ts b/server/lib/configuration/channel/storage.ts index d5dbdf90..d9ecc1fe 100644 --- a/server/lib/configuration/channel/storage.ts +++ b/server/lib/configuration/channel/storage.ts @@ -54,7 +54,8 @@ function getDefaultChannelConfigurationOptions (_options: RegisterServerOptions) anonymous: false }, moderation: { - delay: 0 + delay: 0, + anonymize: false }, terms: undefined } diff --git a/server/lib/external-auth/oidc.ts b/server/lib/external-auth/oidc.ts index a694d00e..b2780450 100644 --- a/server/lib/external-auth/oidc.ts +++ b/server/lib/external-auth/oidc.ts @@ -87,8 +87,8 @@ class ExternalAuthOIDC { private readonly redirectUrl: string private readonly connectUrl: string private readonly externalVirtualhost: string - private readonly avatarsDir: string - private readonly avatarsFiles: string[] + private readonly avatarsDir: string | undefined + private readonly avatarsFiles: string[] | undefined private readonly encryptionOptions = { algorithm: 'aes256' as string, @@ -129,8 +129,8 @@ class ExternalAuthOIDC { connectUrl: string redirectUrl: string externalVirtualhost: string - avatarsDir: string - avatarsFiles: string[] + avatarsDir?: string + avatarsFiles?: string[] }) { this.logger = { debug: (s) => params.logger.debug('[ExternalAuthOIDC] ' + s), @@ -591,8 +591,8 @@ class ExternalAuthOIDC { */ private async getRandomAvatar (): Promise { try { - if (!this.avatarsDir || !this.avatarsFiles.length) { - throw new Error('Seems there is no default avatars') + if (!this.avatarsDir || !this.avatarsFiles?.length) { + return undefined } const file = this.avatarsFiles[Math.floor(Math.random() * this.avatarsFiles.length)] diff --git a/server/lib/firewall/config.ts b/server/lib/firewall/config.ts new file mode 100644 index 00000000..e29eaa88 --- /dev/null +++ b/server/lib/firewall/config.ts @@ -0,0 +1,210 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { RegisterServerOptions } from '@peertube/peertube-types' +import type { AdminFirewallConfiguration } from '../../../shared/lib/types' +import * as path from 'path' +import * as fs from 'fs' +import { + firewallNameRegexp, maxFirewallFileSize, maxFirewallFiles, maxFirewallNameLength +} from '../../../shared/lib/admin-firewall' + +/** + * Indicates if the firewall configuration can be changed in the Peertube web interface. + * Sys admins can disable this feature by creating a special file in the plugin folder. + * @param options Peertube server options + */ +export async function canEditFirewallConfig (options: RegisterServerOptions): Promise { + const peertubeHelpers = options.peertubeHelpers + const logger = peertubeHelpers.logger + if (!peertubeHelpers.plugin) { + return false + } + + const filepath = path.resolve(peertubeHelpers.plugin.getDataDirectoryPath(), 'disable_mod_firewall_editing') + try { + // Testing if file exist by reading it. + await fs.promises.readFile(filepath) + return false + } catch (err: any) { + if (('code' in err) && err.code === 'ENOENT') { + // File does not exist + return true + } + logger.error(err) + // Here it is safer to disable the editing... + return false + } +} + +/** + * Returns the list of mod_firewall configuration files. + * @param options: Peertube server options. + * @param dir the path to the directory containing these configuration files. + * @param includeDisabled if true, disabled files are included in the results. + */ +export async function listModFirewallFiles ( + options: RegisterServerOptions, + dir: string, + includeDisabled?: boolean +): Promise { + try { + const files = (await fs.promises.readdir(dir, { withFileTypes: true })).filter(file => { + if (!file.isFile()) { + return false + } + + if ( + file.name.endsWith('.pfw') && + // we only load valid names, to avoid having files that could not be edited from frontend + firewallNameRegexp.test(file.name.substring(0, file.name.length - 4)) + ) { + return true + } + + if ( + includeDisabled && + file.name.endsWith('.pfw.disabled') && + firewallNameRegexp.test(file.name.substring(0, file.name.length - 13)) + ) { + return true + } + + return false + }) + + return files.map(f => path.join(dir, f.name)).sort() + } catch (err) { + // should be that the directory does not exists + return [] + } +} + +/** + * Returns the modFirewall configuration. + * @param options Peertube server options + * @param dir the path to the directory containing these configuration files. + * @throws will throw an error if it can't read any of the configuration file. + */ +export async function getModFirewallConfig ( + options: RegisterServerOptions, + dir: string +): Promise { + const filePaths = await listModFirewallFiles(options, dir, true) + + const files = [] + for (const filePath of filePaths) { + const content = (await fs.promises.readFile(filePath)).toString() + const name = path.basename(filePath).replace(/\.pfw(\.disabled)?$/, '') + files.push({ + name, + content, + enabled: !filePath.endsWith('.disabled') + }) + } + + const enabled = (await options.settingsManager.getSetting('prosody-firewall-enabled')) === true + + return { + enabled, + files + } +} + +/** + * Sanitize any data received from the frontend, to store in modFirewall configuration. + * Throws an exception if data is invalid. + * @param options Peertube server options + * @param data Incoming data + */ +export async function sanitizeModFirewallConfig ( + options: RegisterServerOptions, + data: any +): Promise { + if (typeof data !== 'object') { + throw new Error('Invalid data type') + } + if (!Array.isArray(data.files)) { + throw new Error('Invalid data.files') + } + + if (data.files.length > maxFirewallFiles) { + throw new Error('Too many files') + } + + const files: AdminFirewallConfiguration['files'] = [] + for (const entry of data.files) { + if (typeof entry !== 'object') { + throw new Error('Invalid data in data.files') + } + if (typeof entry.enabled !== 'boolean') { + throw new Error('Invalid data in data.files (enabled)') + } + if (typeof entry.name !== 'string') { + throw new Error('Invalid data in data.files (name)') + } + if (typeof entry.content !== 'string') { + throw new Error('Invalid data in data.files (content)') + } + + if (entry.name.length > maxFirewallNameLength || !firewallNameRegexp.test(entry.name)) { + throw new Error('Invalid name in data.files') + } + if (entry.content.length > maxFirewallFileSize) { + throw new Error('File content too big in data.files') + } + + files.push({ + enabled: entry.enabled, + name: entry.name, + content: entry.content + }) + } + + const result = { + enabled: !!data.enabled, // this is not saved, so no need to check type. + files + } + + return result +} + +/** + * Saves the modFirewall configuration. + * FIXME: currently, if the save fails on one file, remaining files will not be saved. So there is a risk of data loss. + * @param options Peertube server options + * @param dir the path to the directory containing these configuration files. + * @param config the configuration to save + * @throws will throw an error if it can't read any of the configuration file. + */ +export async function saveModFirewallConfig ( + options: RegisterServerOptions, + dir: string, + config: AdminFirewallConfiguration +): Promise { + const logger = options.peertubeHelpers.logger + + const previousFiles = await listModFirewallFiles(options, dir, true) + + logger.debug('[mod-firewall-lib] Creating the ' + dir + ' directory.') + await fs.promises.mkdir(dir, { recursive: true }) + + const seen = new Map() + for (const f of config.files) { + const filePath = path.join( + dir, + f.name + '.pfw' + (f.enabled ? '' : '.disabled') + ) + logger.info('[mod-firewall-lib] Saving ' + filePath) + await fs.promises.writeFile(filePath, f.content) + seen.set(filePath, true) + } + + // Removing deprecated files: + for (const p of previousFiles) { + if (seen.has(p)) { continue } + logger.info('[mod-firewall-lib] Deleting deprecated file ' + p) + await fs.promises.rm(p) + } +} diff --git a/server/lib/middlewares/is-admin.ts b/server/lib/middlewares/is-admin.ts new file mode 100644 index 00000000..d220513c --- /dev/null +++ b/server/lib/middlewares/is-admin.ts @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { RegisterServerOptions } from '@peertube/peertube-types' +import type { Request, Response, NextFunction } from 'express' +import type { RequestPromiseHandler } from './async' +import { isUserAdmin } from '../helpers' + +/** + * Returns a middleware handler to check if advanced configuration is not disabled + * @param options Peertube server options + * @returns middleware function + */ +function checkUserIsAdminMiddleware (options: RegisterServerOptions): RequestPromiseHandler { + return async (req: Request, res: Response, next: NextFunction) => { + const logger = options.peertubeHelpers.logger + if (!await isUserAdmin(options, res)) { + logger.warn('Current user tries to access a page only allowed for admins, and has no right.') + res.sendStatus(403) + return + } + + logger.debug('User is admin, can access the page..') + next() + } +} + +export { + checkUserIsAdminMiddleware +} diff --git a/server/lib/migration/settings.ts b/server/lib/migration/settings.ts index b1a19d63..f73f729f 100644 --- a/server/lib/migration/settings.ts +++ b/server/lib/migration/settings.ts @@ -3,11 +3,77 @@ // SPDX-License-Identifier: AGPL-3.0-only import type { RegisterServerOptions } from '@peertube/peertube-types' +import { pluginShortName } from '../helpers' async function migrateSettings (options: RegisterServerOptions): Promise { const logger = options.peertubeHelpers.logger logger.info('Checking if there is a migration script to launch...') // 2022-10-10: as we removed the «chat-type» settings, there is no migration needed for now. + // 2024-09-02: concord theme was removed from ConverseJS, must change if used. + await _migrateConverseTheme(options) +} + +async function _migrateConverseTheme (options: RegisterServerOptions): Promise { + const peertubeHelpers = options.peertubeHelpers + const logger = peertubeHelpers.logger + // NB: we cant use safely settingsManager.getSetting, because settings are not registered yet. + logger.info('Checking if we need to migrate converse-theme') + if (!/^[-a-z]+$/.test(pluginShortName)) { + // to prevent sql injection... be sure there is no special char here. + throw new Error(`Wrong pluginShortName '${pluginShortName}'`) + } + const [results] = await peertubeHelpers.database.query( + 'SELECT "settings" FROM "plugin"' + + ' WHERE "plugin"."name" = :pluginShortName', + { + replacements: { + pluginShortName + } + } + ) + if (!Array.isArray(results)) { + throw new Error('_migrateConverseTheme: query result is not an array.') + } + if (results.length === 0) { + logger.error('Plugin not found in database') + return + } + if (results.length > 1) { + logger.error('Multiple lines for plugin in database, dont know which one to migrate... Aborting.') + return + } + const settings = results[0].settings + if (!settings) { + logger.info('Plugin settings are empty in database, no migration needed.') + return + } + if (typeof settings !== 'object') { + logger.error('Plugin settings in database seems to be invalid json') + return + } + if (!('converse-theme' in settings)) { + logger.debug('The setting converse-theme is not here, no need to migrate.') + return + } + if (settings['converse-theme'] !== 'concord') { + logger.debug('The setting converse-theme is not set to concord, no need to migrate.') + return + } + + logger.info('The setting converse-theme is set to concord, we must replace by peertube..') + await peertubeHelpers.database.query( + 'UPDATE "plugin" ' + + ' SET "settings" = "settings" || :value ' + + ' WHERE "name" = :pluginShortName', + { + replacements: { + pluginShortName, + value: JSON.stringify({ + 'converse-theme': 'peertube' + }) + } + } + ) } export { diff --git a/server/lib/prosody/config.ts b/server/lib/prosody/config.ts index c132dfa8..25557f3b 100644 --- a/server/lib/prosody/config.ts +++ b/server/lib/prosody/config.ts @@ -18,6 +18,7 @@ import { getRemoteServerInfosDir } from '../federation/storage' import { BotConfiguration } from '../configuration/bot' import { debugMucAdmins } from '../debug' import { ExternalAuthOIDC } from '../external-auth/oidc' +import { listModFirewallFiles } from '../firewall/config' async function getWorkingDir (options: RegisterServerOptions): Promise { const peertubeHelpers = options.peertubeHelpers @@ -102,14 +103,23 @@ async function getProsodyFilePaths (options: RegisterServerOptions): Promise() @@ -356,7 +368,9 @@ async function getProsodyConfig (options: RegisterServerOptionsV5): Promise { await initPromoteApiRouter(options, router) await initEmojisRouter(options, router) + await initAdminFirewallApiRouter(options, router) + if (isDebugMode(options)) { // Only add this route if the debug mode is enabled at time of the server launch. // Note: the isDebugMode will be tested again when the API is called. diff --git a/server/lib/routers/api/admin/firewall.ts b/server/lib/routers/api/admin/firewall.ts new file mode 100644 index 00000000..502d2738 --- /dev/null +++ b/server/lib/routers/api/admin/firewall.ts @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +import type { RegisterServerOptions } from '@peertube/peertube-types' +import type { Router, Request, Response, NextFunction } from 'express' +import type { AdminFirewallConfiguration } from '../../../../../shared/lib/types' +import { asyncMiddleware, RequestPromiseHandler } from '../../../middlewares/async' +import { checkUserIsAdminMiddleware } from '../../../middlewares/is-admin' +import { + getModFirewallConfig, sanitizeModFirewallConfig, saveModFirewallConfig, canEditFirewallConfig +} from '../../../firewall/config' +import { getProsodyFilePaths, writeProsodyConfig } from '../../../prosody/config' +import { reloadProsody } from '../../../prosody/ctl' + +function canEditFirewallConfigMiddleware (options: RegisterServerOptions): RequestPromiseHandler { + return async (req: Request, res: Response, next: NextFunction) => { + if (!await canEditFirewallConfig(options)) { + options.peertubeHelpers.logger.info('Firewall configuration editing is disabled') + res.sendStatus(403) + return + } + next() + } +} + +async function initAdminFirewallApiRouter (options: RegisterServerOptions, router: Router): Promise { + const logger = options.peertubeHelpers.logger + + router.get('/admin/firewall', asyncMiddleware([ + checkUserIsAdminMiddleware(options), + canEditFirewallConfigMiddleware(options), + async (req: Request, res: Response, _next: NextFunction): Promise => { + try { + const prosodyPaths = await getProsodyFilePaths(options) + const result: AdminFirewallConfiguration = await getModFirewallConfig(options, prosodyPaths.modFirewallFiles) + res.status(200) + res.json(result) + } catch (err) { + options.peertubeHelpers.logger.error(err) + res.sendStatus(500) + } + } + ])) + + router.post('/admin/firewall', asyncMiddleware([ + checkUserIsAdminMiddleware(options), + canEditFirewallConfigMiddleware(options), + async (req: Request, res: Response, _next: NextFunction): Promise => { + try { + const prosodyPaths = await getProsodyFilePaths(options) + + let data: AdminFirewallConfiguration + try { + data = await sanitizeModFirewallConfig(options, req.body) + } catch (err) { + logger.error(err) + res.sendStatus(400) + return + } + + await saveModFirewallConfig(options, prosodyPaths.modFirewallFiles, data) + + logger.info('Just saved a new mod_firewall const, must rewrite Prosody configuration file, and reload Prosody.') + await writeProsodyConfig(options) + await reloadProsody(options) + + const result: AdminFirewallConfiguration = await getModFirewallConfig(options, prosodyPaths.modFirewallFiles) + res.status(200) + res.json(result) + } catch (err) { + options.peertubeHelpers.logger.error(err) + res.sendStatus(500) + } + } + ])) +} + +export { + initAdminFirewallApiRouter +} diff --git a/server/lib/routers/api/room.ts b/server/lib/routers/api/room.ts index ec2d0da8..a3efbad6 100644 --- a/server/lib/routers/api/room.ts +++ b/server/lib/routers/api/room.ts @@ -39,6 +39,7 @@ interface RoomDefaults { mute_anonymous?: boolean livechat_muc_terms?: string moderation_delay?: number + anonymize_moderation_actions?: boolean } affiliations?: Affiliations } @@ -54,7 +55,8 @@ async function _getChannelSpecificOptions ( slow_mode_duration: channelOptions.slowMode.duration, mute_anonymous: channelOptions.mute.anonymous, livechat_muc_terms: channelOptions.terms, - moderation_delay: channelOptions.moderation.delay + moderation_delay: channelOptions.moderation.delay, + anonymize_moderation_actions: channelOptions.moderation.anonymize } } diff --git a/server/lib/settings.ts b/server/lib/settings.ts index 3b82fdde..ca45e7a9 100644 --- a/server/lib/settings.ts +++ b/server/lib/settings.ts @@ -11,9 +11,10 @@ import { ExternalAuthOIDC, ExternalAuthOIDCType } from './external-auth/oidc' import { Emojis } from './emojis' import { LivechatProsodyAuth } from './prosody/auth' import { loc } from './loc' +import { canEditFirewallConfig } from './firewall/config' const escapeHTML = require('escape-html') -type AvatarSet = 'sepia' | 'cat' | 'bird' | 'fenec' | 'abstract' | 'legacy' | 'nctv' +type AvatarSet = 'sepia' | 'cat' | 'bird' | 'fenec' | 'abstract' | 'legacy' | 'none' | 'nctv' async function initSettings (options: RegisterServerOptions): Promise { const { peertubeHelpers, settingsManager } = options @@ -27,7 +28,7 @@ async function initSettings (options: RegisterServerOptions): Promise { initAdvancedChannelCustomizationSettings(options) initChatBehaviourSettings(options) initThemingSettings(options) - initChatServerAdvancedSettings(options) + await initChatServerAdvancedSettings(options) await ExternalAuthOIDC.initSingletons(options) const loadOidcs = (): void => { @@ -511,7 +512,8 @@ function initThemingSettings ({ registerSetting }: RegisterServerOptions): void { value: 'bird', label: loc('avatar_set_option_bird') }, { value: 'fenec', label: loc('avatar_set_option_fenec') }, { value: 'abstract', label: loc('avatar_set_option_abstract') }, - { value: 'legacy', label: loc('avatar_set_option_legacy') } + { value: 'legacy', label: loc('avatar_set_option_legacy') }, + { value: 'none', label: loc('avatar_set_option_none') } ] as Array<{ value: AvatarSet label: string @@ -525,9 +527,9 @@ function initThemingSettings ({ registerSetting }: RegisterServerOptions): void default: 'peertube' as ConverseJSTheme, private: false, options: [ - { value: 'peertube', label: loc('peertube') }, - { value: 'default', label: loc('default') }, - { value: 'concord', label: loc('concord') } + { value: 'peertube', label: loc('converse_theme_option_peertube') }, + { value: 'default', label: loc('converse_theme_option_default') }, + { value: 'cyberpunk', label: loc('converse_theme_option_cyberpunk') } ] as Array<{value: ConverseJSTheme, label: string}>, descriptionHTML: loc('converse_theme_description') }) @@ -555,7 +557,9 @@ function initThemingSettings ({ registerSetting }: RegisterServerOptions): void * Registers settings related to the "Chat server advanded settings" section. * @param param0 server options */ -function initChatServerAdvancedSettings ({ registerSetting }: RegisterServerOptions): void { +async function initChatServerAdvancedSettings (options: RegisterServerOptions): Promise { + const { registerSetting } = options + registerSetting({ name: 'prosody-advanced', type: 'html', @@ -723,6 +727,23 @@ function initChatServerAdvancedSettings ({ registerSetting }: RegisterServerOpti private: true, descriptionHTML: loc('prosody_components_list_description') }) + + registerSetting({ + name: 'prosody-firewall-enabled', + label: loc('prosody_firewall_label'), + type: 'input-checkbox', + default: false, + private: true, + descriptionHTML: loc('prosody_firewall_description') + }) + if (await canEditFirewallConfig(options)) { + registerSetting({ + type: 'html', + name: 'prosody-firewall-configure-button', + private: true, + descriptionHTML: loc('prosody_firewall_configure_button') + }) + } } export { diff --git a/shared/lib/admin-firewall.ts b/shared/lib/admin-firewall.ts new file mode 100644 index 00000000..36d4fabf --- /dev/null +++ b/shared/lib/admin-firewall.ts @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +// Note: API request body size is limited to 100Kb (expressjs body-parser defaut limit, and Peertube nginx config). +// So we must be sure to never send more than 100Kb. +// All files are sent in one JSON object. +export const maxFirewallFileSize: number = 3 * 1024 +export const maxFirewallFiles = 20 + +export const maxFirewallNameLength = 20 +export const firewallNameRegexp = /^[a-zA-Z0-9_-]+$/ diff --git a/shared/lib/types.ts b/shared/lib/types.ts index a827efb7..9d3915da 100644 --- a/shared/lib/types.ts +++ b/shared/lib/types.ts @@ -13,7 +13,7 @@ interface ActorImage { updatedAt: Date | string } -type ConverseJSTheme = 'peertube' | 'default' | 'concord' +type ConverseJSTheme = 'peertube' | 'default' | 'cyberpunk' interface InitConverseJSParams { peertubeVideoOriginalUrl?: string @@ -109,6 +109,7 @@ interface ChannelConfigurationOptions { terms?: string // comes with Livechat 10.2.0 moderation: { // comes with Livechat 10.3.0 delay: number + anonymize: boolean // comes with Livechat 11.0.0 } } @@ -191,6 +192,17 @@ interface LivechatToken { date: number } +interface AdminFirewallConfigurationFile { + name: string + content: string + enabled: boolean +} + +interface AdminFirewallConfiguration { + enabled: boolean + files: AdminFirewallConfigurationFile[] +} + export type { ConverseJSTheme, InitConverseJSParams, @@ -211,5 +223,7 @@ export type { ChannelEmojis, ChannelEmojisConfiguration, ProsodyAuthentInfos, - LivechatToken + LivechatToken, + AdminFirewallConfiguration, + AdminFirewallConfigurationFile } diff --git a/support/documentation/config.toml b/support/documentation/config.toml index b2cda28e..089114b8 100644 --- a/support/documentation/config.toml +++ b/support/documentation/config.toml @@ -6,21 +6,20 @@ baseURL = "http://localhost:1313/peertube-plugin-livechat/" # this will be overr languageCode = "en-us" defaultContentLanguage = "en" title = "Peertube plugin livechat" -theme = 'hugo-theme-learn' +theme = 'hugo-theme-relearn' [outputs] -home = [ "HTML", "RSS", "JSON"] +home = [ "HTML", "RSS", "SEARCH"] [params] - author = "John Livingston" - description = "Peertube plugin livechat documentation" showVisitedLinks = true disableSearch = false disableLandingPageButton = false + landingPageName = " Livechat" themeVariant = "red" - landingPageURL = "/peertube-plugin-livechat/" - landingPageName = " Home" - custom_css = ["css/livechatdoc.css"] + + [params.author] + name = "John Livingston" [[menu.shortcuts]] name = " Github repository" @@ -34,187 +33,185 @@ weight = 20 [Languages] [Languages.en] + weight = 1 title = "Peertube plugin livechat documentation" languageName = "English" contentDir = "content/en" [Languages.ar] + weight = 2 languageName = "العربية" - landingPageURL = "/peertube-plugin-livechat/ar/" contentDir = "content/translations/ar" [Languages.ca] + weight = 3 languageName = "Català" - landingPageURL = "/peertube-plugin-livechat/ca/" contentDir = "content/translations/ca" [Languages.cs] + weight = 4 languageName = "Čeština" - landingPageURL = "/peertube-plugin-livechat/cs/" contentDir = "content/translations/cs" [Languages.de] + weight = 5 title = "Peertube Plugin Livechat Dokumentation" languageName = "Deutsch" - landingPageName = " Home" - landingPageURL = "/peertube-plugin-livechat/de/" contentDir = "content/translations/de" [Languages.el] + weight = 6 languageName = "ελληνικά" - landingPageURL = "/peertube-plugin-livechat/el/" contentDir = "content/translations/el" [Languages.eo] + weight = 7 languageName = "Esperanto" - landingPageURL = "/peertube-plugin-livechat/eo/" contentDir = "content/translations/eo" [Languages.es] + weight = 8 languageName = "Español" - landingPageURL = "/peertube-plugin-livechat/es/" contentDir = "content/translations/es" [Languages.eu] + weight = 9 languageName = "Euskara" - landingPageURL = "/peertube-plugin-livechat/eu/" contentDir = "content/translations/eu" [Languages.fa] + weight = 10 languageName = "فارسی" - landingPageURL = "/peertube-plugin-livechat/fa/" contentDir = "content/translations/fa" [Languages.fi] + weight = 11 languageName = "Suomi" - landingPageURL = "/peertube-plugin-livechat/fi/" contentDir = "content/translations/fi" [Languages.fr] + weight = 12 title = "Documentation plugin Peertube livechat" languageName = "Français" - landingPageName = " Accueil" - landingPageURL = "/peertube-plugin-livechat/fr/" contentDir = "content/translations/fr" [Languages.gd] + weight = 13 languageName = "Gàidhlig" - landingPageURL = "/peertube-plugin-livechat/gd/" contentDir = "content/translations/gd" [Languages.gl] + weight = 14 languageName = "Galego" - landingPageURL = "/peertube-plugin-livechat/gl/" contentDir = "content/translations/gl" [Languages.hr] + weight = 15 languageName = "Hrvatski" - landingPageURL = "/peertube-plugin-livechat/hr/" contentDir = "content/translations/hr" [Languages.hu] + weight = 16 languageName = "Magyar" - landingPageURL = "/peertube-plugin-livechat/hu/" contentDir = "content/translations/hu" [Languages.is] + weight = 17 languageName = "Íslenska" - landingPageURL = "/peertube-plugin-livechat/is/" contentDir = "content/translations/is" [Languages.it] + weight = 18 languageName = "Italiano" - landingPageURL = "/peertube-plugin-livechat/it/" contentDir = "content/translations/it" [Languages.ja] + weight = 19 title = "PeerTube ライブチャットプラグイン" languageName = "日本語バージョン" - landingPageName = " Home" - landingPageURL = "/peertube-plugin-livechat/ja/" contentDir = "content/translations/ja" [Languages.kab] + weight = 20 languageName = "Taqbaylit" - landingPageURL = "/peertube-plugin-livechat/ka/" contentDir = "content/translations/kab" [Languages.nb] + weight = 21 languageName = "Norsk bokmål" - landingPageURL = "/peertube-plugin-livechat/nb/" contentDir = "content/translations/nb" [Languages.nl] + weight = 22 languageName = "Nederlands" - landingPageURL = "/peertube-plugin-livechat/nl/" contentDir = "content/translations/nl" [Languages.nn] + weight = 23 languageName = "Norsk nynorsk" - landingPageURL = "/peertube-plugin-livechat/nn/" contentDir = "content/translations/nn" [Languages.oc] + weight = 24 languageName = "Occitan" - landingPageURL = "/peertube-plugin-livechat/oc/" contentDir = "content/translations/oc" [Languages.pl] + weight = 25 languageName = "Polski" - landingPageURL = "/peertube-plugin-livechat/pl/" contentDir = "content/translations/pl" [Languages.pt] + weight = 26 languageName = "uguês" - landingPageURL = "/peertube-plugin-livechat/pt/" contentDir = "content/translations/pt" [Languages.ru] + weight = 27 languageName = "Pусский" - landingPageURL = "/peertube-plugin-livechat/ru/" contentDir = "content/translations/ru" [Languages.sq] + weight = 28 languageName = "Shqip" - landingPageURL = "/peertube-plugin-livechat/sq/" contentDir = "content/translations/sq" [Languages.sv] + weight = 29 languageName = "Svenska" - landingPageURL = "/peertube-plugin-livechat/sv/" contentDir = "content/translations/sv" [Languages.th] + weight = 30 languageName = "ไทย" - landingPageURL = "/peertube-plugin-livechat/th/" contentDir = "content/translations/th" [Languages.tr] + weight = 31 languageName = "Türkçe" - landingPageURL = "/peertube-plugin-livechat/tr/" contentDir = "content/translations/tr" [Languages.tok] + weight = 32 languageName = "Toki Pona" - landingPageURL = "/peertube-plugin-livechat/to/" contentDir = "content/translations/tok" [Languages.uk] + weight = 33 languageName = "украї́нська мо́ва" - landingPageURL = "/peertube-plugin-livechat/uk/" contentDir = "content/translations/uk" [Languages.vi] + weight = 34 languageName = "Tiếng Việt" - landingPageURL = "/peertube-plugin-livechat/vi/" contentDir = "content/translations/vi" [Languages.zh-Hans] + weight = 35 languageName = "简体中文(中国)" - landingPageURL = "/peertube-plugin-livechat/zh-Hans/" contentDir = "content/translations/zh-Hans" [Languages.zh-Hant] + weight = 36 languageName = "繁體中文(台灣" - landingPageURL = "/peertube-plugin-livechat/zh-Hant/" contentDir = "content/translations/zh-Hant" diff --git a/support/documentation/content/en/_index.md b/support/documentation/content/en/_index.md index 6d762580..3951b333 100644 --- a/support/documentation/content/en/_index.md +++ b/support/documentation/content/en/_index.md @@ -1,11 +1,14 @@ -# PeerTube plugin livechat +--- +title: "Peertube livechat" +description: "Peertube plugin livechat documentation" +--- {{% notice tip %}} You can use the language selector in the left menu to view this documentation in different languages. Some translations are missing or incomplete. In this case, you'll see the English version of the text. {{% /notice %}} -![Chat screenshot](/peertube-plugin-livechat/images/chat.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video page, with a web chat on the right of the video.](/peertube-plugin-livechat/images/chat.png?classes=shadow,border&height=200px "Chat screenshot") Welcome the **Peertube Livechat Plugin** documentation. diff --git a/support/documentation/content/en/contributing/document/_index.md b/support/documentation/content/en/contributing/document/_index.md index 69cb336a..1bc429f8 100644 --- a/support/documentation/content/en/contributing/document/_index.md +++ b/support/documentation/content/en/contributing/document/_index.md @@ -17,7 +17,10 @@ The documentation source code is in the `support/documentation/content` folder. The documentation is generated using [Hugo](https://gohugo.io/). You have to install it on your computer if you want to preview your work. -The used theme is [hugo-theme-learn](https://learn.netlify.app/). +The minimum required version for Hugo is 0.121.0. +It was tested using version 0.132.2. + +The used theme is [hugo-theme-relearn](https://mcshelby.github.io/hugo-theme-relearn). You should read its documentation before starting editing the documentation. When a new plugin version is released, or when documentation is updated, plugin maintainers will merge the `main` branch to the `documentation` branch. diff --git a/support/documentation/content/en/documentation/admin/advanced/_index.md b/support/documentation/content/en/documentation/admin/advanced/_index.md index 81290c44..b9856d83 100644 --- a/support/documentation/content/en/documentation/admin/advanced/_index.md +++ b/support/documentation/content/en/documentation/admin/advanced/_index.md @@ -1,7 +1,7 @@ --- title: "Advanced usage" description: "Some advanced features" -weight: 20 +weight: 40 chapter: false --- diff --git a/support/documentation/content/en/documentation/admin/advanced/xmpp_clients.md b/support/documentation/content/en/documentation/admin/advanced/xmpp_clients.md index d8774472..7dbdbae0 100644 --- a/support/documentation/content/en/documentation/admin/advanced/xmpp_clients.md +++ b/support/documentation/content/en/documentation/admin/advanced/xmpp_clients.md @@ -113,7 +113,7 @@ You must then place these certificates in a folder that will be accessible to th {{% notice tip %}} If you want to use the ProsodyCtl utility to import certificates, this utility is available (once Peertube is started) using the following command (adapting the path to your Peertube data folder, and replacing "xxx" with the arguments you wish to pass to -prosodyctl): `sudo -u peertube /var/www/peertube/storage/plugins/data/peertube-plugin-livechat/prosodyAppImage/squashfs-root/AppRun prosodyctl xxx` +prosodyctl): `sudo -u peertube /var/www/peertube/storage/plugins/data/peertube-plugin-livechat/prosodyAppImage/squashfs-root/AppRun prosodyctl --config /var/www/peertube/storage/plugins/data/peertube-plugin-livechat/prosody/prosody.cfg.lua xxx` {{% /notice %}} The plugin will check once a day to see if any files have been modified in this folder, and reload Prosody if necessary. diff --git a/support/documentation/content/en/documentation/admin/external_auth.md b/support/documentation/content/en/documentation/admin/external_auth.md index c6c3ca42..8bc6424f 100644 --- a/support/documentation/content/en/documentation/admin/external_auth.md +++ b/support/documentation/content/en/documentation/admin/external_auth.md @@ -14,9 +14,9 @@ Such "external account users" will be easier to moderate than anonymous accounts This also allows user to join the chat without creating Peertube account (in case your instance has closed registration for example, or without waiting for account approval). -![External login button](/peertube-plugin-livechat/images/external_login_button.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video page, with a chat on the right. At the bottom of the chat, there is a "{{% livechat_label login_using_external_account %}}" button.](/peertube-plugin-livechat/images/external_login_button.png?classes=shadow,border&height=200px "{{% livechat_label login_using_external_account %}} button") -![External login dialog - OpenID Connect](/peertube-plugin-livechat/images/external_login_dialog_oidc.png?classes=shadow,border&height=200px) +![Screenshot of a dialog with an "OpenID Connect" button.](/peertube-plugin-livechat/images/external_login_dialog_oidc.png?classes=shadow,border&height=200px "External login dialog - OpenID Connect") This page will describe available authentication methods. @@ -49,7 +49,7 @@ You will now have to fill some settings. This is the button label in the following screenshot: -![External login dialog - OpenID Connect](/peertube-plugin-livechat/images/external_login_dialog_oidc.png?classes=shadow,border&height=200px) +![Screenshot of a dialog with an "OpenID Connect" button.](/peertube-plugin-livechat/images/external_login_dialog_oidc.png?classes=shadow,border&height=200px "External login dialog - OpenID Connect") For now, it is not possible to localize this label. diff --git a/support/documentation/content/en/documentation/admin/mod_firewall.md b/support/documentation/content/en/documentation/admin/mod_firewall.md new file mode 100644 index 00000000..404e3c00 --- /dev/null +++ b/support/documentation/content/en/documentation/admin/mod_firewall.md @@ -0,0 +1,55 @@ +--- +title: "Prosody mod_firewall" +description: "Advanced firewall rules for the Prosody server" +weight: 30 +chapter: false +--- + +{{% notice info %}} +This feature comes with the livechat plugin version 11.0.0. +{{% /notice %}} + +You can enable [mod_firewall](https://modules.prosody.im/mod_firewall) on your Prosody server. + +Doing so, Peertube admins will be able to define advanced firewall rules. + +{{% notice warning %}} +These rules could be used to run arbitrary code on the server. +If you are a hosting provider, and you don't want to allow Peertube admins to write such rules, you can disable the online editing by creating a `disable_mod_firewall_editing` file in the plugin directory (`plugins/data/peertube-plugin-livechat/disable_mod_firewall_editing`). +This is opt-out, as Peertube admins can already run arbitrary code just by installing any plugin. +You can still use mod_firewall by editing files directly on the server. +{{% /notice %}} + +## Edit rules + +First, you must enable the feature in the [plugin settings](/peertube-plugin-livechat/documentation/admin/settings). + +Just bellow the settings, you will find a "Configure mod_firewall" button. +This button will open a configuration page. + +![Screenshot of the "{{% livechat_label prosody_firewall_configuration %}}" form.](/peertube-plugin-livechat/images/mod_firewall.png?classes=shadow,border&height=400px "{{% livechat_label prosody_firewall_configuration %}}") + +Here you can add several configuration files. + +You can enable/disable each files. + +Files will be loaded in the alphabetical order. +You can use a number as prefix to easily choose the order. + +{{% notice info %}} +You can also edit these firewall rules directly on the server, in the `plugins/data/peertube-plugin-livechat/prosody/mod_firewall_config/` directory. +File names must only contains alphanumerical characters, underscores and hyphens. +The extension must be `.pfw`, or `.pfw.disabled` if you want to disable a file. +Please be sure that the peertube system user has write access to these files, else the web editing interface will fail. +Once you have edited these files, you must reload prosody. +This can be done by saving the plugin settings, or saving the mod_firewall configuration in the web interface, or by restarting Peertube. +{{% /notice %}} + +When you save the configuration, the server will automatically reload it, and your rules will apply immediatly. +You can check that there is no parsing error in the Prosody error log. +To do so, you can read the `plugins/data/peertube-plugin-livechat/prosody/prosody.err` file, or use the [diagnostic tool](/peertube-plugin-livechat/documentation/installation/troubleshooting/) that will show last Prosody errors. + +## Examples + +Don't hesitate to share your rules. +To do so, you can for example edit this [page](/peertube-plugin-livechat/contributing/document/#write-documentation). diff --git a/support/documentation/content/en/documentation/admin/settings.md b/support/documentation/content/en/documentation/admin/settings.md index b6167453..a778bd15 100644 --- a/support/documentation/content/en/documentation/admin/settings.md +++ b/support/documentation/content/en/documentation/admin/settings.md @@ -120,27 +120,27 @@ You can choose from several different sets the default avatars that will be used {{% livechat_label avatar_set_option_sepia %}}: [David Revoy's Peertube avatar generator](https://www.peppercarrot.com/extras/html/2023_peertube-generator/), [CC-By](https://creativecommons.org/licenses/by/4.0/) license -![Sepia](/peertube-plugin-livechat/images/avatar_sepia.png?classes=shadow,border&height=40px) +![Sepia avatar example](/peertube-plugin-livechat/images/avatar_sepia.png?classes=shadow,border&height=40px "Sepia") {{% livechat_label avatar_set_option_cat %}}: [David Revoy's cat avatar generator](https://www.peppercarrot.com/extras/html/2016_cat-generator/), [CC-By](https://creativecommons.org/licenses/by/4.0/) license -![Cats](/peertube-plugin-livechat/images/avatar_cat.png?classes=shadow,border&height=40px) +![Cats avatar example](/peertube-plugin-livechat/images/avatar_cat.png?classes=shadow,border&height=40px "Cats") {{% livechat_label avatar_set_option_bird %}}: [David Revoy's bird avatar generator](https://www.peppercarrot.com/extras/html/2019_bird-generator/), [CC-By](https://creativecommons.org/licenses/by/4.0/) license -![Birds](/peertube-plugin-livechat/images/avatar_bird.png?classes=shadow,border&height=40px) +![Birds avatar example](/peertube-plugin-livechat/images/avatar_bird.png?classes=shadow,border&height=40px "Birds") {{% livechat_label avatar_set_option_fenec %}}: [David Revoy's fenec/mobilizon avatar generator](https://www.peppercarrot.com/extras/html/2020_mobilizon-generator/), [CC-By](https://creativecommons.org/licenses/by/4.0/) license -![Fenecs](/peertube-plugin-livechat/images/avatar_fenec.png?classes=shadow,border&height=40px) +![Fenecs avatar example](/peertube-plugin-livechat/images/avatar_fenec.png?classes=shadow,border&height=40px "Fenecs") {{% livechat_label avatar_set_option_abstract %}}: [David Revoy's Abstract avatar generator](https://www.peppercarrot.com/extras/html/2017_abstract-generator/index.php), [CC-By](https://creativecommons.org/licenses/by/4.0/) license -![Abstracts](/peertube-plugin-livechat/images/avatar_abstract.png?classes=shadow,border&height=40px) +![Abstracts avatar example](/peertube-plugin-livechat/images/avatar_abstract.png?classes=shadow,border&height=40px "Abtracts") {{% livechat_label avatar_set_option_legacy %}}: Based on [David Revoy' work](https://www.davidrevoy.com), [AGPL-v3](https://www.gnu.org/licenses/agpl-3.0.en.html) license -![Legacy](/peertube-plugin-livechat/images/avatar_legacy.jpg?classes=shadow,border&height=40px) +![Legacy avatar example](/peertube-plugin-livechat/images/avatar_legacy.jpg?classes=shadow,border&height=40px "Legacy") If you can't see the change immediatly, it could be because of your browser cache. Just clear your browser session storage, or restart it. @@ -150,7 +150,7 @@ You can choose which theme to use for ConverseJS: - Peertube theme: this is a special theme, made especially for peertube's integration. - Default ConverseJS theme: this is the default ConverseJS theme. -- ConverseJS concord theme: this is a theme provided by ConverseJS. +- ConverseJS cyberpunk theme: this is a theme provided by ConverseJS. ### {{% livechat_label autocolors_label %}} @@ -254,3 +254,9 @@ More informations on Prosody external components [here](https://prosody.im/doc/c #### {{% livechat_label prosody_components_list_label %}} {{% livechat_label prosody_components_list_description %}} + +### {{% livechat_label prosody_firewall_label %}} + +You can enable [mod_firewall](https://modules.prosody.im/mod_firewall) on your Prosody server. + +For more information, please check [the documentation](/peertube-plugin-livechat/documentation/admin/mod_firewall/). diff --git a/support/documentation/content/en/documentation/installation/troubleshooting.md b/support/documentation/content/en/documentation/installation/troubleshooting.md index cbf8527a..348a878e 100644 --- a/support/documentation/content/en/documentation/installation/troubleshooting.md +++ b/support/documentation/content/en/documentation/installation/troubleshooting.md @@ -15,11 +15,11 @@ If the chat does not work, there is a diagnostic tool in the plugin's settings p Open the plugin settings, and click on the "launch diagnostic" button. -![Launch diagnostic](/peertube-plugin-livechat/images/launch_diagnostic.png?classes=shadow,border&height=200px) +![Screenshot of the plugin's settings page, with a "launch diagnostic" button.](/peertube-plugin-livechat/images/launch_diagnostic.png?classes=shadow,border&height=200px "Launch diagnostic") If there is any error in the diagnostic page, you can search in this page for a solution, or refer to the [Bug tracking documentation page](/peertube-plugin-livechat/issues/) if you can't find any response. -![Diagnostic result](/peertube-plugin-livechat/images/diagnostic.png?classes=shadow,border&height=200px) +![Screenshot of the diagnostic result page. This gives a lot of information, with status for different test suites.](/peertube-plugin-livechat/images/diagnostic.png?classes=shadow,border&height=200px "Diagnostic result") ## Chat does not load diff --git a/support/documentation/content/en/documentation/user/obs.md b/support/documentation/content/en/documentation/user/obs.md index e08f19b0..ec0560ab 100644 --- a/support/documentation/content/en/documentation/user/obs.md +++ b/support/documentation/content/en/documentation/user/obs.md @@ -12,18 +12,18 @@ In the current page, you will find some advices to handle your live chats using You can easily include the chat in your video stream. -![Embeding the chat in a live stream](/peertube-plugin-livechat/images/embed_chat_in_livestream.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube live, replay, with the chat included at the bottom of the video stream.](/peertube-plugin-livechat/images/embed_chat_in_livestream.png?classes=shadow,border&height=200px "Embeding the chat in a live stream") You can use the "{{% livechat_label share_chat_link %}}" feature to generate an URL to your chat. This button should be near the chat if you are the video owner (unless it was desactivated by your server admins). Check the "{{% livechat_label read_only %}}" checkbox in the modal. -![Share link popup](/peertube-plugin-livechat/images/share_readonly.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, where the "{{% livechat_label read_only %}}" option is checked.](/peertube-plugin-livechat/images/share_readonly.png?classes=shadow,border&height=200px "Share link popup") Then use this link as a "web browser source" in OBS. -![Embeding the chat in OBS](/peertube-plugin-livechat/images/embed_chat_in_obs.png?classes=shadow,border&height=200px) +![Screenshot of the OBS software, where the chat was added as web browser source.](/peertube-plugin-livechat/images/embed_chat_in_obs.png?classes=shadow,border&height=200px "Embeding the chat in OBS") You can use the "{{% livechat_label transparent_background %}}" option to have a transparent background in OBS. If you want to customize the background transparency, you can add this CSS in your OBS browser source's settings: @@ -56,17 +56,17 @@ The livechat plugin offers a way to create long term token that can identify you To do so, just use the "{{% livechat_label share_chat_link %}}" feature, and open the "{{% livechat_label share_chat_dock %}}" tab. From there, you can create a new token using the "+" button. -![Share link popup - dock tab](/peertube-plugin-livechat/images/share_dock.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, on the "{{% livechat_label share_chat_dock %}} tab. A token was generated, and is selectionable."](/peertube-plugin-livechat/images/share_dock.png?classes=shadow,border&height=200px "Share link popup - dock tab") Then, copy the url, and use the "Docks / Custom browser docks" menu from your OBS to add a dock with this URL. -![OBS - Dock menu](/peertube-plugin-livechat/images/obs_dock_menu.png?classes=shadow,border&height=200px) +![Screenshot of the OBS Dock menu, with a "Custom Browser Docks" entry.](/peertube-plugin-livechat/images/obs_dock_menu.png?classes=shadow,border&height=200px "OBS - Dock menu") -![OBS - Dock dialog](/peertube-plugin-livechat/images/obs_dock_dialog.png?classes=shadow,border&height=200px) +![Screenshot of the OBS Custom Browser Docks dialog, with a new dock called "My chat".](/peertube-plugin-livechat/images/obs_dock_dialog.png?classes=shadow,border&height=200px "OBS - Dock dialog") Once you have done, you will have a new dock connected to the chat with your account. -![OBS - Dock](/peertube-plugin-livechat/images/obs_dock.png?classes=shadow,border&height=200px) +![Screenshot of OBS with a new dock including the chat. The user is logged in with their Peertube account, and can chat directly from OBS.](/peertube-plugin-livechat/images/obs_dock.png?classes=shadow,border&height=200px "OBS - Dock") {{% notice tip %}} Tokens are valid to join any chat room. You don't have to generate separate tokens for each of your rooms. diff --git a/support/documentation/content/en/documentation/user/streamers/basics.md b/support/documentation/content/en/documentation/user/streamers/basics.md index 3114f059..79f42c24 100644 --- a/support/documentation/content/en/documentation/user/streamers/basics.md +++ b/support/documentation/content/en/documentation/user/streamers/basics.md @@ -14,12 +14,12 @@ Information in this section are only true in the default case. When you create or modify a Peertube live, there is a "plugin settings" tab: -![New live](/peertube-plugin-livechat/images/new_live.png?classes=shadow,border&height=200px) +![Screenshot of the Peertube new live form.](/peertube-plugin-livechat/images/new_live.png?classes=shadow,border&height=200px "New live") In the "plugin settings" tab, there is a "{{% livechat_label use_chat %}}" checkbox. Just check or uncheck it to enable or disable the chat associated to your video. -![Activate the chat](/peertube-plugin-livechat/images/new_live_activate_chat.png?classes=shadow,border&height=200px) +![Screenshot of the form, with a "{{% livechat_label use_chat %}}" checkbox.](/peertube-plugin-livechat/images/new_live_activate_chat.png?classes=shadow,border&height=200px "Activate the chat") {{% notice tip %}} There can be other settings in this tab, depending on plugins installed on your Peertube instance. @@ -39,7 +39,7 @@ This url can be shared. The "{{% livechat_label share_chat_embed %}}" tab provide some links to embed the chat in websites, or in your live stream. -![Share link popup](/peertube-plugin-livechat/images/share_readonly.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, where the "{{% livechat_label read_only %}}" option is checked.](/peertube-plugin-livechat/images/share_readonly.png?classes=shadow,border&height=200px "Share link popup") You can customize some options: @@ -49,19 +49,19 @@ You can customize some options: For more information on the "{{% livechat_label share_chat_dock %}}" tab, check the [OBS documentation](/peertube-plugin-livechat/documentation/user/obs). -![Share link popup - dock tab](/peertube-plugin-livechat/images/share_dock.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, on the "{{% livechat_label share_chat_dock %}} tab. A token was generated, and is selectionable."](/peertube-plugin-livechat/images/share_dock.png?classes=shadow,border&height=200px "Share link popup - dock tab") In the "{{% livechat_label web %}}" tab, the provided url opens the chat in the Peertube interface. You can share this link to other users to invite them to join the chat. -![Share link popup - web tab](/peertube-plugin-livechat/images/share_web.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, on the "{{% livechat_label web %}} tab. There is a url you can copy.](/peertube-plugin-livechat/images/share_web.png?classes=shadow,border&height=200px "Share link popup - web tab") The "{{% livechat_label share_chat_link %}}" popup can also contain a "{{% livechat_label connect_using_xmpp %}}" tab. This will only be available if your instance's administators have enabled an correctly configured this option. Using this option, you can provide a link to join the chat using any [XMPP client software](https://en.wikipedia.org/wiki/XMPP#Clients). Using such softwares can for example facilitate moderation actions. -![Share link popup - xmpp tab](/peertube-plugin-livechat/images/share_xmpp_dialog.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, on the "{{% livechat_label connect_using_xmpp %}}" tab.](/peertube-plugin-livechat/images/share_xmpp_dialog.png?classes=shadow,border&height=200px "{{% livechat_label connect_using_xmpp %}}") ## Moderation @@ -80,11 +80,11 @@ User joining will see messages posted before their arrival. You can change the persistence behaviour. [Open the chat dropdown menu](/peertube-plugin-livechat/documentation/user/viewers), and click on "Configure". -![Chat menu](/peertube-plugin-livechat/images/top_menu.png?classes=shadow,border&height=200px) +![Screenshot of the dropdown menu at the top of the chat. Several entries are available.](/peertube-plugin-livechat/images/top_menu.png?classes=shadow,border&height=200px "Chat menu") There are several options that can be changed. -![Configure chat room](/peertube-plugin-livechat/images/configure.png?classes=shadow,border&height=200px) +![Screenshot of the chat configuration form.](/peertube-plugin-livechat/images/configure.png?classes=shadow,border&height=200px "Configure chat room") You can for example set the default and maximum number of messages to return to 0, so that new incomers won't see any previously sent message. diff --git a/support/documentation/content/en/documentation/user/streamers/bot/_index.md b/support/documentation/content/en/documentation/user/streamers/bot/_index.md index ffd81d45..d81031d3 100644 --- a/support/documentation/content/en/documentation/user/streamers/bot/_index.md +++ b/support/documentation/content/en/documentation/user/streamers/bot/_index.md @@ -12,7 +12,7 @@ This feature comes with the livechat plugin version 8.0.0, and can be disabled b You can enable a chat bot on your chatrooms. The bot configuration is made channel per channel, and will apply to all related videos' chatrooms. -![Channel configuration](/peertube-plugin-livechat/images/channel_configuration.png?classes=shadow,border&height=400px) +![Screenshot of the channel options. There is a form with multiple fields.](/peertube-plugin-livechat/images/channel_configuration.png?classes=shadow,border&height=400px "Channel configuration") To access this page, check the [channel configuration documentation](/peertube-plugin-livechat/documentation/user/streamers/channel). diff --git a/support/documentation/content/en/documentation/user/streamers/bot/commands.md b/support/documentation/content/en/documentation/user/streamers/bot/commands.md index e80d8bb7..c9a2f773 100644 --- a/support/documentation/content/en/documentation/user/streamers/bot/commands.md +++ b/support/documentation/content/en/documentation/user/streamers/bot/commands.md @@ -7,7 +7,7 @@ chapter: false {{% livechat_label livechat_configuration_channel_command_desc %}} -![Commands configuration](/peertube-plugin-livechat/images/bot_commands.png?classes=shadow,border&height=400px) +![Screenshot of the channel options page, with some fields to configure the bot commands.](/peertube-plugin-livechat/images/bot_commands.png?classes=shadow,border&height=400px "Commands configuration") You can setup several commands. @@ -15,6 +15,6 @@ You can setup several commands. {{% livechat_label livechat_configuration_channel_command_cmd_desc %}} -## {{% livechat_label livechat_configuration_channel_quote_delay_label %}} +## {{% livechat_label livechat_configuration_channel_command_message_label %}} -{{% livechat_label livechat_configuration_channel_quote_delay_desc %}} +{{% livechat_label livechat_configuration_channel_command_message_desc %}} diff --git a/support/documentation/content/en/documentation/user/streamers/bot/forbidden_words.md b/support/documentation/content/en/documentation/user/streamers/bot/forbidden_words.md index b40a875b..b8fd0ff1 100644 --- a/support/documentation/content/en/documentation/user/streamers/bot/forbidden_words.md +++ b/support/documentation/content/en/documentation/user/streamers/bot/forbidden_words.md @@ -7,9 +7,9 @@ chapter: false {{% livechat_label livechat_configuration_channel_forbidden_words_desc %}} -![Forbidden words configuration](/peertube-plugin-livechat/images/bot_forbidden_words.png?classes=shadow,border&height=400px) +![Screenshot of the channel options page, with several fields to configure the forbidden words.](/peertube-plugin-livechat/images/bot_forbidden_words.png?classes=shadow,border&height=400px "Forbidden words configuration") -![Deleted message](/peertube-plugin-livechat/images/bot_deleted_message.png?classes=shadow,border&height=100px) +![Screenshot of a chat message that was deleted, with the following reason: "No url allowed".](/peertube-plugin-livechat/images/bot_deleted_message.png?classes=shadow,border&height=100px "Deleted message") You can fill several "{{% livechat_label livechat_configuration_channel_forbidden_words_label %}}" fields. When a user sends a message that match the configured criteria, the message will automatically be deleted. @@ -35,6 +35,10 @@ See the [contribution guide](/peertube-plugin-livechat/contributing/) for more i These words are case insensitive. {{% /notice %}} +{{% notice tip %}} +You can combine a short [moderation delay](/peertube-plugin-livechat/documentation/user/streamers/moderation_delay) (1 second for example) with the [moderation bot](/peertube-plugin-livechat/documentation/user/streamers/bot) to delete messages containing swear words before any non-moderator user will see them. +{{% /notice %}} + {{% notice warning %}} This features is still experimental. There might be some issues with non-latin alphabets. diff --git a/support/documentation/content/en/documentation/user/streamers/bot/quotes.md b/support/documentation/content/en/documentation/user/streamers/bot/quotes.md index f41ee149..6c384b62 100644 --- a/support/documentation/content/en/documentation/user/streamers/bot/quotes.md +++ b/support/documentation/content/en/documentation/user/streamers/bot/quotes.md @@ -11,7 +11,7 @@ chapter: false If there is no user in the chatroom, the bot won't send any message. {{% /notice %}} -![Timers configuration](/peertube-plugin-livechat/images/bot_quotes.png?classes=shadow,border&height=200px) +![Screenshot of the channel options page, with some fields to configure a new timer.](/peertube-plugin-livechat/images/bot_quotes.png?classes=shadow,border&height=200px "Timers configuration") ## {{% livechat_label livechat_configuration_channel_quote_label %}} diff --git a/support/documentation/content/en/documentation/user/streamers/channel.md b/support/documentation/content/en/documentation/user/streamers/channel.md index a36079f7..3a4d5ed8 100644 --- a/support/documentation/content/en/documentation/user/streamers/channel.md +++ b/support/documentation/content/en/documentation/user/streamers/channel.md @@ -11,12 +11,12 @@ This feature comes with the livechat plugin version 8.0.0, and can be disabled b In the Peertube left menu, there is a "{{% livechat_label menu_configuration_label %}}" entry: -![Chatrooms menu](/peertube-plugin-livechat/images/chatrooms_menu.png?classes=shadow,border&height=400px) +![Screenshot of the chatrooms configuration page. The page list the user's channels.](/peertube-plugin-livechat/images/chatrooms_menu.png?classes=shadow,border&height=400px "Chatrooms menu") This "{{% livechat_label menu_configuration_label %}}" link takes you to a list of your channels. By clicking on a channel, you will then be able to setup some options for your channels: -![Channel configuration](/peertube-plugin-livechat/images/channel_configuration.png?classes=shadow,border&height=400px) +![Screenshot of the channel options. There is a form with multiple fields.](/peertube-plugin-livechat/images/channel_configuration.png?classes=shadow,border&height=400px "Channel configuration") Here you can configure: diff --git a/support/documentation/content/en/documentation/user/streamers/emojis.md b/support/documentation/content/en/documentation/user/streamers/emojis.md index ed9336a0..f0119060 100644 --- a/support/documentation/content/en/documentation/user/streamers/emojis.md +++ b/support/documentation/content/en/documentation/user/streamers/emojis.md @@ -15,11 +15,11 @@ Streamers can add custom emojis to their channels. On the [channel configuration page](/peertube-plugin-livechat/documentation/user/streamers/channel), open the "{{% livechat_label livechat_configuration_channel_emojis_title %}}" tab: -![Channel configuration / Channel emojis configuration](/peertube-plugin-livechat/images/channel_custom_emojis_configuration.png?classes=shadow,border&height=400px) +![Screenshot of the emoji configuration page. There is a form where you can add new emojis.](/peertube-plugin-livechat/images/channel_custom_emojis_configuration.png?classes=shadow,border&height=400px "Channel configuration / Channel emojis configuration") {{% livechat_label livechat_configuration_channel_emojis_desc %}} -![Channel configuration / Channel emojis](/peertube-plugin-livechat/images/channel_custom_emojis.png?classes=shadow,border&height=400px) +![Screenshot of a chat session, with messages containing custom emojis. The emoji picker is open, and shows custom emojis.](/peertube-plugin-livechat/images/channel_custom_emojis.png?classes=shadow,border&height=400px "Channel configuration / Channel emojis") {{% livechat_label livechat_emojis_shortname_desc %}} diff --git a/support/documentation/content/en/documentation/user/streamers/moderation.md b/support/documentation/content/en/documentation/user/streamers/moderation.md index eb3c0e9a..7881553a 100644 --- a/support/documentation/content/en/documentation/user/streamers/moderation.md +++ b/support/documentation/content/en/documentation/user/streamers/moderation.md @@ -23,7 +23,7 @@ Check [the chat bot documentation](/peertube-plugin-livechat/documentation/user/ You can access room settings and moderation tools using the [chat dropdown menu](/peertube-plugin-livechat/documentation/user/viewers) at the top of the chat. -![Chat menu](/peertube-plugin-livechat/images/top_menu.png?classes=shadow,border&height=200px) +![Screenshot of the dropdown menu at the top of the chat. Several entries are available.](/peertube-plugin-livechat/images/top_menu.png?classes=shadow,border&height=200px "Chat menu") {{% notice tip %}} The video owner will be owner of the chat room. @@ -50,11 +50,11 @@ You can prevent anonymous users to send messages. In such case, only registered To enable or disable this feature, use the [chat dropdown menu](/peertube-plugin-livechat/documentation/user/viewers), open the "configure" menu. In the form, you will find a "{{% livechat_label livechat_configuration_channel_mute_anonymous_label %}}" checkbox. -![Room configuration / Mute anonymous users](/peertube-plugin-livechat/images/configure_mute_anonymous.png?classes=shadow,border&height=400px) +![Screenshot of the room configuration form. There is a "{{% livechat_label livechat_configuration_channel_mute_anonymous_label %}}" checkbox.](/peertube-plugin-livechat/images/configure_mute_anonymous.png?classes=shadow,border&height=400px "Room configuration / Mute anonymous users") Anonymous users won't have the message field, and will see following prompt: "{{% livechat_label muted_anonymous_message %}}" -![Room configuration / Muted anonymous users](/peertube-plugin-livechat/images/anonymous_muted.png?classes=shadow,border&height=400px) +![Screenshot of a chat session. The current user has no message field. There is a message: "{{% livechat_label muted_anonymous_message %}}"](/peertube-plugin-livechat/images/anonymous_muted.png?classes=shadow,border&height=400px "Room configuration / Muted anonymous users") When this feature is enabled, anonymous users will be assigned the "visitor" role. You can change their role to "participant" if you want to allow some of them to talk. @@ -73,6 +73,47 @@ This section is still incomplete. You can promote users as moderators, if you need some help. +## {{% livechat_label livechat_configuration_channel_anonymize_moderation_label %}} + +{{% notice info %}} +This feature comes with the livechat plugin version 11.0.0. +{{% /notice %}} + +It is possible to anonymize moderation actions, to avoid disclosing who is banning/kicking/… occupants. + +To enable or disable this feature, use the [chat dropdown menu](/peertube-plugin-livechat/documentation/user/viewers), open the "configure" menu. +In the form, you will find a "{{% livechat_label livechat_configuration_channel_anonymize_moderation_label %}}" checkbox. + +You can choose to enable or disable this feature for new chatrooms on the [channel configuration page](/peertube-plugin-livechat/documentation/user/streamers/channel). + +## Participant message history search + +{{% notice info %}} +This feature comes with the livechat plugin version 11.0.0. +{{% /notice %}} + +As a room admin or owner, you can search all messages sent by a given participant. + +To do so, you have several ways: + +* using the "{{% livechat_label search_occupant_message %}}" action in the dropdown menu besides participants in the sidebar +* using the "{{% livechat_label search_occupant_message %}}" action in the dropdown menu besides chat messages + +![Screenshot of a chat session. The moderator has open the message menu, and there is a "{{% livechat_label search_occupant_message %}}" button.](/peertube-plugin-livechat/images/message_search.png?classes=shadow,border&height=200px "Message history search") + +{{% notice tip %}} +To have more space and better readability, open the chat in full-page mode. +{{% /notice %}} + +In the search results, there are several informations that are shown at the right of the participant nickname: + +* if the current nickname is different than the nickname when the participant has sent the message, the original nickname will be shown +* you will see the [JID (Jabber ID)](https://xmpp.org/extensions/xep-0029.html) of the participant +* you will also see the [occupant-id](https://xmpp.org/extensions/xep-0421.html) of the participant + +The search result will also include all messages related to participants who had the same nickname. +You can differenciate them by comparing [JID](https://xmpp.org/extensions/xep-0029.html) and [occupant-id](https://xmpp.org/extensions/xep-0421.html). + ## Delete room content You can delete old rooms: join the room, and use the menu on the top to destroy the room. diff --git a/support/documentation/content/en/documentation/user/streamers/moderation_delay.md b/support/documentation/content/en/documentation/user/streamers/moderation_delay.md index 3033b5cc..3c6718c9 100644 --- a/support/documentation/content/en/documentation/user/streamers/moderation_delay.md +++ b/support/documentation/content/en/documentation/user/streamers/moderation_delay.md @@ -22,7 +22,7 @@ Please note that messages sent by moderators will also be delayed, to avoid them On the [channel configuration page](/peertube-plugin-livechat/documentation/user/streamers/channel), you can set the "{{% livechat_label moderation_delay %}}" option: -![Channel configuration / Moderation delay](/peertube-plugin-livechat/images/moderation_delay_channel_option.png?classes=shadow,border&height=400px) +![Screenshot of the channel option form, with a field to configure the moderation delay.](/peertube-plugin-livechat/images/moderation_delay_channel_option.png?classes=shadow,border&height=400px "Channel configuration / Moderation delay") This value will apply as a default value for all your channel's chatrooms. @@ -39,8 +39,12 @@ Currently, this feature has one known bug: users that join the chat will get all However, messages sent after they joined will be delayed correctly. {{% /notice %}} +{{% notice tip %}} +You can combine a short [moderation delay](/peertube-plugin-livechat/documentation/user/streamers/moderation_delay) (1 second for example) with the [moderation bot](/peertube-plugin-livechat/documentation/user/streamers/bot) to delete messages containing swear words before any non-moderator user will see them. +{{% /notice %}} + ## In the chat As a moderator, you will see the remaining time (in seconds) before the message is broadcasted, just besides the message datetime. -![Moderation delay timer](/peertube-plugin-livechat/images/moderation_delay_timer.png?classes=shadow,border) +![Screenshot of a chat message. A timer is displayed next to the message datetime. The timer is in seconds.](/peertube-plugin-livechat/images/moderation_delay_timer.png?classes=shadow,border "Moderation delay timer") diff --git a/support/documentation/content/en/documentation/user/streamers/moderation_notes.md b/support/documentation/content/en/documentation/user/streamers/moderation_notes.md new file mode 100644 index 00000000..87cf394e --- /dev/null +++ b/support/documentation/content/en/documentation/user/streamers/moderation_notes.md @@ -0,0 +1,105 @@ +--- +title: "Moderation notes" +description: "Plugin peertube-plugin-livechat moderation notes" +weight: 355 +chapter: false +--- + +{{% notice info %}} +This feature comes with the livechat plugin version 11.0.0. +{{% /notice %}} + +## Introduction + +The livechat plugin includes a Moderator Notes Application: you can write some notes, that could be associated to chat participants. +Every room's admins have access to these notes, so they can edit them collaboratively. + +You can for example use this Application to: + +* share some notes between moderators +* take notes about participants that were kicked or caused troubles +* ... + +## Using the Moderator Notes Application + +### Opening the Moderator Notes Application + +To open the Moderator Notes Application, there is a "{{% livechat_label "moderator_notes" %}}" button in the top chat menu: + +![Screenshot of a Peertube video, with the chat on the right. The chat top menu is open, with a "{{% livechat_label "moderator_notes" %}}" button.](/peertube-plugin-livechat/images/moderation_notes_open_app_video.png?classes=shadow,border&height=200px "Opening the Moderator Notes Application") + +![Screenshot of a Peertube chat, fullscreen. The chat top menu open, with a "{{% livechat_label "moderator_notes" %}}" button.](/peertube-plugin-livechat/images/moderation_notes_open_app_fullpage.png?classes=shadow,border&height=200px "Opening the Moderator Notes Application") + +Clicking this button will toggle the Application display: + +![Screenshot of a Peertube video, with the chat on the right. The moderation notes application is open. There are several notes, some of them are associated to users.](/peertube-plugin-livechat/images/moderator_notes_app_video_1.png?classes=shadow,border&height=200px "Moderator Notes Application") + +![Screenshot of a Peertube chat, fullscreen. The moderation notes application is open. There are several notes, some of them are associated to users.](/peertube-plugin-livechat/images/moderator_notes_app_fullpage_1.png?classes=shadow,border&height=200px "Moderator Notes Application") + +{{% notice tip %}} +To have more space and better readability, open the chat in full-page mode. +{{% /notice %}} + +### Access rights + +Every room's admins have access to this Application (read and write access). + +When you promote someone as room admin or owner, they gets instant access to this Application. +When you remove admin or owner rights to someone, they instantly lose access to this Application. + +### Scope + +Notes are only available in the room in which you have created them. + +Chatrooms can be releated to video or channel. +If you want to keep notes from one video to another, please consider using rooms associated to channels. + +{{% notice warning %}} +Currently the video vs channel rooms is an instance-wide settings. +Only Peertube admins can change it, and it applies to all chatrooms. +In the future, this choice will be added in your channel's options. +{{% /notice %}} + +### Notes + +#### Create/Edit Notes + +You can use the plus button on the top to create a new note. +You can also edit existing notes using the edit button, or delate any note. + +{{% notice tip %}} +All modification are instantly visible in all your browser tabs, and for all room's admins. +{{% /notice %}} + +You can create a note associated to a participant in several ways: + +* using the "{{% livechat_label moderator_note_create_for_participant %}}" action in the dropdown menu besides participants in the sidebar +* using the "{{% livechat_label moderator_note_create_for_participant %}}" action in the dropdown menu besides chat messages + +When a note is associated to a participant, you will see their nickname and avatar on the top of the note. + +#### Notes filtering + +You can filter notes to find all notes related to a given participant in several ways: + +* click on the "{{% livechat_label moderator_note_search_for_participant %}}" button that is available on notes to find all notes related to the same participant +* click on the "{{% livechat_label moderator_note_search_for_participant %}}" button in the dropdown menu besides participants in the sidebar +* click on the "{{% livechat_label moderator_note_search_for_participant %}}" button in the dropdown menu besides chat messages + +You can remove the filter by clicking on the close button. + +![Screenshot of the note application, with a filter enabled for user "Mike". The only notes that are shown are the notes for the Mike user.](/peertube-plugin-livechat/images/moderation_notes_filters.png?classes=shadow,border&height=200px "Moderator Notes Application - filtering") + +When you filters notes on a participant, there are several informations that are shown at the right of the participant nickname: + +* if the current nickname is different than the nickname when you created the note, the original nickname will be shown +* you will see the [JID (Jabber ID)](https://xmpp.org/extensions/xep-0029.html) of the participant +* you will also see the [occupant-id](https://xmpp.org/extensions/xep-0421.html) of the participant + +The search result will also include all notes related to participants who had the same nickname. +So you can also take note for anonymous users (who don't have any consistent JID or occupant-id). +You can differenciate them by comparing JID and occupant-id. + +#### Sorting notes + +You can sort notes simply using drag & drop. diff --git a/support/documentation/content/en/documentation/user/streamers/polls.md b/support/documentation/content/en/documentation/user/streamers/polls.md index d737a90d..1f6f172f 100644 --- a/support/documentation/content/en/documentation/user/streamers/polls.md +++ b/support/documentation/content/en/documentation/user/streamers/polls.md @@ -13,7 +13,7 @@ This feature comes with the livechat plugin version 10.2.0. You can create a new poll by using the "{{% livechat_label new_poll %}}" action in the chat top menu: -![Poll form](/peertube-plugin-livechat/images/polls_form.png?classes=shadow,border&height=200px) +![Screenshot of a "{{% livechat_label new_poll %}}" form. The form contains several fields: question, duration, choices, …](/peertube-plugin-livechat/images/polls_form.png?classes=shadow,border&height=200px "Poll form") {{% notice warning %}} This poll feature should not be considered as a reliable voting system. @@ -54,7 +54,7 @@ When the polls starts, a first message will be sent in the chat, from the accoun A banner will also appear to show the poll, and will be updated regularly with the current votes. -![Poll start](/peertube-plugin-livechat/images/polls_start.png?classes=shadow,border&height=200px) +![Screenshot of a chat session. In the chat, there is a message with the poll question, and the different choices. There is also a banner on the top of the chat, where you can see the question, and the number of votes for each answers.](/peertube-plugin-livechat/images/polls_start.png?classes=shadow,border&height=200px "Poll start") Viewers can then vote by clicking on their choice, or by sending message like "!1" in the chat. @@ -63,7 +63,7 @@ Votes counts will be updated regularly in the banner. Viewers can change their vote at any time, just by making a new choice. Their precedent choice will be replaced by the new one. -![Poll votes](/peertube-plugin-livechat/images/polls_votes.png?classes=shadow,border&height=200px) +![Screenshot of a chat session, with an ongoing poll. The current user has just voted by sending "!1".](/peertube-plugin-livechat/images/polls_votes.png?classes=shadow,border&height=200px "Poll votes") {{% notice tip %}} Anonymous viewers can only vote once they have choosen their nickname. @@ -79,7 +79,7 @@ But they will see the message in the chat and will be able to vote by sending me When the poll ends, a new message will be sent in the chat, with the results. -![Poll end](/peertube-plugin-livechat/images/polls_end.png?classes=shadow,border&height=200px) +![Screenshot of a chat session, with poll that has ended. The banner no more accept new votes. There is a message in the chat with the poll results. For each choice, there is the number of votes, and the percentage of the total it represents.](/peertube-plugin-livechat/images/polls_end.png?classes=shadow,border&height=200px "Poll end") {{% notice info %}} The only way to get old polls results is to search for the poll end message in the chat. diff --git a/support/documentation/content/en/documentation/user/streamers/slow_mode.md b/support/documentation/content/en/documentation/user/streamers/slow_mode.md index 8dd43462..577cdc7d 100644 --- a/support/documentation/content/en/documentation/user/streamers/slow_mode.md +++ b/support/documentation/content/en/documentation/user/streamers/slow_mode.md @@ -26,7 +26,7 @@ This limitation does not apply to moderators. On the [channel configuration page](/peertube-plugin-livechat/documentation/user/streamers/channel), you can set the slow mode option: -![Channel configuration / Slow Mode](/peertube-plugin-livechat/images/slow_mode_channel_option.png?classes=shadow,border&height=400px) +![Screenshot of the channel options form, with a slow mode field.](/peertube-plugin-livechat/images/slow_mode_channel_option.png?classes=shadow,border&height=400px "Channel configuration / Slow Mode") This value will apply as a default value for all your channel's chatrooms. @@ -40,7 +40,7 @@ To modify the value for an already existing room, just open the room "configurat If the slow mode is enabled, users will be informed by a message. -![Slow mode infobox](/peertube-plugin-livechat/images/slow_mode.png?classes=shadow,border&height=400px) +![Screenshot of a chat session. There is a banner on the bottom of the chat, indicating that the slow mode is enabled, and that users can send a message every 2 seconds.](/peertube-plugin-livechat/images/slow_mode.png?classes=shadow,border&height=400px "Slow mode infobox") When they send a message, the input field will be disabled for X seconds (where X is the slow mode duration). diff --git a/support/documentation/content/en/documentation/user/streamers/tasks.md b/support/documentation/content/en/documentation/user/streamers/tasks.md index 0c09b75b..05f538fc 100644 --- a/support/documentation/content/en/documentation/user/streamers/tasks.md +++ b/support/documentation/content/en/documentation/user/streamers/tasks.md @@ -26,15 +26,15 @@ You can for example use the Task Application to: To open the Task Application, there is a "{{% livechat_label "tasks" %}}" button in the top chat menu: -![Opening the Task Application](/peertube-plugin-livechat/images/task_open_app_video.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video, with the chat on the right. The chat top menu is open, with a "{{% livechat_label tasks %}}" button.](/peertube-plugin-livechat/images/task_open_app_video.png?classes=shadow,border&height=200px "Opening the Task Application") -![Opening the Task Application](/peertube-plugin-livechat/images/task_open_app_fullpage.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube chat, fullscreen. The chat top menu open, with a "{{% livechat_label tasks %}}" button.](/peertube-plugin-livechat/images/task_open_app_fullpage.png?classes=shadow,border&height=200px "Opening the Task Application") Clicking this button will toggle the Task Application display: -![Task Application](/peertube-plugin-livechat/images/task_app_video_1.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video, with the chat on the right. The Task application is open. There is a task list, and a form to create a new task.](/peertube-plugin-livechat/images/task_app_video_1.png?classes=shadow,border&height=200px "Task Application") -![Task Application](/peertube-plugin-livechat/images/task_app_fullpage_1.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube chat, fullscreen. The Task application is open. There is a task list, and a form to create a new task.](/peertube-plugin-livechat/images/task_app_fullpage_1.png?classes=shadow,border&height=200px "Task Application") {{% notice tip %}} To have more space and better readability, open the chat in full-page mode. @@ -56,7 +56,7 @@ You can also edit existing task lists using the edit button, or delete any task Task lists are sorted alphabetically. -![Task lists](/peertube-plugin-livechat/images/task_app_task_lists.png?classes=shadow,border&height=200px) +![Screenshot of a chat session, with the Task application. There are several task lists.](/peertube-plugin-livechat/images/task_app_task_lists.png?classes=shadow,border&height=200px "Task lists") {{% notice tip %}} All modification are instantly visible in all your browser tabs, and for all room's admins. @@ -69,9 +69,9 @@ All modification are instantly visible in all your browser tabs, and for all roo You can create a task using the button on the right of task lists. This opens a form with two fields: a mandatory task name, and an optional description. -![Task form](/peertube-plugin-livechat/images/task_app_task_form.png?classes=shadow,border&height=200px) +![Screenshot of the task application. Under the first task list, there is a form to create a new task.](/peertube-plugin-livechat/images/task_app_task_form.png?classes=shadow,border&height=200px "Task form") -![Task created](/peertube-plugin-livechat/images/task_app_task_1.png?classes=shadow,border&height=200px) +![Screenshot of the task application. Under the first task list, a new task was created.](/peertube-plugin-livechat/images/task_app_task_1.png?classes=shadow,border&height=200px "Task created") #### Edit tasks @@ -79,15 +79,15 @@ Tasks can be edited by using the edit button on the right. Tasks can be marked complete (or uncomplete) by clicking directly on the checkbox in the list. -![Tasks](/peertube-plugin-livechat/images/task_app_task_2.png?classes=shadow,border&height=200px) +![Screenshot of the task application. Under task lists, there are several tasks. Some of them are checked, other not.](/peertube-plugin-livechat/images/task_app_task_2.png?classes=shadow,border&height=200px "Tasks") #### Sorting tasks / change task list You can sort tasks, or move tasks from one list to another, simply using drag & drop. -![Drag and drop to sort](/peertube-plugin-livechat/images/task_drag_drop.png?classes=shadow,border&height=200px) +![Screenshot of the task application. There is a task that is dragged over another.](/peertube-plugin-livechat/images/task_drag_drop.png?classes=shadow,border&height=200px "Drag and drop to sort") -![Drag and drop to move to another list](/peertube-plugin-livechat/images/task_drag_drop_task_list.png?classes=shadow,border&height=200px) +![Screenshot of the task application. There is a task that is dragged over another task list.](/peertube-plugin-livechat/images/task_drag_drop_task_list.png?classes=shadow,border&height=200px "Drag and drop to move to another list") #### Create a task from a chat message @@ -95,10 +95,10 @@ You can create a task from a message in a chat, using the "{{% livechat_label "t This will open a dialog box where you can choose which task list you want to add the task into. The task name will be the user nickname, and the task description the message content. -![Create task from message](/peertube-plugin-livechat/images/task_from_message_1.png?classes=shadow,border&height=200px) +![Screenshot of a chat session. The menu besides a message is open, with a button to create a new task.](/peertube-plugin-livechat/images/task_from_message_1.png?classes=shadow,border&height=200px "Create task from message") -![Choose the task list](/peertube-plugin-livechat/images/task_from_message_2.png?classes=shadow,border&height=200px) +![Screenshot of a dialog, where you can choose in which task list you want to add the new task.](/peertube-plugin-livechat/images/task_from_message_2.png?classes=shadow,border&height=200px "Choose the task list") -![Task created](/peertube-plugin-livechat/images/task_from_message_3.png?classes=shadow,border&height=200px) +![Screenshot of the task application. A new task was added in the "chat questions" task list, with the user's nickname, and the message as content.](/peertube-plugin-livechat/images/task_from_message_3.png?classes=shadow,border&height=200px "Task created") Using this feature, for example, you can ask your moderators to highlight all chat questions, so you can see them at a glance during your livestream, and check them as answered. diff --git a/support/documentation/content/en/documentation/user/streamers/terms.md b/support/documentation/content/en/documentation/user/streamers/terms.md index bf190c04..04ed3835 100644 --- a/support/documentation/content/en/documentation/user/streamers/terms.md +++ b/support/documentation/content/en/documentation/user/streamers/terms.md @@ -16,7 +16,7 @@ These terms will be shown to all users joining the chat. To configure the terms & conditions, go to the [channel configuration page](/peertube-plugin-livechat/documentation/user/streamers/channel): -![Channel configuration / Terms](/peertube-plugin-livechat/images/channel_terms_config.png?classes=shadow,border&height=400px) +![Screenshot of the channel options form, with a field to configure your terms and conditions.](/peertube-plugin-livechat/images/channel_terms_config.png?classes=shadow,border&height=400px "Channel configuration / Terms") URL in the message will be clickable. You can also do some styling: [Message Styling](https://xmpp.org/extensions/xep-0393.html). @@ -25,7 +25,7 @@ You can also do some styling: [Message Styling](https://xmpp.org/extensions/xep- When joining the chat, viewers will see the terms: -![Terms](/peertube-plugin-livechat/images/terms.png?classes=shadow,border&height=400px) +![Screenshot of a chat session. On the top of the chat, there are terms and conditions for both the server and the channel.](/peertube-plugin-livechat/images/terms.png?classes=shadow,border&height=400px "Terms") {{% notice info %}} Peertube instance's admin can also set global terms & conditions. diff --git a/support/documentation/content/en/documentation/user/viewers.md b/support/documentation/content/en/documentation/user/viewers.md index d9bbe70e..d7130b4a 100644 --- a/support/documentation/content/en/documentation/user/viewers.md +++ b/support/documentation/content/en/documentation/user/viewers.md @@ -9,7 +9,7 @@ chapter: false When you are watching a Peertube video that has the chat activated, you will see the chat next to the video: -![Chat screenshot](/peertube-plugin-livechat/images/chat.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video page, with a web chat on the right of the video.](/peertube-plugin-livechat/images/chat.png?classes=shadow,border&height=200px "Chat screenshot") There are two slightly different use cases, depending on wether or not you have an account on the Peertube instance. See bellow for more informations. @@ -23,11 +23,11 @@ This feature can be disabled by the instance's adminitrators. If you are not logged in on the Peertube instance where you are watching the video, you will automatically join the chat. You will be assigned a random nickname (something like "Anonymous 12345"). -![Chat with an anonymous user](/peertube-plugin-livechat/images/chat_with_anonymous.png?classes=shadow,border&height=200px) +![Screenshot of a chat. In the participant list, there is John Livingston, and an anonymous account using "Anonymous 212873" nickname.](/peertube-plugin-livechat/images/chat_with_anonymous.png?classes=shadow,border&height=200px "Chat with an anonymous user") Before being able to speak in the chat room, you have to enter a nickname in the field on the bottom of the window. -![Joining chat when not connected](/peertube-plugin-livechat/images/chat_anonymous.png?classes=shadow,border&height=200px) +![Screenshot of the chat. The current user is not logged in, and must choose a nickname before being able to write in the chat.](/peertube-plugin-livechat/images/chat_anonymous.png?classes=shadow,border&height=200px "Joining chat when not connected") #### Log in using an external authentication provider @@ -39,9 +39,9 @@ The Peertube instance can configure external authentication providers (Mastodon In such case, you will see a "{{% livechat_label login_using_external_account %}}" button, that will open a dialog modal. In this dialog modal, there will be some buttons to connect using a remote account. -![External login button](/peertube-plugin-livechat/images/external_login_button.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video page, with a chat on the right. At the bottom of the chat, there is a "{{% livechat_label login_using_external_account %}}" button.](/peertube-plugin-livechat/images/external_login_button.png?classes=shadow,border&height=200px "{{% livechat_label login_using_external_account %}} button") -![External login dialog - OpenID Connect](/peertube-plugin-livechat/images/external_login_dialog_oidc.png?classes=shadow,border&height=200px) +![Screenshot of a dialog with an "OpenID Connect" button.](/peertube-plugin-livechat/images/external_login_dialog_oidc.png?classes=shadow,border&height=200px "External login dialog - OpenID Connect") Once you signed in the remote account, and have granted access, your nickname and avatar (if available) will be automatically fetched. No other data will be stored. @@ -68,9 +68,9 @@ This button will open a dialog where you can enter your Peertube instance URL. Once you entered it, it will check if the livechat plugin is available on the remote instance, and if the video is available. If it is the case, you will be redirected to the video on the remote instance. -![External login button](/peertube-plugin-livechat/images/external_login_button.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video page, with a chat on the right. At the bottom of the chat, there is a "{{% livechat_label login_using_external_account %}}" button.](/peertube-plugin-livechat/images/external_login_button.png?classes=shadow,border&height=200px "{{% livechat_label login_using_external_account %}} button") -![External login dialog](/peertube-plugin-livechat/images/external_login_dialog.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label login_using_external_account %}}" dialog. There is a field where you can enter a Peertube url.](/peertube-plugin-livechat/images/external_login_dialog.png?classes=shadow,border&height=200px "External login dialog") ## Chatting @@ -91,7 +91,7 @@ You can also click on a nickname in the participants list to insert it in the me To see the list of participants, just open the right menu: -![Participants list](/peertube-plugin-livechat/images/open_participants_list.png?classes=shadow,border&height=200px) +![Screenshot of a chat session, with on the right the list of participants.](/peertube-plugin-livechat/images/open_participants_list.png?classes=shadow,border&height=200px "Participants list") You can see that some participants have special rights (moderator, owner, ...). @@ -101,14 +101,14 @@ There is a dropdown menu on the top of the chat, with some advanced features. This is especially useful for [moderation features](/peertube-plugin-livechat/documentation/user/streamers/moderation). Available features depends on your access level. -![Chat menu](/peertube-plugin-livechat/images/top_menu.png?classes=shadow,border&height=200px) +![Screenshot of the dropdown menu at the top of the chat. Several entries are available.](/peertube-plugin-livechat/images/top_menu.png?classes=shadow,border&height=200px "Chat menu") ## Opening full screen On top of the chat, there is a button to open the chat in fullscreen. This will open a new browser tab with the following content: -![Fullscreen chat screenshot](/peertube-plugin-livechat/images/fullscreen.png?classes=shadow,border&height=200px) +![Screenshot of a chat using the full web page.](/peertube-plugin-livechat/images/fullscreen.png?classes=shadow,border&height=200px "Fullscreen chat screenshot") It can be easier to chat using a full browser tab. diff --git a/support/documentation/content/en/documentation/user/xmpp_clients.md b/support/documentation/content/en/documentation/user/xmpp_clients.md index b04c6382..19d923e2 100644 --- a/support/documentation/content/en/documentation/user/xmpp_clients.md +++ b/support/documentation/content/en/documentation/user/xmpp_clients.md @@ -29,7 +29,7 @@ chats using any XMPP account. To get the address of the room you want to join, you can use the "share chat" button that is located above the chat: -![Share button](/peertube-plugin-livechat/images/share_button.png?classes=shadow,border&height=200px) +![Screenshot of the chat, with a share button on the top.](/peertube-plugin-livechat/images/share_button.png?classes=shadow,border&height=200px "Share button") {{% notice info %}} By default, the share button is only visible to the owner of the video, @@ -37,9 +37,9 @@ and the admins/moderators of the instance. However, admins can decide to display this button for everyone. {{% /notice %}} -Then, choose "Connect using XMPP": +Then, choose "{{% livechat_label connect_using_xmpp %}}": -![Share XMPP](/peertube-plugin-livechat/images/share_xmpp_dialog.png?classes=shadow,border&height=200px) +![Screenshot of the "{{% livechat_label share_chat_link %}}" dialog, on the "{{% livechat_label connect_using_xmpp %}}" tab.](/peertube-plugin-livechat/images/share_xmpp_dialog.png?classes=shadow,border&height=200px "{{% livechat_label connect_using_xmpp %}}") Then you just have to click on "open" or copy/paste the address of the chat room into your XMPP client (using the "join a room" feature). diff --git a/support/documentation/content/en/images/message_search.png b/support/documentation/content/en/images/message_search.png new file mode 100644 index 00000000..8177be9b Binary files /dev/null and b/support/documentation/content/en/images/message_search.png differ diff --git a/support/documentation/content/en/images/mod_firewall.png b/support/documentation/content/en/images/mod_firewall.png new file mode 100644 index 00000000..9c6e9952 Binary files /dev/null and b/support/documentation/content/en/images/mod_firewall.png differ diff --git a/support/documentation/content/en/images/moderation_notes_filters.png b/support/documentation/content/en/images/moderation_notes_filters.png new file mode 100644 index 00000000..1eed5de4 Binary files /dev/null and b/support/documentation/content/en/images/moderation_notes_filters.png differ diff --git a/support/documentation/content/en/images/moderation_notes_open_app_fullpage.png b/support/documentation/content/en/images/moderation_notes_open_app_fullpage.png new file mode 100644 index 00000000..4a461645 Binary files /dev/null and b/support/documentation/content/en/images/moderation_notes_open_app_fullpage.png differ diff --git a/support/documentation/content/en/images/moderation_notes_open_app_video.png b/support/documentation/content/en/images/moderation_notes_open_app_video.png new file mode 100644 index 00000000..18e2b819 Binary files /dev/null and b/support/documentation/content/en/images/moderation_notes_open_app_video.png differ diff --git a/support/documentation/content/en/images/moderator_notes_app_fullpage_1.png b/support/documentation/content/en/images/moderator_notes_app_fullpage_1.png new file mode 100644 index 00000000..3f691d80 Binary files /dev/null and b/support/documentation/content/en/images/moderator_notes_app_fullpage_1.png differ diff --git a/support/documentation/content/en/images/moderator_notes_app_video_1.png b/support/documentation/content/en/images/moderator_notes_app_video_1.png new file mode 100644 index 00000000..3ec9d5ad Binary files /dev/null and b/support/documentation/content/en/images/moderator_notes_app_video_1.png differ diff --git a/support/documentation/content/en/intro/_index.md b/support/documentation/content/en/intro/_index.md index 3fa3ca94..87500d8e 100644 --- a/support/documentation/content/en/intro/_index.md +++ b/support/documentation/content/en/intro/_index.md @@ -13,14 +13,14 @@ By default, once you have installed the plugin on your Peertube instance, a chat On the following screenshot, you can see a classic Peertube video page, with a chat room on the right (click on the picture to view it full screen): -![Chat screenshot](/peertube-plugin-livechat/images/chat.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube video page, with a web chat on the right of the video.](/peertube-plugin-livechat/images/chat.png?classes=shadow,border&height=200px "Chat screenshot") The chat room will be accessible for all viewers, even those who don't have an account on your instance. Those "anonymous" users just have to choose a nickname before they can begin talking in the chat. By default, the chat is displayed next to the video. But you can open it in another browser tab, using the button on top of it : -![Fullscreen chat screenshot](/peertube-plugin-livechat/images/fullscreen.png?classes=shadow,border&height=200px) +![Screenshot of a chat using the full web page.](/peertube-plugin-livechat/images/fullscreen.png?classes=shadow,border&height=200px "Fullscreen chat screenshot") {{% notice tip %}} You can test the livechat plugin with this [demo page](https://www.yiny.org/w/399a8d13-d4cf-4ef2-b843-98530a8ccbae). @@ -31,7 +31,7 @@ You can test the livechat plugin with this [demo page](https://www.yiny.org/w/39 As a Peertube administrator, you can setup this plugin on your instance simply by using the Peertube plugin marketplace included in the administration interface. Search for "livechat", then click "install": that's it! -![Livechat installation](/peertube-plugin-livechat/images/installation.png?classes=shadow,border&height=200px) +![Screenshot of Peertube plugins admin page. The search fields contains "livechat", and the search results show the livechat plugin.](/peertube-plugin-livechat/images/installation.png?classes=shadow,border&height=200px "Livechat installation") ## Livechat capabilities @@ -76,11 +76,11 @@ This is for example useful for replays. In the following screenshot, you can see a live replay, where the chat content is embeded on bottom of the video: -![Embeding the chat in a live stream](/peertube-plugin-livechat/images/embed_chat_in_livestream.png?classes=shadow,border&height=200px) +![Screenshot of a Peertube live, replay, with the chat included at the bottom of the video stream.](/peertube-plugin-livechat/images/embed_chat_in_livestream.png?classes=shadow,border&height=200px "Embeding the chat in a live stream") In the following screenshot, you can see an OBS setup, where the chat is included as a source in the current scene (background color can be changed, and can be transparent): -![Embeding the chat in OBS](/peertube-plugin-livechat/images/embed_chat_in_obs.png?classes=shadow,border&height=200px) +![Screenshot of the OBS software, where the chat was added as web browser source.](/peertube-plugin-livechat/images/embed_chat_in_obs.png?classes=shadow,border&height=200px "Embeding the chat in OBS") ## Other usages diff --git a/support/documentation/content/en/technical/moderation_notes.md b/support/documentation/content/en/technical/moderation_notes.md new file mode 100644 index 00000000..d775583d --- /dev/null +++ b/support/documentation/content/en/technical/moderation_notes.md @@ -0,0 +1,86 @@ +--- +title: "Moderator notes overview" +description: "Moderator Notes Application technical overview" +weight: 75 +chapter: false +livechatnotranslation: true +--- + +The livechat plugin includes a [Moderation Notes Application](/peertube-plugin-livechat/documentation/user/streamers/moderation_notes). +The present document describes how this is implemented. + +## Basics + +This features relies on [XEP-0060: Publish-Subscribe](https://xmpp.org/extensions/xep-0060.html). +This XEP provide a way to store and retrieve items, and to receive push notifications when an item is created/deleted/modified. + +There is a Prosody Module, [mod_pubsub_peertubelivechat](https://github.com/JohnXLivingston/peertube-plugin-livechat/tree/main/prosody-modules/mod_pubsub_peertubelivechat), to implement some specific use of the pubsub mechanism. + +This module is also used for [Tasks](/peertube-plugin-livechat/technical/tasks/). + +We use the [JID+NodeID addressing](https://xmpp.org/extensions/xep-0060.html#addressing-jidnode) to specify some nodes related to each MUC room. +The JID is the MUC room JID, the NodeID is functionnality we want to address. + +This modules implement the "livechat-notes" node, to handle moderator notes. + +The "livechat-notes" node contains one type of objects: Note (XML Namespaces: `urn:peertube-plugin-livechat:note`). + +On the front-end, we have the [livechat-converse-notes](https://github.com/JohnXLivingston/peertube-plugin-livechat/tree/main/conversejs/custom/plugins/notes) plugin for ConverseJS. + +## Workflow / Unsubscribing + +This is basically the same as for [Tasks](/peertube-plugin-livechat/technical/tasks/). + +## Items + +Here we describes the content of note items. + +* Item tag: `note` +* XML Namespace: `urn:peertube-plugin-livechat:note` +* item attributes: + * `order`: the order of the note in the note list +* item childs: + * `description`: the text content of the note + * `note-about`: an optional tag, if the note is associated to a participant + +The `note-about` tag, if present, has following structure: + +* Item tag: `note-about` +* XML Namespace: none +* item attributes: + * `jid`: the JID of the occupant + * `nick` the nick of the occupant, at time of note creation +* item childs: + * `occupant-id`: see [XEP-0421](https://xmpp.org/extensions/xep-0421.html). + +Example: + +```xml + + + + + + Some text. + + + + + + + + +``` diff --git a/support/documentation/content/en/technical/tasks.md b/support/documentation/content/en/technical/tasks.md index e4b38879..adef52b4 100644 --- a/support/documentation/content/en/technical/tasks.md +++ b/support/documentation/content/en/technical/tasks.md @@ -16,10 +16,12 @@ This XEP provide a way to store and retrieve items, and to receive push notifica There is a Prosody Module, [mod_pubsub_peertubelivechat](https://github.com/JohnXLivingston/peertube-plugin-livechat/tree/main/prosody-modules/mod_pubsub_peertubelivechat), to implement some specific use of the pubsub mechanism. +This module is also used for [Moderator Notes](/peertube-plugin-livechat/technical/moderation_notes/). + We use the [JID+NodeID addressing](https://xmpp.org/extensions/xep-0060.html#addressing-jidnode) to specify some nodes related to each MUC room. The JID is the MUC room JID, the NodeID is functionnality we want to address. -For now, this modules only implement one such node: "livechat-tasks", to handle tasks and task lists. -But the module code anticipates futur uses. + +This modules implement the "livechat-tasks" node, to handle tasks and task lists. The "livechat-tasks" node contains two type of objects: Task and TaskList (XML Namespaces: `urn:peertube-plugin-livechat:tasklist` and `urn:peertube-plugin-livechat:task`). Tasks have an attribute containing their task list id. diff --git a/support/documentation/static/css/livechatdoc.css b/support/documentation/layouts/partials/custom-header.html similarity index 56% rename from support/documentation/static/css/livechatdoc.css rename to support/documentation/layouts/partials/custom-header.html index 3850d345..37f5085d 100644 --- a/support/documentation/static/css/livechatdoc.css +++ b/support/documentation/layouts/partials/custom-header.html @@ -1,16 +1,13 @@ -/* - * SPDX-FileCopyrightText: 2024 John Livingston - * - * SPDX-License-Identifier: AGPL-3.0-only - */ + \ No newline at end of file diff --git a/support/documentation/layouts/partials/custom-header.html.license b/support/documentation/layouts/partials/custom-header.html.license new file mode 100644 index 00000000..b253ad42 --- /dev/null +++ b/support/documentation/layouts/partials/custom-header.html.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2024 John Livingston + +SPDX-License-Identifier: AGPL-3.0-only diff --git a/support/documentation/layouts/partials/logo.html b/support/documentation/layouts/partials/logo.html index a72f60c6..df524763 100644 --- a/support/documentation/layouts/partials/logo.html +++ b/support/documentation/layouts/partials/logo.html @@ -1,5 +1,6 @@ -