From f27e749fe1803742d3324dbdd50bca8d33b5551f Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 7 Jun 2025 13:13:41 +0100 Subject: [PATCH 01/22] auto restart after version change of hb or ui --- CHANGELOG.md | 16 ++++++- .../restart-homebridge.component.ts | 30 ++---------- .../manage-plugin.component.html | 12 +++-- .../manage-plugin/manage-plugin.component.ts | 47 +++++++++++-------- .../manage-version.component.html | 4 ++ .../manage-version.component.ts | 3 +- ui/src/i18n/bg.json | 1 + ui/src/i18n/ca.json | 1 + ui/src/i18n/cs.json | 1 + ui/src/i18n/de.json | 1 + ui/src/i18n/en.json | 1 + ui/src/i18n/es.json | 1 + ui/src/i18n/fi.json | 1 + ui/src/i18n/fr.json | 1 + ui/src/i18n/he.json | 1 + ui/src/i18n/hu.json | 1 + ui/src/i18n/id.json | 1 + ui/src/i18n/it.json | 1 + ui/src/i18n/ja.json | 1 + ui/src/i18n/ko.json | 1 + ui/src/i18n/mk.json | 1 + ui/src/i18n/nl.json | 1 + ui/src/i18n/no.json | 1 + ui/src/i18n/pl.json | 1 + ui/src/i18n/pt-BR.json | 1 + ui/src/i18n/pt.json | 1 + ui/src/i18n/ru.json | 1 + ui/src/i18n/sl.json | 1 + ui/src/i18n/sv.json | 1 + ui/src/i18n/th.json | 1 + ui/src/i18n/tr.json | 1 + ui/src/i18n/uk.json | 1 + ui/src/i18n/zh-CN.json | 1 + ui/src/i18n/zh-TW.json | 1 + 34 files changed, 87 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 412cb369e..8d089b106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/). -## v4.76.0 (2025-06-07) +## v4.77.0 (Unreleased) ### ⚠️ Upcoming Deprecations: @@ -12,7 +12,19 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - Drop support for Node.js `v18` and earlier, so please update to `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js) - Drop support for Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware - Drop support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) -- Note that these are not requirements for UI `v4.76.0` +- Note that these are not requirements for UI `v4.77.0` + +### UI Changes + +- auto restart after version change of hb or ui + +### Homebridge Dependencies + +- `@homebridge/hap-client` @ `v2.2.0` +- `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` +- `@homebridge/plugin-ui-utils` @ `v2.1.0` + +## v4.76.0 (2025-06-07) ### UI Changes diff --git a/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts b/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts index 01d99ff4e..3b03cc019 100644 --- a/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts +++ b/ui/src/app/core/components/restart-homebridge/restart-homebridge.component.ts @@ -1,10 +1,7 @@ -import { Component, inject, Input } from '@angular/core' +import { Component, inject } from '@angular/core' import { Router } from '@angular/router' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { TranslatePipe, TranslateService } from '@ngx-translate/core' -import { ToastrService } from 'ngx-toastr' - -import { ApiService } from '@/app/core/api.service' +import { TranslatePipe } from '@ngx-translate/core' @Component({ templateUrl: './restart-homebridge.component.html', @@ -13,31 +10,12 @@ import { ApiService } from '@/app/core/api.service' }) export class RestartHomebridgeComponent { $activeModal = inject(NgbActiveModal) - private $api = inject(ApiService) private $router = inject(Router) - private $toastr = inject(ToastrService) - private $translate = inject(TranslateService) - - @Input() fullRestart = false constructor() {} public onRestartHomebridgeClick() { - if (!this.fullRestart) { - this.$router.navigate(['/restart']) - this.$activeModal.close() - return - } - - this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ - next: () => { - this.$router.navigate(['/restart']) - this.$activeModal.close() - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) + this.$router.navigate(['/restart']) + this.$activeModal.close() } } diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html index ddfb95341..a571de6da 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html @@ -24,9 +24,9 @@
class="mb-3 text-center grey-text" [innerHTML]="'plugins.manage.github_support' | translate:{ iconStar, iconThumbsUp }" >

- @if (['homebridge', 'homebridge-config-ui-x'].includes(pluginName) || childBridges.length === 0) { + @if (childBridges.length === 0) {

{{ 'plugins.settings.restart_required' | translate }}

- } @if (!['homebridge', 'homebridge-config-ui-x'].includes(pluginName) && childBridges.length > 0) { + } @if (childBridges.length > 0) {

{{ 'restart.child_bridges' | translate }}

} } @if (changeLog) {
@@ -82,7 +82,11 @@
v{{ installedVersion }} → } @if (release.name) { {{ release.name }} } @if (!release.name) { v{{ latestVersion }} }
- } + @if (['homebridge', 'homebridge-config-ui-x'].includes(pluginName)) { + +

{{ 'plugins.manage.hb_restart' | translate }}

+
+ } }
@@ -124,7 +128,7 @@
diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts index fb4d32ef8..24649bd89 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts @@ -1,7 +1,7 @@ import { NgClass } from '@angular/common' import { Component, inject, Input, OnDestroy, OnInit } from '@angular/core' import { Router } from '@angular/router' -import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { NgbActiveModal, NgbAlert, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { saveAs } from 'file-saver' import { NgxMdModule } from 'ngx-md' @@ -27,6 +27,7 @@ import { HbV2ModalComponent } from '@/app/modules/status/widgets/update-info-wid PluginsMarkdownDirective, TranslatePipe, NgClass, + NgbAlert, ], }) @@ -197,6 +198,20 @@ export class ManagePluginComponent implements OnInit, OnDestroy { termRows: this.term.rows, }).subscribe({ next: async () => { + // Updating the UI needs a restart straight away + if (this.pluginName === 'homebridge-config-ui-x') { + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => { + window.location.href = '/restart' + }, + error: (error) => { + console.error(error) + window.location.href = '/restart' + }, + }) + return + } + try { await Promise.all([this.getChangeLog(), this.getChildBridges()]) } catch (error) { @@ -204,7 +219,7 @@ export class ManagePluginComponent implements OnInit, OnDestroy { } this.actionComplete = true this.justUpdatedPlugin = true - this.$router.navigate([this.pluginName === 'homebridge-config-ui-x' ? '/' : '/plugins']) + this.$router.navigate(['/plugins']) }, error: (error) => { this.actionFailed = true @@ -240,11 +255,15 @@ export class ManagePluginComponent implements OnInit, OnDestroy { }).subscribe({ next: () => { this.$activeModal.close() - const ref = this.$modal.open(RestartHomebridgeComponent, { - size: 'lg', - backdrop: 'static', + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => { + this.$router.navigate(['/restart']) + }, + error: (error) => { + console.error(error) + this.$router.navigate(['/restart']) + }, }) - ref.componentInstance.fullRestart = true }, error: (error) => { this.actionFailed = true @@ -291,20 +310,8 @@ export class ManagePluginComponent implements OnInit, OnDestroy { } public onRestartHomebridgeClick() { - if (this.pluginName === 'homebridge-config-ui-x') { - this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ - next: () => { - window.location.href = '/restart' - }, - error: (error) => { - console.error(error) - window.location.href = '/restart' - }, - }) - } else { - this.$router.navigate(['/restart']) - this.$activeModal.close() - } + this.$router.navigate(['/restart']) + this.$activeModal.close() } public async onRestartChildBridgeClick() { diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html index f0e669d01..dcead1d7d 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html @@ -25,6 +25,10 @@
{{ 'plugins.manage.select_version' | translate }}
} @else {
{{ 'plugins.manage.select_version' | translate }}
+ } @if (['homebridge', 'homebridge-config-ui-x'].includes(plugin.name)) { + +

{{ 'plugins.manage.hb_restart' | translate }}

+
}
autocomplete="username" autocapitalize="none" tabindex="1" - class="form-control py-2" - [placeholder]="'users.label_username' | translate" + class="form-control custom-input" [readonly]="loading" [ngClass]="{ 'is-valid': (createUserForm.controls.username.dirty) && createUserForm.controls.username.valid, 'is-invalid': (createUserForm.controls.username.dirty) && createUserForm.controls.username.invalid }" + [placeholder]="'users.label_username' | translate" + required /> -
- +
+
-
- +
+
-
+
+
- } @if (step === 'restore-backup') { -
- -

{{ 'form.button_restore' | translate }}

-

{{ 'backup.restore_help_one' | translate }}

+ } @else if (step === 'restore-backup') { +
+

{{ 'setup_wizard_restore' | translate }}

+
{{ 'backup.restore_help_one' | translate }}
{{ 'form.button_restore' | translate }} [disabled]="restoreUploading" (click)="onClickCancelRestore()" > - {{ 'form.button_cancel' | translate }} + {{ 'form.button_back' | translate }}
- } @if (step === 'restarting') { -
- -

{{ 'restart.title_restart' | translate }}

-

- -

+ } @else if (['restoring', 'restarting', 'restore-complete'].includes(step)) { +
+

+ @if (step === 'restoring') { {{ 'setup_wizard_restoring' | translate }} } @else if (step === 'restarting') { {{ + 'setup_wizard_starting' | translate }} } @else if (step === 'restore-complete') { {{ 'setup_wizard_complete' | + translate }} } +

+
+ @if (step === 'restore-complete') { + {{ 'form.label_continue' | translate }} + }
- } @if (step === 'setup-complete') { -
- -

{{ 'setup_wizard_message_complete_title' | translate }}

-

{{ 'setup_wizard_message_complete_message' | translate }}

- {{ 'setup.open_dashboard' | translate }} + } @else if (step === 'setup-complete') { +
+

{{ 'setup_wizard_complete_title' | translate }}

+
{{ 'setup_wizard_completed' | translate }}
+ {{ 'form.label_continue' | translate }}
}
diff --git a/ui/src/app/modules/setup-wizard/setup-wizard.component.scss b/ui/src/app/modules/setup-wizard/setup-wizard.component.scss index 8ac420536..d0d4a4ddf 100644 --- a/ui/src/app/modules/setup-wizard/setup-wizard.component.scss +++ b/ui/src/app/modules/setup-wizard/setup-wizard.component.scss @@ -1,77 +1,68 @@ +::ng-deep body { + overflow: scroll !important; +} + +::ng-deep body.dark-mode { + .setup-card { + background-color: #2b2b2b; + color: #ffffff; + } +} + .setup-container { - background-size: cover; z-index: -1; - padding-top: 1em; - padding-bottom: 1em; + padding-top: 2em; + padding-bottom: 2em; + min-height: 100%; + background-size: 300% 300%; +} + +.anim { + -webkit-animation: gradient 20s ease infinite; + -moz-animation: gradient 20s ease infinite; + -o-animation: gradient 20s ease infinite; + animation: gradient 20s ease infinite; +} - @media screen and (min-height: 500px) and (min-width: 600px) { - padding-top: 4em; +@keyframes gradient { + 0% { + background-position: 0 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0 50%; } } .setup-card { - max-width: 600px; - border-radius: 15px; - background-color: #ffffff; + max-width: 550px; + border-radius: 1rem; padding-right: 25px; padding-left: 25px; + background-color: rgba(255, 255, 255, 0.9); .form-control:focus { background-color: inherit !important; } - @media screen and (max-width: 600px) { + @media screen and (max-width: 575px) { margin-left: 1em; margin-right: 1em; } } -::ng-deep body.dark-mode { - .setup-card { - background-color: #2b2b2b; - color: #fff; - } -} - .homebridge-logo { - margin-right: 10px; - height: 200px; - - @media screen and (max-height: 500px) { - height: 100px; - } - - @media screen and (max-width: 600px) { - height: 100px; - } + margin-bottom: 10px; } -.homebridge-logo-small { - height: 50px; +.progress { + background-color: #dddddd; } -.button-loading { - position: relative; - color: rgba(0, 0, 0, 0); - - .button-loading-overlay { - display: block; - color: #fff; - } -} - -.button-loading-overlay { - display: none; - position: absolute; - top: 9px; - left: 0; - right: 0; -} - -small { - a { - &:hover { - text-decoration: underline; - } - } +#output { + height: 200px; + overflow-y: scroll; + white-space: pre-wrap; } diff --git a/ui/src/app/modules/setup-wizard/setup-wizard.component.ts b/ui/src/app/modules/setup-wizard/setup-wizard.component.ts index 43b50479e..8ad191c90 100644 --- a/ui/src/app/modules/setup-wizard/setup-wizard.component.ts +++ b/ui/src/app/modules/setup-wizard/setup-wizard.component.ts @@ -1,9 +1,7 @@ -import { NgClass } from '@angular/common' -import { Component, inject, OnDestroy, OnInit } from '@angular/core' +import { NgClass, NgOptimizedImage, NgStyle } from '@angular/common' +import { Component } from '@angular/core' import { AbstractControl, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms' import { Title } from '@angular/platform-browser' -import { RouterLink } from '@angular/router' -import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { firstValueFrom } from 'rxjs' @@ -11,49 +9,63 @@ import { firstValueFrom } from 'rxjs' import { ApiService } from '@/app/core/api.service' import { AuthService } from '@/app/core/auth/auth.service' import { SettingsService } from '@/app/core/settings.service' -import { RestoreComponent } from '@/app/modules/settings/backup/restore/restore.component' +import { IoNamespace, WsService } from '@/app/core/ws.service' import { environment } from '@/environments/environment' @Component({ templateUrl: './setup-wizard.component.html', styleUrls: ['./setup-wizard.component.scss'], - standalone: true, imports: [ - FormsModule, - ReactiveFormsModule, NgClass, - RouterLink, TranslatePipe, + NgOptimizedImage, + FormsModule, + ReactiveFormsModule, + NgStyle, ], }) -export class SetupWizardComponent implements OnInit, OnDestroy { - private $api = inject(ApiService) - private $auth = inject(AuthService) - private $modal = inject(NgbModal) - private $settings = inject(SettingsService) - private $title = inject(Title) - private $toastr = inject(ToastrService) - private $translate = inject(TranslateService) - - public previousTitle: string - public step: 'welcome' | 'create-account' | 'setup-complete' | 'restore-backup' | 'restarting' = 'welcome' - +export class SetupWizardComponent { + private io: IoNamespace + + public step: 'welcome' | 'create-account' | 'setup-complete' | 'restore-backup' | 'restoring' | 'restarting' | 'restore-complete' = 'welcome' + public backgroundStyle: string + public progress = 1 + public restoreInProgress = false + public restoreStarted = false + public restoreFailed = false + public loading = false + public selectedFile: File + public restoreUploading = false public createUserForm = new FormGroup({ username: new FormControl('', [Validators.required]), password: new FormControl('', [Validators.compose([Validators.required, Validators.minLength(4)])]), passwordConfirm: new FormControl('', [Validators.required]), }, this.matchPassword) - public loading = false - - public selectedFile: File - public restoreUploading = false + constructor( + private $api: ApiService, + private $auth: AuthService, + private $settings: SettingsService, + private $title: Title, + private $toastr: ToastrService, + private $translate: TranslateService, + private $ws: WsService, + ) {} + + async ngOnInit(): Promise { + this.$title.setTitle(this.$translate.instant('setup_wizard_page_title')) + await this.setBackground() + } - constructor() {} + async setBackground() { + if (!this.$settings.settingsLoaded) { + await firstValueFrom(this.$settings.onSettingsLoaded) + } - ngOnInit(): void { - this.previousTitle = this.$title.getTitle() - this.$title.setTitle('Setup Homebridge') + if (this.$settings.env.customWallpaperHash) { + const backgroundImageUrl = `${environment.api.base}/auth/wallpaper/${this.$settings.env.customWallpaperHash}` + this.backgroundStyle = `url('${backgroundImageUrl}') center/cover` + } } matchPassword(AC: AbstractControl) { @@ -66,113 +78,153 @@ export class SetupWizardComponent implements OnInit, OnDestroy { } } - ngOnDestroy() { - this.$title.setTitle(this.previousTitle) - } - onClickGettingStarted() { this.step = 'create-account' + this.progress = 50 } onClickRestoreBackup() { this.step = 'restore-backup' + this.progress = 20 } onClickCancelRestore() { this.selectedFile = null this.step = 'welcome' + this.progress = 1 } - createFirstUser() { + async createFirstUser() { this.loading = true + this.progress = 75 const payload = this.createUserForm.getRawValue() as Record payload.name = payload.username - this.$api.post('/setup-wizard/create-first-user', payload).subscribe({ - next: async () => { - this.$settings.env.setupWizardComplete = true - await this.$auth.login({ - username: payload.username, - password: payload.password, - }) - this.step = 'setup-complete' - }, - error: (error) => { - this.loading = false - console.error(error) - this.$toastr.error(error.error.message || this.$translate.instant('users.toast_failed_to_add_user'), this.$translate.instant('toast.title_error')) - }, - }) + try { + await firstValueFrom(this.$api.post('/setup-wizard/create-first-user', payload)) + this.$settings.env.setupWizardComplete = true + this.progress = 100 + this.loading = false + await this.$auth.login({ + username: payload.username, + password: payload.password, + }) + this.step = 'setup-complete' + } catch (error) { + this.loading = false + this.progress = 50 + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } } handleRestoreFileInput(files: FileList) { if (files.length) { this.selectedFile = files[0] + this.progress = 40 } else { delete this.selectedFile + this.progress = 20 } } - onRestoreBackupClick() { + async onRestoreBackupClick() { this.restoreUploading = true - this.uploadHomebridgeArchive() - } - - async uploadHomebridgeArchive() { + this.step = 'restoring' + this.progress = 60 try { - // Get and set a temporary access token + // get and set a temporary access token const authorization = await firstValueFrom(this.$api.get('/setup-wizard/get-setup-wizard-token')) window.localStorage.setItem(environment.jwt.tokenKey, authorization.access_token) this.$auth.token = authorization.access_token + this.progress = 65 - // Upload archive + // upload archive const formData: FormData = new FormData() formData.append('restoreArchive', this.selectedFile, this.selectedFile.name) await firstValueFrom(this.$api.post('/backup/restore', formData)) - - // Open restore modal - this.openRestoreModal() - this.restoreUploading = false + this.progress = 70 + + // start restore + this.io = this.$ws.connectToNamespace('backup') + const outputBox = document.getElementById('output') + this.io.socket.on('stdout', (data) => { + const lines = data.split('\n\r') + lines.forEach((line: string) => { + if (line && !/^[⠇⠏⠋⠙⠹⠸]+$/.test(line)) { // Ignore lines with invalid characters + const lineElement = document.createElement('div') + const regex = /\x1B\[(\d{1,2}(;\d{1,2})?)?[mGK]/g // eslint-disable-line no-control-regex + lineElement.innerHTML = line.replace(regex, '') + if (line.includes('[0;31m')) { + lineElement.classList.add('red-text') + } else if (line.includes('[0;32m')) { + lineElement.classList.add('green-text') + } else if (line.includes('[0;33m')) { + lineElement.classList.add('orange-text') + } else if (line.includes('[0;36m')) { + lineElement.classList.add('cyan-text') + } + outputBox.appendChild(lineElement) + outputBox.scrollTop = outputBox.scrollHeight + } + }) + }) + this.restoreStarted = true + this.restoreInProgress = true + this.progress = 75 + await firstValueFrom(this.io.request('do-restore')) + this.progress = 80 + this.restoreInProgress = false + await firstValueFrom(this.$api.put('/backup/restart', {})) + this.step = 'restarting' + this.progress = 85 + + // remove tokens + window.localStorage.removeItem(environment.jwt.tokenKey) + this.$auth.token = null + + // show final message in the terminal box + const restoreMessage = document.createElement('div') + restoreMessage.classList.add('orange-text') + restoreMessage.innerHTML = 'Starting Homebridge, please wait...' + outputBox.appendChild(restoreMessage) + outputBox.scrollTop = outputBox.scrollHeight + + // wait at least 15 seconds + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 88 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 91 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 94 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 97 + await new Promise(resolve => setTimeout(resolve, 3000)) + this.progress = 99 + + const checkHomebridgeInterval = setInterval(async () => { + try { + await firstValueFrom(this.$api.get('/auth/settings')) + clearInterval(checkHomebridgeInterval) + this.progress = 100 + this.restoreUploading = false + this.step = 'restore-complete' + } catch (error) { + // not up yet + } + }, 1000) } catch (error) { - this.restoreUploading = false console.error(error) - this.$toastr.error(error.error.message || this.$translate.instant('users.toast_failed_to_add_user'), this.$translate.instant('toast.title_error')) - } - } - - openRestoreModal() { - const ref = this.$modal.open(RestoreComponent, { - size: 'lg', - backdrop: 'static', - }) - ref.componentInstance.setupWizardRestore = true - - ref.result.then((success) => { - if (success === true) { - this.waitForHomebridgeToRestart() - } - }) - } - - async waitForHomebridgeToRestart() { - this.step = 'restarting' - - // Remove tokens - window.localStorage.removeItem(environment.jwt.tokenKey) - this.$auth.token = null - - // Wait at least 15 seconds - await new Promise(resolve => setTimeout(resolve, 15000)) - - const checkHomebridgeInterval = setInterval(async () => { - try { - await firstValueFrom(this.$api.get('/auth/settings')) - clearInterval(checkHomebridgeInterval) - location.reload() - } catch (e) { - // Not up yet + this.restoreUploading = false + this.restoreFailed = true + this.progress = 20 + this.step = 'restore-backup' + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } finally { + if (this.io) { + this.io.end() } - }, 1000) + } } } diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 24c99f7e2..81ea6e04e 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Сканирайте, за да добавите към Homekit", "status.cpu.load": "Използва", "status.cpu.temp": "Темп.", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 2d6127aad..8f234e503 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Arxiu de còpia de seguretat restaurat", "backup.backup_warning": "Els arxius de còpia de seguretat contenen informació confidencial i no s'han de compartir amb els altres.", - "backup.button_restore_backup": "Restaurar còpia de seguretat", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Carregant…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Començar", "setup.create_account": "Crear Compte", - "setup.create_account_reason": "S'ha de configurar l'autenticació de contrasenya a la interfície web d'administració de Homebridge. Encara que Homebridge només sigui accessible a la teva xarxa local, és important protegir-lo de l'accés sense restriccions.", - "setup.open_dashboard": "Obriu Tauler", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Benvingut/da a Homebridge", - "setup_wizard_message_complete_message": "El procediment de configuració s'ha completat i ja estàs preparat per començar a utilitzar Homebridge.", - "setup_wizard_message_complete_title": "Felicitats!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Felicitats!", + "setup_wizard_completed": "El procediment de configuració s'ha completat i ja estàs preparat per començar a utilitzar Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Escaneja per afegir a HomeKit", "status.cpu.load": "Càrrega", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 76704e648..e17ddcfe6 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Vygenerujte a stáhněte si aktuální soubor zálohy", "backup.backup_restored": "Záloha byla obnovena", "backup.backup_warning": "Zálohy obsahují citlivé informace a neměly by být sdíleny s ostatními.", - "backup.button_restore_backup": "Obnovit zálohu", "backup.files_auto": "Předešlé automatické zálohy", "backup.label_uploading": "Nahrávám…", "backup.load_error": "Nepodařilo se načíst zálohu konfigurace.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Spárované mosty nelze načíst.", "setup.button_get_started": "Začněme", "setup.create_account": "Vytvořit Účet", - "setup.create_account_reason": "Do webového rozhraní správce Homebridge musí být nakonfigurováno ověřování heslem. I když je Homebridge přístupný pouze ve vaší místní síti, je stále důležité jej chránit před neomezeným přístupem.", - "setup.open_dashboard": "Otevřít Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Vítejte v rozhraní Homebridge", - "setup_wizard_message_complete_message": "Postup nastavení je dokončen. Nyní můžete začít používat Homebridge.", - "setup_wizard_message_complete_title": "Gratulujeme!", - "setup_wizard_message_restore": "Obnovit ze zálohy", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Gratulujeme!", + "setup_wizard_completed": "Postup nastavení je dokončen. Nyní můžete začít používat Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Obnovit ze zálohy", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Naskenováním přidejte do HomeKitu", "status.cpu.load": "Zatížení", "status.cpu.temp": "Teplota", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index 1c3da8f4c..079698c3d 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Erstelle und lade ein aktuelles Backup.", "backup.backup_restored": "Backup-Archiv wiederhergestellt", "backup.backup_warning": "Backup-Archive enhalten sensitive Informationen und sollten nicht mit anderen geteilt werden.", - "backup.button_restore_backup": "Backup wiederherstellen", "backup.files_auto": "Vorherige automatische Backups", "backup.label_uploading": "Lädt hoch …", "backup.load_error": "Config-Backup konnte nicht geladen werden.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Gepairte Bridge konnten nicht geladen werden.", "setup.button_get_started": "Los geht's", "setup.create_account": "Konto erstellen", - "setup.create_account_reason": "Die Passwortauthentifizierung für die Homebridge-Administrationsweboberfläche muss konfiguriert werden. Auch wenn Homebridge nur in deinem lokalen Netzwerk zugänglich ist, ist es wichtig, es vor ungehindertem Zugriff zu schützen.", - "setup.open_dashboard": "Dashboard öffnen", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Wilkommen bei Homebridge", - "setup_wizard_message_complete_message": "Der Einrichtungsvorgang ist abgeschlossen und du kannst Homebridge jetzt verwenden.", - "setup_wizard_message_complete_title": "Herzlichen Glückwunsch!", - "setup_wizard_message_restore": "Wiederherstellen aus Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Herzlichen Glückwunsch!", + "setup_wizard_completed": "Der Einrichtungsvorgang ist abgeschlossen und du kannst Homebridge jetzt verwenden.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Wiederherstellen aus Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scannen, um es zu HomeKit hinzuzufügen", "status.cpu.load": "Auslastung", "status.cpu.temp": "Temperatur", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 7cf76e5ad..ce56d1811 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scan to add to HomeKit", "status.cpu.load": "Load", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 4a16a09b3..e4ec03fa9 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generar y descargar un archivo de copia de seguridad actualizado.", "backup.backup_restored": "Copia de seguridad restaurada", "backup.backup_warning": "Los archivos de copias de seguridad contienen información confidencial que no deberías compartir con otros.", - "backup.button_restore_backup": "Restaurar una copia de seguridad", "backup.files_auto": "Copias de Seguridad Automatizadas Anteriores", "backup.label_uploading": "Subiendo...", "backup.load_error": "Error al cargar la copia de seguridad de la configuración.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "No se pudieron cargar los puentes emparejados.", "setup.button_get_started": "Empezar", "setup.create_account": "Crear Cuenta", - "setup.create_account_reason": "Debe configurar una contraseña de autenticación para su interfaz web de Homebridge. Aunque Homebridge sea accesible solo desde la red local, es importante protegerlo de accesos no autorizados.", - "setup.open_dashboard": "Abrir Panel de Control", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Bienvenido a Homebridge", - "setup_wizard_message_complete_message": "El procedimiento de configuración se ha completado y ya está listo para empezar a utilizar Homebridge.", - "setup_wizard_message_complete_title": "¡Felicidades!", - "setup_wizard_message_restore": "Restaurar desde Copia de Seguridad", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "¡Felicidades!", + "setup_wizard_completed": "El procedimiento de configuración se ha completado y ya está listo para empezar a utilizar Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restaurar desde Copia de Seguridad", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Escanear para agregar a HomeKit.", "status.cpu.load": "Carga", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index fb3622b79..4db28522a 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Varmuuskopio palautettu", "backup.backup_warning": "Varmuuskopio sisältää arkaluontoista tietoa, älä jaa sitä muille.", - "backup.button_restore_backup": "Palauta varmuuskopio", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Ladataan", "backup.load_error": "Asetus varmuuskopion lataus epäonnistui.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paritettuja siltoja ei voitu otta käyttöön.", "setup.button_get_started": "Aloitetaan", "setup.create_account": "Luo käyttäjätunnus", - "setup.create_account_reason": "Kirjautuminen Homebridgen web hallintaan täytyy määritellä. Vaikka Homebridge on vain omassa lähiverkossasi on siltikin tärkeää estää rajoittamaton pääsy järjestelmään.", - "setup.open_dashboard": "Avaa käyttöpaneeli", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Tervetuloa Homebridge järjestelmään", - "setup_wizard_message_complete_message": "Asetukset ovat valmiit ja Homebridge on valmis käyttöön.", - "setup_wizard_message_complete_title": "Onnea!", - "setup_wizard_message_restore": "Palauta varmuuskopiosta", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Onnea!", + "setup_wizard_completed": "Asetukset ovat valmiit ja Homebridge on valmis käyttöön.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Palauta varmuuskopiosta", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skannaa lisätäksesi HomeKit järjestelmään", "status.cpu.load": "Käyttöaste", "status.cpu.temp": "Lämpötila", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 6c6eb0e95..7a6174fc5 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Archive de sauvegarde restaurée", "backup.backup_warning": "Les archives de sauvegarde contiennent des informations sensibles et ne doivent pas être partagées à des tiers.", - "backup.button_restore_backup": "Restaurer une Sauvegarde", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Envoi en cours…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Démarrer", "setup.create_account": "Créer un Compte", - "setup.create_account_reason": "Le Mot de passe d'authentification à l'interface d'administration d'Homebridge doit être configuré. Même si Homebridge n'est accessible que depuis votre réseau local, il est important de protégér son accès.", - "setup.open_dashboard": "Ouvrir le Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Bienvenue sur Homebridge", - "setup_wizard_message_complete_message": "La procédure d'installation est terminée et vous êtes maintenant prêt à utiliser Homebridge.", - "setup_wizard_message_complete_title": "Félicitations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Félicitations!", + "setup_wizard_completed": "La procédure d'installation est terminée et vous êtes maintenant prêt à utiliser Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scannez pour ajouter à HomeKit", "status.cpu.load": "Charge", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 9835be71a..c327c7d5f 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "גיבוי שחזור", "backup.backup_warning": "גיבוי מכיל מידע רגיש ולא אמור להיות משותף עם אנשים אחרים", - "backup.button_restore_backup": "שחזר מגיבוי", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "מעלה…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "סרוק כדי להוסיף ל-HomeKit", "status.cpu.load": "עומס", "status.cpu.temp": "טמפרטורה", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index 75023d5df..2d8ef7a1a 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Szkennelje be, hogy hozzáadja a HomeKit", "status.cpu.load": "Terhelés", "status.cpu.temp": "Hőmérséklet", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 81f6f3afb..25cc4c68e 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Buat dan unduh file cadangan terbaru.", "backup.backup_restored": "Arsip Cadangan Dipulihkan", "backup.backup_warning": "Arsip cadangan berisikan informasi sensitif dan sebaiknya tidak dibagikan kepada orang lain.", - "backup.button_restore_backup": "Pulihkan Cadangan", "backup.files_auto": "Pencadangan Otomatis Sebelumnya", "backup.label_uploading": "Mengunggah…", "backup.load_error": "Gagal memuat cadangan konfigurasi.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Jembatan berpasangan tidak dapat dimuat.", "setup.button_get_started": "Mulai", "setup.create_account": "Buat akun", - "setup.create_account_reason": "Otentikasi kata sandi untuk antarmuka web admin homebridge Anda harus dikonfigurasi. Bahkan jika Homebridge hanya dapat diakses di jaringan lokal Anda, masih penting untuk melindunginya dari akses tidak terbatas.", - "setup.open_dashboard": "Buka Dasbor", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Selamat datang di Homebridge", - "setup_wizard_message_complete_message": "Prosedur pengaturan selesai dan Anda sekarang siap untuk mulai menggunakan Homebridge.", - "setup_wizard_message_complete_title": "Selamat!", - "setup_wizard_message_restore": "Kembalikan dari cadangan", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Selamat!", + "setup_wizard_completed": "Prosedur pengaturan selesai dan Anda sekarang siap untuk mulai menggunakan Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Kembalikan dari cadangan", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Pindai untuk menambahkan ke HomeKit", "status.cpu.load": "Beban", "status.cpu.temp": "Suhu", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 3801e4cea..5065dc54d 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Archivio di backup ripristinato", "backup.backup_warning": "Gli archivi di backup contengono informazioni sensibili e non dovrebbero essere condivisi con altre persone.", - "backup.button_restore_backup": "Ripristina Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Caricamento in corso…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Inizia", "setup.create_account": "Crea un account utente", - "setup.create_account_reason": "È necessario configurare una password di autenticazione per l'interfaccia web di amministrazione di Homebridge. Anche se Homebridge è accessibile solo dalla rete locale, è comunque importante proteggerlo da accessi non autorizzati.", - "setup.open_dashboard": "Apri la dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Benvenuto in Homebridge", - "setup_wizard_message_complete_message": "La procedura di configurazione è stata completata ed è ora possibile iniziare a utilizzare Homebridge.", - "setup_wizard_message_complete_title": "Congratulazioni!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulazioni!", + "setup_wizard_completed": "La procedura di configurazione è stata completata ed è ora possibile iniziare a utilizzare Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scansiona per aggiungere a HomeKit", "status.cpu.load": "Carico della CPU", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 4129e882d..0f994944c 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "バックアップアーカイブを復元しました", "backup.backup_warning": "バックアップアーカイブには機密情報が含まれているため、第三者と共有することは推奨しません。", - "backup.button_restore_backup": "バックアップを復元", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "アップロード中…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "さぁ、始めよう!", "setup.create_account": "アカウントを作成", - "setup.create_account_reason": "Homebridgeの管理者用Webインターフェイスへのパスワード認証を設定する必要があります。Homebridgeがローカルネットワークでのみアクセス可能な場合でも、不正なアクセスから保護することが重要です。", - "setup.open_dashboard": "ダッシュボードを開く", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Homebridgeへようこそ!", - "setup_wizard_message_complete_message": "これでセットアップは完了です。Homebridgeを使用できます!", - "setup_wizard_message_complete_title": "おめでとう!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "おめでとう!", + "setup_wizard_completed": "これでセットアップは完了です。Homebridgeを使用できます!", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "スキャンして HomeKit に追加します", "status.cpu.load": "負荷", "status.cpu.temp": "温度", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 4649229e3..e8ec9d11f 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "백업 기록파일 복원됨", "backup.backup_warning": "백업 기록파일에는 민감한 정보가 포함되어 있기 때문에 다른사람과 공유해서는 안됩니다.", - "backup.button_restore_backup": "백업 복원", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "업로드 중…", "backup.load_error": "설정 백업을 로드하지 못했습니다.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "페어링된 Bridge를 불러오는 데 실패했습니다.", "setup.button_get_started": "설치 마법사 시작", "setup.create_account": "계정 생성", - "setup.create_account_reason": "Homebridge 관리자 페이지 비밀번호를 설정하세요. Homebridge를 로컬 네트워크에서만 사용하는 경우라도 해커의 표적이 될 수 있습니다. 꼭 비밀번호를 설정 후 사용하세요.", - "setup.open_dashboard": "대시보드 열기", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Homebridge에 오신 것을 환영합니다", - "setup_wizard_message_complete_message": "설치가 완료되었습니다. 이제 Homebridge를 사용할 준비가 되었습니다.", - "setup_wizard_message_complete_title": "축하합니다!", - "setup_wizard_message_restore": "백업에서 복원하기", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "축하합니다!", + "setup_wizard_completed": "설치가 완료되었습니다. 이제 Homebridge를 사용할 준비가 되었습니다.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "백업에서 복원하기", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "HomeKit에 추가하려면 스캔하세요", "status.cpu.load": "로드", "status.cpu.temp": "온도", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index b6abd9e21..c81c93bbf 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Поратена бекап архива", "backup.backup_warning": "Бекап архивите содржат сензитивни информации и не треба да се споделуваат.", - "backup.button_restore_backup": "Поврати бекап", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Се прикачува…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Скенирајте за да додадете во HomeKit", "status.cpu.load": "Товар", "status.cpu.temp": "Температура", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 339b00c78..0e06449b3 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archief Teruggeplaatst", "backup.backup_warning": "Backup archieven bevatten gevoelige informatie en moeten niet met anderen worden gedeelt.", - "backup.button_restore_backup": "Backup Terugplaatsen", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Aan het uploaden…", "backup.load_error": "Laden van configuratie backup is mislukt.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Gekoppelde bridges konden niet geladen worden.", "setup.button_get_started": "Beginnen", "setup.create_account": "Account aanmaken", - "setup.create_account_reason": "Wachtwood authenticatie voor de Homebridge admin web interface moet geconfigureerd worden. Ook als Homebridge alleen toegankelijk is in Uw lokale netwerk, is het nog steeds belangrijk om te beveiligen tegen onbeperkte toegang.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welkom bij Homebridge", - "setup_wizard_message_complete_message": "De setup procedure is compleet and U bent nu klaar om gebruik te maken van Homebridge.", - "setup_wizard_message_complete_title": "Felicitaties!", - "setup_wizard_message_restore": "Herstel vanuit Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Felicitaties!", + "setup_wizard_completed": "De setup procedure is compleet and U bent nu klaar om gebruik te maken van Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Herstel vanuit Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Scannen om toe te voegen aan HomeKit.", "status.cpu.load": "Belasting", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index fb89f2ed5..e4ab789ba 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Backup Archive Restored", "backup.backup_warning": "Backup archives contain sensitive information and should not be shared with others.", - "backup.button_restore_backup": "Restore Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Uploading…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skann for å legge til HomeKit", "status.cpu.load": "Bruk", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index 541d3f69e..fd40ddf54 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Przywracanie backupu zakończone sukcesem", "backup.backup_warning": "Backup zawiera ważne informacje i nie powinien być udostępniany nikomu.", - "backup.button_restore_backup": "Przywróć z backupu", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Przywracanie…", "backup.load_error": "Nie udało się załadować backupu.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Nie można było załadować sparowanych mostków.", "setup.button_get_started": "Rozpocznij", "setup.create_account": "Utwórz konto", - "setup.create_account_reason": "Hasło administratora do interfejsu Homebridge musi zostać utworzone. Obojętnie czy Homebridge jest dostępny tylko w sieci lokalnej, wymagane jest zabezpieczenie go przed nieautoryzowanym dostępem.", - "setup.open_dashboard": "Otwórz dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Witaj w Homebridge", - "setup_wizard_message_complete_message": "Procedura została zakończona, możesz zacząć używać Homebridge.", - "setup_wizard_message_complete_title": "Gratulacje!", - "setup_wizard_message_restore": "Przywróć z backupu", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Gratulacje!", + "setup_wizard_completed": "Procedura została zakończona, możesz zacząć używać Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Przywróć z backupu", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Zeskanuj aby dodać do HomeKit", "status.cpu.load": "Obciążenie", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index a8c2bf364..4e35f1a73 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Arquivo de Backup Restaurado", "backup.backup_warning": "Os arquivos de backup possuem informações privadas e não devem de ser compartilhados com outras pessoas.", - "backup.button_restore_backup": "Restaurar Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Enviando…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Digitalize para adicionar ao HomeKit", "status.cpu.load": "Utilização", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index d02c1b9f8..887c6e296 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Ficheiro de Backup Restaurado", "backup.backup_warning": "Os ficheiro de backup contem informação privada e não devem de ser partilhados com outros.", - "backup.button_restore_backup": "Restaurar Backup", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "A Enviar…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Começar", "setup.create_account": "Criar Conta", - "setup.create_account_reason": "A autenticação por palavra-passe deverá de ser configurada para a página de administração do Homebridge. Mesmo que o Homebridge seja acessível apenas na rede local, é importante protege-lo de acessos não autorizados.", - "setup.open_dashboard": "Abrir Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Bem-vindo ao Homebridge", - "setup_wizard_message_complete_message": "O processo de configuração está concluído e está pronto para utilizar o Homebridge.", - "setup_wizard_message_complete_title": "Parabéns!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Parabéns!", + "setup_wizard_completed": "O processo de configuração está concluído e está pronto para utilizar o Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Digitalize para adicionar ao HomeKit", "status.cpu.load": "Utilização", "status.cpu.temp": "Temperatura", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index aae991770..3976f41f4 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Создать и скачать актуальный файл резервной копии.", "backup.backup_restored": "Архив резервной копии восстановлен", "backup.backup_warning": "Архивы резервных копий содержат конфиденциальную информацию и не должны передаваться третьим лицам.", - "backup.button_restore_backup": "Восстановить из резервной копии", "backup.files_auto": "Предыдущие автоматические копии", "backup.label_uploading": "Загрузка…", "backup.load_error": "Ошибка загрузки конфигурации резервной копии.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Не удалось загрузить привязанные мосты.", "setup.button_get_started": "Начать работу", "setup.create_account": "Создать аккаунт", - "setup.create_account_reason": "Необходимо настроить аутентификацию по паролю для вашего веб-интерфейса администратора Homebridge. Даже если Homebridge доступен только в вашей локальной сети, важно защитить его от неограниченного доступа.", - "setup.open_dashboard": "Открыть панель управления", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Добро пожаловать в Homebridge", - "setup_wizard_message_complete_message": "Процедура настройки завершена, вы готовы начать использовать Homebridge.", - "setup_wizard_message_complete_title": "Поздравляем!", - "setup_wizard_message_restore": "Восстановить из резервной копии", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Поздравляем!", + "setup_wizard_completed": "Процедура настройки завершена, вы готовы начать использовать Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Восстановить из резервной копии", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Сканируйте для добавления в HomeKit", "status.cpu.load": "Нагрузка", "status.cpu.temp": "Температура", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index 2e5c98437..da7199576 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Varnostno kopiranje arhiva obnovljeno", "backup.backup_warning": "Rezervni arhivi vsebujejo občutljive podatke in jih ne smete deliti z drugimi.", - "backup.button_restore_backup": "Obnovi varnostno kopijo", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Nalaganje …", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skenirajte za dodajanje v HomeKit", "status.cpu.load": "Naloži", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index e2171398c..312cbac57 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Säkerhetskopia återställd", "backup.backup_warning": "Säkerhetskopian innehåller känslig information och bör inte delas med andra.", - "backup.button_restore_backup": "Återställ säkerhetskopia", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Laddar upp…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Kom igång", "setup.create_account": "Skapa konto", - "setup.create_account_reason": "Lösenordsautentisering till ditt Homebridge admin-webbgränssnitt måste konfigureras. Även om Homebridge endast kan nås i ditt lokala nätverk är det fortfarande viktigt att skydda den från obehörig åtkomst.", - "setup.open_dashboard": "Öppna instrumentpanel", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Välkommen till Homebridge", - "setup_wizard_message_complete_message": "Installationsprocessen är klar och du kan nu börja använda Homebridge.", - "setup_wizard_message_complete_title": "Grattis!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Grattis!", + "setup_wizard_completed": "Installationsprocessen är klar och du kan nu börja använda Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Skanna för att lägga till i HomeKit", "status.cpu.load": "Används", "status.cpu.temp": "Temp", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 14e1cbc49..acb9984a2 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "สร้างและดาวน์โหลดไฟล์สำรองข้อมูลที่อัปเดต", "backup.backup_restored": "กู้คืนที่เก็บข้อมูลสำรองแล้ว", "backup.backup_warning": "คลังข้อมูลสำรองมีข้อมูลที่ละเอียดอ่อนและไม่ควรแชร์กับผู้อื่น", - "backup.button_restore_backup": "คืนค่าการสำรองข้อมูล", "backup.files_auto": "การสำรองข้อมูลอัตโนมัติก่อนหน้านี้", "backup.label_uploading": "กำลังอัปโหลด…", "backup.load_error": "ไม่สามารถโหลดการสำรองข้อมูลการกำหนดค่าได้", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "บริดจ์จับคู่ไม่สามารถโหลดได้", "setup.button_get_started": "เริ่ม", "setup.create_account": "สร้างบัญชี", - "setup.create_account_reason": "การตรวจสอบรหัสผ่านสำหรับเว็บอินเตอร์เฟสผู้ดูแลระบบ Homebridge ของคุณต้องได้รับการกำหนดค่า แม้ว่า Homebridge จะสามารถเข้าถึงได้เฉพาะในเครือข่ายท้องถิ่นของคุณ ก็ยังเป็นสิ่งสำคัญที่จะต้องปกป้องจากการเข้าถึงที่ไม่จำกัด", - "setup.open_dashboard": "เปิดแดชบอร์ด", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "ยินดีต้อนรับสู่ Homebridge", - "setup_wizard_message_complete_message": "ขั้นตอนการตั้งค่าเสร็จสมบูรณ์ และตอนนี้คุณก็พร้อมที่จะเริ่มใช้ Homebridge แล้ว", - "setup_wizard_message_complete_title": "ยินดีด้วย!", - "setup_wizard_message_restore": "กู้คืนจากการสำรองข้อมูล", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "ยินดีด้วย!", + "setup_wizard_completed": "ขั้นตอนการตั้งค่าเสร็จสมบูรณ์ และตอนนี้คุณก็พร้อมที่จะเริ่มใช้ Homebridge แล้ว", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "กู้คืนจากการสำรองข้อมูล", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "สแกนเพื่อเพิ่มลงใน HomeKit", "status.cpu.load": "โหลด", "status.cpu.temp": "อุณหภูมิ", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index b6f098262..2988dbbc8 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "Yedekleme Arşivi Geri Yüklendi", "backup.backup_warning": "Yedekleme arşivleri hassas bilgiler barındırırlar ve başka kişilerle paylaşılmamalıdırlar.", - "backup.button_restore_backup": "Yedeği Geri Yükle", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "Yükleniyor…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "HomeKit'e eklemek için tarayın", "status.cpu.load": "Yükle", "status.cpu.temp": "Sıcaklık", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 728160d55..43693817e 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Створіть і завантажте оновлений файл резервної копії.", "backup.backup_restored": "Резервна копія відновлена", "backup.backup_warning": "Архіви резервних копій містять конфіденціїну інформацію і не повинні передаватись іншим особам.", - "backup.button_restore_backup": "Відновити", "backup.files_auto": "Попередні автоматичні резервні копії", "backup.label_uploading": "Завантаження…", "backup.load_error": "Не вдалося завантажити резервну копію конфігурації.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Не вдалося завантажити парні мости.", "setup.button_get_started": "Розпочати", "setup.create_account": "Створити обліковий запис", - "setup.create_account_reason": "Необхідно налаштувати автентифікацію за допомогою пароля для веб-інтерфейсу адміністратора Homebridge. Навіть якщо Homebridge доступний тільки у Вашій локальній мережі, важливо захистити його від необмеженого доступу.", - "setup.open_dashboard": "Відкрийте панель приладів", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Ласкаво просимо до Homebridge", - "setup_wizard_message_complete_message": "Процедуру встановлення завершено, тепер Ви можете почати використовувати Homebridge.", - "setup_wizard_message_complete_title": "Вітаємо!", - "setup_wizard_message_restore": "Відновити з резервної копії", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Вітаємо!", + "setup_wizard_completed": "Процедуру встановлення завершено, тепер Ви можете почати використовувати Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Відновити з резервної копії", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "Скануйте, щоб додати до HomeKit", "status.cpu.load": "Завантаження", "status.cpu.temp": "Температура", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index c2d14ce60..00b3af8b3 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "已从备份档案中恢复", "backup.backup_warning": "备份文档包含了敏感信息,请勿与他人共享。", - "backup.button_restore_backup": "恢复备份", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "上传中…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "扫描添加到HomeKit", "status.cpu.load": "负载", "status.cpu.temp": "温度", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index a80b77ed4..a6c0f76ad 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -87,7 +87,6 @@ "backup.backup_now_desc": "Generate and download an up-to-date backup file.", "backup.backup_restored": "備份檔案已回復", "backup.backup_warning": "備份檔案包含敏感資訊、請不要隨意與其他人共享。", - "backup.button_restore_backup": "回復備份", "backup.files_auto": "Previous Automated Backups", "backup.label_uploading": "上傳中…", "backup.load_error": "Failed to load config backup.", @@ -446,12 +445,16 @@ "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", "setup.create_account": "Create Account", - "setup.create_account_reason": "Password authentication to your Homebridge admin web interface must be configured. Even if Homebridge is accessible only in your local network, it is still important to protect it from unrestricted access.", - "setup.open_dashboard": "Open Dashboard", + "setup.intro": "If you are setting up for the first time, or if you just need to reset the password for your existing Homebridge setup, then choose Get Started.", "setup.welcome_to_homebridge": "Welcome to Homebridge", - "setup_wizard_message_complete_message": "The setup procedure is complete and you are now ready to start using Homebridge.", - "setup_wizard_message_complete_title": "Congratulations!", - "setup_wizard_message_restore": "Restore From Backup", + "setup_wizard_complete": "Restore Complete!", + "setup_wizard_complete_title": "Congratulations!", + "setup_wizard_completed": "The setup procedure is complete and you are now ready to start using Homebridge.", + "setup_wizard_create_info": "Once Homebridge is set up, you can set up 2FA on your account, or disable the need for authentication altogether.", + "setup_wizard_page_title": "Setup Homebridge", + "setup_wizard_restore": "Restore From Backup", + "setup_wizard_restoring": "Restoring Backup...", + "setup_wizard_starting": "Starting Homebridge...", "status.code_scan": "掃描加入到HomeKit", "status.cpu.load": "負載", "status.cpu.temp": "溫度", diff --git a/ui/src/scss/base/layout.scss b/ui/src/scss/base/layout.scss index f2f802fea..3eb5ee25a 100644 --- a/ui/src/scss/base/layout.scss +++ b/ui/src/scss/base/layout.scss @@ -38,6 +38,11 @@ a:focus { color: #4caf50 !important; } +.cyan-text, +.cyan-text a { + color: #00bcd4 !important; +} + .red-text, .red-text a { color: #ff0000 !important; diff --git a/ui/src/scss/themes/themes-dark.scss b/ui/src/scss/themes/themes-dark.scss index c65ad1bc8..195accfb4 100644 --- a/ui/src/scss/themes/themes-dark.scss +++ b/ui/src/scss/themes/themes-dark.scss @@ -174,7 +174,8 @@ background-color: $secondaryBackground !important; } - .login-card { + .login-card, + .setup-card { background-color: rgba($secondaryBackground, 0.97) !important; } diff --git a/ui/src/scss/themes/themes-light.scss b/ui/src/scss/themes/themes-light.scss index 948e5e254..3274f9e8e 100644 --- a/ui/src/scss/themes/themes-light.scss +++ b/ui/src/scss/themes/themes-light.scss @@ -74,6 +74,11 @@ color: $primary; } + .grey-text, + .grey-text a { + color: #666666 !important; + } + .btn-primary, .btn-default { background-color: $primary !important; From 6a4ebb2d726ce0b3c6e6e7018046f5a9abd94d6f Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 7 Jun 2025 23:24:03 +0100 Subject: [PATCH 03/22] on uninstall plugin, only offer to remove config when exists --- .../uninstall-plugin/uninstall-plugin.component.html | 4 ++-- .../uninstall-plugin/uninstall-plugin.component.ts | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html index 1ef7a5b02..d9b80955c 100644 --- a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html +++ b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html @@ -20,7 +20,7 @@
- @if (pluginAlias && pluginType) { + @if (isConfigured) {

  • {{ 'plugins.uninstall_warn_1' | translate }}
  • {{ 'plugins.uninstall_warn_2' | translate }}
  • - } @if (!pluginAlias || !pluginType) { + } @if (isConfigured && (!pluginAlias || !pluginType)) { {{ 'plugins.uninstall_remove_config_required' | translate }} diff --git a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts index 0ad8c0a54..9245f3203 100644 --- a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts +++ b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.ts @@ -35,6 +35,7 @@ export class UninstallPluginComponent implements OnInit { public removeConfig = true public removeChildBridges = true public hasChildBridges = false + public isConfigured = false public pluginType: 'platform' | 'accessory' public pluginAlias: string @@ -50,6 +51,11 @@ export class UninstallPluginComponent implements OnInit { const schema = await this.getAlias() this.pluginType = schema.pluginType this.pluginAlias = schema.pluginAlias + + const existingConfig = await firstValueFrom(this.$api.get(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`)) + if (existingConfig.length) { + this.isConfigured = true + } } finally { this.loading = false } @@ -59,7 +65,7 @@ export class UninstallPluginComponent implements OnInit { this.uninstalling = true // Remove the plugin config if exists and specified by the user - if (this.removeConfig && this.pluginType && this.pluginAlias) { + if (this.removeConfig && this.isConfigured) { try { await this.removePluginConfig() } catch (error) { From 843067ba8c6948ecc830bf4ff1c297857d41f00f Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 14 Jun 2025 16:59:55 +0100 Subject: [PATCH 04/22] style HBv2/UIv5 icons on status page based on readiness --- CHANGELOG.md | 1 + .../update-info-widget.component.html | 10 ++++++-- .../update-info-widget.component.ts | 23 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ee2e2374..0341241ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - auto restart after version change of hb or ui - redesigned setup wizard page +- style HBv2/UIv5 icons on status page based on readiness ### Homebridge Dependencies diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html index 284491836..9e70bd154 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html @@ -36,7 +36,10 @@ placement="top" aria-label="Homebridge v2 Readiness" > - + } } @if (!homebridgePkg.installedVersion) { Homebridge @@ -89,7 +92,10 @@ placement="top" aria-label="Homebridge UI v5 Readiness" > - + } } @if (!homebridgeUiPkg.installedVersion) { Homebridge UI diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts index ce188f8b4..114d8799d 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts @@ -6,6 +6,7 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { firstValueFrom } from 'rxjs' +import { ApiService } from '@/app/core/api.service' import { InformationComponent } from '@/app/core/components/information/information.component' import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' import { SettingsService } from '@/app/core/settings.service' @@ -25,6 +26,7 @@ import { UiV5ModalComponent } from '@/app/modules/status/widgets/update-info-wid ], }) export class UpdateInfoWidgetComponent implements OnInit { + private $api = inject(ApiService) private $modal = inject(NgbModal) $plugin = inject(ManagePluginsService) $settings = inject(SettingsService) @@ -45,6 +47,9 @@ export class UpdateInfoWidgetComponent implements OnInit { public isRunningHbV2 = false public isRunningUiV5 = false + public isHbV2Ready = false + public isUiV5Ready = false + private io: IoNamespace constructor() {} @@ -69,6 +74,20 @@ export class UpdateInfoWidgetComponent implements OnInit { this.getNodeInfo(), ]) } + + this.isHbV2Ready = this.homebridgeUiPkg.readyForV5.node + + if (!this.isRunningHbV2) { + const installedPlugins = await firstValueFrom(this.$api.get('/plugins')) + const allHb2Ready = installedPlugins + .filter((x: any) => x.name !== 'homebridge-config-ui-x') + .every((x: any) => { + const hbEngines = x.engines?.homebridge?.split('||').map((s: string) => s.trim()) || [] + return hbEngines.some((v: string) => v.startsWith('^2') || v.startsWith('>=2')) + }) + + this.isHbV2Ready = this.isHbV2Ready && allHb2Ready + } } async checkHomebridgeVersion() { @@ -101,6 +120,10 @@ export class UpdateInfoWidgetComponent implements OnInit { this.homebridgeUiPkg = response this.$settings.env.homebridgeUiVersion = response.installedVersion this.isRunningUiV5 = response.installedVersion.startsWith('5.') + this.isUiV5Ready = this.homebridgeUiPkg.readyForV5.node + && this.homebridgeUiPkg.readyForV5.service + && this.homebridgeUiPkg.readyForV5.pnpm + && this.homebridgeUiPkg.readyForV5.arch } catch (error) { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) From e06895c10d74f8bf8e1600dc17b0ed1c3fc7113c Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 14 Jun 2025 21:34:44 +0100 Subject: [PATCH 05/22] security system modal only show valid modes --- CHANGELOG.md | 1 + .../securitysystem/securitysystem.manage.component.html | 5 +++++ .../types/securitysystem/securitysystem.manage.component.ts | 2 ++ 3 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0341241ff..bbbfbed2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - auto restart after version change of hb or ui - redesigned setup wizard page - style HBv2/UIv5 icons on status page based on readiness +- security system modal only show valid modes ### Homebridge Dependencies diff --git a/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.html b/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.html index 74d676c0d..fcd5a0819 100644 --- a/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.html +++ b/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.html @@ -15,6 +15,7 @@
    diff --git a/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.ts b/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.ts index d9c7da953..95dee00d6 100644 --- a/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.ts +++ b/ui/src/app/core/accessories/types/securitysystem/securitysystem.manage.component.ts @@ -17,11 +17,13 @@ export class SecuritysystemManageComponent implements OnInit { @Input() public service: ServiceTypeX public targetMode: any + public targetModeValidValues: number[] = [] constructor() {} ngOnInit() { this.targetMode = this.service.values.SecuritySystemTargetState + this.targetModeValidValues = this.service.getCharacteristic('SecuritySystemTargetState').validValues as number[] } setTargetMode(value: number) { From 270f840f596e8f0db49f0f6adae7d5cecd477445 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:06:09 +0100 Subject: [PATCH 06/22] refactor settings page with immediate saving --- CHANGELOG.md | 1 + config.schema.json | 100 +- src/core/config/config.service.ts | 37 +- src/main.ts | 1 + .../config-editor/config-editor.controller.ts | 9 + .../config-editor/config-editor.service.ts | 106 +- src/modules/plugins/plugins.service.ts | 8 +- src/modules/server/server.controller.ts | 16 + src/modules/server/server.service.ts | 75 + .../accessory-info.component.html | 2 + .../reset-accessories.component.html | 2 +- ui/src/app/core/settings.service.ts | 52 +- .../container-restart.component.html | 7 +- .../modules/restart/restart.component.html | 7 +- .../accessory-control-lists.component.html | 117 ++ .../accessory-control-lists.component.ts | 91 ++ .../settings/backup/backup.component.ts | 34 +- .../remove-bridge-accessories.component.html | 2 +- ...remove-individual-accessories.component.ts | 2 +- .../reset-individual-bridges.component.html | 6 +- .../select-network-interfaces.component.html | 28 +- .../select-network-interfaces.component.ts | 47 +- .../modules/settings/settings.component.html | 1082 ++++++++++---- .../modules/settings/settings.component.ts | 1331 ++++++++++++++--- .../app/modules/settings/settings.module.ts | 2 + .../settings/wallpaper/wallpaper.component.ts | 1 + .../widget-visibility.component.html | 25 +- .../widget-visibility.component.ts | 4 +- .../hb-v2-modal/hb-v2-modal.component.ts | 1 + .../modules/support/support.component.html | 7 +- .../layout/sidebar/sidebar.component.ts | 1 - ui/src/i18n/bg.json | 45 +- ui/src/i18n/ca.json | 45 +- ui/src/i18n/cs.json | 45 +- ui/src/i18n/de.json | 45 +- ui/src/i18n/en.json | 45 +- ui/src/i18n/es.json | 45 +- ui/src/i18n/fi.json | 45 +- ui/src/i18n/fr.json | 45 +- ui/src/i18n/he.json | 45 +- ui/src/i18n/hu.json | 45 +- ui/src/i18n/id.json | 45 +- ui/src/i18n/it.json | 45 +- ui/src/i18n/ja.json | 45 +- ui/src/i18n/ko.json | 45 +- ui/src/i18n/mk.json | 45 +- ui/src/i18n/nl.json | 45 +- ui/src/i18n/no.json | 45 +- ui/src/i18n/pl.json | 45 +- ui/src/i18n/pt-BR.json | 45 +- ui/src/i18n/pt.json | 45 +- ui/src/i18n/ru.json | 45 +- ui/src/i18n/sl.json | 45 +- ui/src/i18n/sv.json | 45 +- ui/src/i18n/th.json | 45 +- ui/src/i18n/tr.json | 45 +- ui/src/i18n/uk.json | 45 +- ui/src/i18n/zh-CN.json | 45 +- ui/src/i18n/zh-TW.json | 45 +- 59 files changed, 3681 insertions(+), 783 deletions(-) create mode 100644 ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.html create mode 100644 ui/src/app/modules/settings/accessory-control-lists/accessory-control-lists.component.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index bbbfbed2f..12adc8faa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - redesigned setup wizard page - style HBv2/UIv5 icons on status page based on readiness - security system modal only show valid modes +- refactor settings page with immediate saving ### Homebridge Dependencies diff --git a/config.schema.json b/config.schema.json index 8bf39d392..809c11f6e 100644 --- a/config.schema.json +++ b/config.schema.json @@ -26,7 +26,7 @@ "title": "Homebridge UI Authentication", "type": "string", "default": "form", - "description": "The type of authentication to use for the Homebridge UI.", + "description": "Whether to enable authentication for the Homebridge UI with a username and password.", "oneOf": [ { "title": "Require Authentication", @@ -437,7 +437,7 @@ "placeholder": 28800, "minimum": 600, "maximum": 86400000, - "description": "The number of seconds before a user session will timeout. Defaults to 8 hours.", + "description": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "condition": { "functionBody": "return model.auth === 'form'" } @@ -637,26 +637,12 @@ } }, "layout": [ - { - "ref": "login", - "type": "fieldset", - "expandable": true, - "title": "Login Settings", - "items": [ - "auth", - { - "key": "sessionTimeout", - "type": "number" - } - ] - }, { "ref": "log", "type": "fieldset", "expandable": true, "title": "Log Settings", "items": [ - "debug", "log.method", "log.path", "log.service", @@ -665,57 +651,6 @@ "log.systemd" ] }, - { - "ref": "logRetention", - "type": "fieldset", - "expandable": true, - "title": "Log Retention Settings", - "items": [ - "log.maxSize", - "log.truncateSize" - ] - }, - { - "ref": "accessoryControl", - "type": "fieldset", - "expandable": true, - "title": "Accessory Control", - "items": [ - "accessoryControl.debug", - { - "key": "accessoryControl.instanceBlacklist", - "type": "array", - "items": { - "key": "accessoryControl.instanceBlacklist[]", - "type": "string", - "pattern": "^([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$", - "title": "Instance Username" - } - } - ] - }, - { - "ref": "hostname", - "type": "fieldset", - "expandable": true, - "title": "Hostname Settings", - "items": [ - "proxyHost", - "host" - ] - }, - { - "ref": "ssl", - "type": "fieldset", - "expandable": true, - "title": "SSL Settings", - "items": [ - "ssl.key", - "ssl.cert", - "ssl.pfx", - "ssl.passphrase" - ] - }, { "ref": "homebridge", "type": "fieldset", @@ -723,38 +658,17 @@ "title": "Homebridge Settings", "items": [ "sudo", - "restart", - "homebridgePackagePath" + "restart" ] }, { - "ref": "operatingSystem", + "ref": "container", "type": "fieldset", "expandable": true, - "title": "Operating System Specific Settings", + "title": "Container Settings", "items": [ - "disableServerMetricsMonitoring", - { - "ref": "linux", - "type": "fieldset", - "expandable": true, - "title": "Linux Settings", - "items": [ - "linux.shutdown", - "linux.restart", - "temp" - ] - }, - { - "ref": "container", - "type": "fieldset", - "expandable": true, - "title": "Container Settings", - "items": [ - "standalone", - "noFork" - ] - } + "standalone", + "noFork" ] } ] diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index e157cbf37..eeaa89b0f 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -90,10 +90,12 @@ export class ConfigService { restart?: string lang?: string log?: { - method: 'file' | 'custom' | 'systemd' | 'native' + method?: 'file' | 'custom' | 'systemd' | 'native' command?: string path?: string service?: string + maxSize?: number + truncateSize?: number } ssl?: { key?: string @@ -209,6 +211,7 @@ export class ConfigService { setupWizardComplete: this.setupWizardComplete, }, formAuth: Boolean(this.ui.auth !== 'none'), + sessionTimeout: this.ui.sessionTimeout || 28800, lightingMode: this.ui.lightingMode || 'auto', serverTimestamp: new Date().toISOString(), theme: this.ui.theme || 'deep-purple', @@ -234,9 +237,33 @@ export class ConfigService { runningInFreeBSD: this.runningInFreeBSD, runningOnRaspberryPi: this.runningOnRaspberryPi, temperatureUnits: this.ui.tempUnits || 'c', + temp: this.ui.temp, usePnpm: this.usePnpm, + log: { + maxSize: this.ui.log?.maxSize, + truncateSize: this.ui.log?.truncateSize, + }, + ssl: { + key: this.ui.ssl?.key, + cert: this.ui.ssl?.cert, + pfx: this.ui.ssl?.pfx, + passphrase: this.ui.ssl?.passphrase, + }, + accessoryControl: { + debug: this.ui.accessoryControl?.debug, + instanceBlacklist: this.ui.accessoryControl?.instanceBlacklist || [], + }, + linux: { + shutdown: this.ui.linux?.shutdown, + restart: this.ui.linux?.restart, + }, }, + menuMode: this.ui.menuMode || 'default', wallpaper: this.ui.wallpaper, + host: this.ui.host, + proxyHost: this.ui.proxyHost, + homebridgePackagePath: this.ui.homebridgePackagePath, + disableServerMetricsMonitoring: this.ui.disableServerMetricsMonitoring, } } @@ -287,6 +314,8 @@ export class ConfigService { this.ui.log = { method: 'file', path: '/homebridge/logs/homebridge.log', + maxSize: this.ui.log?.maxSize, + truncateSize: this.ui.log?.truncateSize, } // These options can be overridden using the config.json file @@ -308,6 +337,8 @@ export class ConfigService { this.ui.log = { method: 'native', path: resolve(this.storagePath, 'homebridge.log'), + maxSize: this.ui.log?.maxSize, + truncateSize: this.ui.log?.truncateSize, } } @@ -403,6 +434,10 @@ export interface HomebridgeConfig { mdns?: { interface?: string | string[] } + ports?: { + start?: number + end?: number + } platforms: Record[] accessories: Record[] plugins?: string[] diff --git a/src/main.ts b/src/main.ts index 8e15adae7..dc23d8b21 100644 --- a/src/main.ts +++ b/src/main.ts @@ -105,6 +105,7 @@ async function bootstrap(): Promise { // Setup cors app.enableCors({ origin: ['http://localhost:8080', 'http://localhost:4200'], + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], }) // Validation pipes diff --git a/src/modules/config-editor/config-editor.controller.ts b/src/modules/config-editor/config-editor.controller.ts index 81e628515..2c29ff8dd 100644 --- a/src/modules/config-editor/config-editor.controller.ts +++ b/src/modules/config-editor/config-editor.controller.ts @@ -93,6 +93,15 @@ export class ConfigEditorController { return this.configEditorService.setPropertyForUi(key, value) } + @UseGuards(AdminGuard) + @Put('/ui/accessory-control/instance-blacklist') + @ApiOperation({ summary: 'Update the accessory control instance blacklist.' }) + @ApiBody({ description: 'Array of bridge instances for which control by the UI should be blocked.', type: 'json', isArray: true }) + @Put() + setAccessoryControlInstanceBlacklist(@Body() { body }) { + return this.configEditorService.setAccessoryControlInstanceBlacklist(body) + } + @UseGuards(AdminGuard) @ApiOperation({ summary: 'List the available Homebridge `config.json` backups.' }) @Get('/backups') diff --git a/src/modules/config-editor/config-editor.service.ts b/src/modules/config-editor/config-editor.service.ts index cbde02451..06b445eac 100644 --- a/src/modules/config-editor/config-editor.service.ts +++ b/src/modules/config-editor/config-editor.service.ts @@ -290,12 +290,11 @@ export class ConfigEditorService { // Save the config file await this.updateConfigFile(config) - return pluginConfig } /** - * Set a specific property for the homebridge-config-ui-x plugin + * Set a specific property for the Homebridge UI */ public async setPropertyForUi(property: string, value: any) { // Cannot update the platform property @@ -303,19 +302,59 @@ export class ConfigEditorService { throw new BadRequestException('Cannot update the platform property.') } - // 1. get the current config for homebridge-config-ui-x + // 1. Get the current config for the Homebridge UI const config = await this.getConfigFile() - - // 2. update the property const pluginConfig = config.platforms.find(x => x.platform === 'config') - // If value is empty, null or undefined, delete the property - if (value === '' || value === null || value === undefined) { - delete pluginConfig[property] + + // 2. Calculate the property, split dots into nested properties + const forbiddenKeys = ['__proto__', 'constructor', 'prototype'] + if (property.includes('.')) { + const properties = property.split('.') + let current = pluginConfig + + for (let i = 0; i < properties.length - 1; i++) { + if (!forbiddenKeys.includes(properties[i])) { + if (!current[properties[i]]) { + current[properties[i]] = {} + } + current = current[properties[i]] + } + } + + const finalProperty = properties[properties.length - 1] + if (!forbiddenKeys.includes(finalProperty)) { + // 3. Update the final property + current[finalProperty] = value + } } else { - pluginConfig[property] = value + if (!forbiddenKeys.includes(property)) { + pluginConfig[property] = value + } + } + + // 4. Clean and save the UI config block + config.platforms[config.platforms.findIndex(x => x.platform === 'config')] = this.cleanUpUiConfig(pluginConfig) + await this.updateConfigFile(config) + } + + /** + * Set the accessory control blacklist (this request is not partial) + */ + public async setAccessoryControlInstanceBlacklist(value: string[]) { + // 1. Get the current config for the Homebridge UI + const config = await this.getConfigFile() + const pluginConfig = config.platforms.find(x => x.platform === 'config') + + // 2. Ensure the accessoryControl block exists and set the instanceBlacklist + if (!pluginConfig.accessoryControl) { + pluginConfig.accessoryControl = {} } + pluginConfig.accessoryControl.instanceBlacklist = (value || []) + .filter(x => typeof x === 'string' && x.trim() !== '' && /^(?:[A-F0-9]{2}:){5}[A-F0-9]{2}$/i.test(x.trim())) + .map(x => x.trim().toUpperCase()) - // 3. save the config file + // 3. Clean and save the UI config block + config.platforms[config.platforms.findIndex(x => x.platform === 'config')] = this.cleanUpUiConfig(pluginConfig) await this.updateConfigFile(config) } @@ -336,7 +375,6 @@ export class ConfigEditorService { config.disabledPlugins.push(pluginName) await this.updateConfigFile(config) - return config.disabledPlugins } @@ -409,9 +447,9 @@ export class ConfigEditorService { const backups = await this.listConfigBackups() // Delete each backup file - backups.forEach(async (backupFile) => { + for (const backupFile of backups) { await unlink(resolve(this.configService.configBackupPath, backupFile.file)) - }) + } } /** @@ -505,4 +543,46 @@ export class ConfigEditorService { } return username } + + /** + * Removes empty objects and arrays from the provided object + * Warning: This will modify the object in place, so use with caution. + * @param {Record} obj + * @return {void} + * @private + */ + private removeEmpty(obj: Record): void { + Object.keys(obj).forEach((key) => { + const value = obj[key] + if (value === '' || value === null || value === undefined || value === false || (Array.isArray(value) && value.length === 0)) { + // Checking for 'false' is okay for the UI as all defaults are false + delete obj[key] + } else if (typeof value === 'object') { + this.removeEmpty(value) + if (Object.keys(value).length === 0) { + delete obj[key] + } + } + }) + } + + /** + * Cleans up the UI config object + * - Removes empty objects and arrays + * - Ensures the name key is first and platform key is last + * @param {Record} uiConfig + * @return {Record} + * @private + */ + private cleanUpUiConfig(uiConfig: Record): Record { + // Name key first, platform key last + const { name, platform, ...rest } = uiConfig + const cleanedUiConfig = { + name, + ...rest, + platform, + } + this.removeEmpty(cleanedUiConfig) + return cleanedUiConfig + } } diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index c30970385..dfbd2157c 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -951,13 +951,7 @@ export class PluginsService { // Filter some options from the UI config when using service mode if (this.configService.serviceMode) { - configSchema.layout = configSchema.layout.filter((x: any) => { - return x.ref !== 'log' - }) - - configSchema.layout = configSchema.layout.filter((x: any) => { - return !(x === 'sudo' || x.key === 'restart') - }) + configSchema.layout = configSchema.layout.filter((section: any) => section.ref !== 'log' && section.ref !== 'homebridge') } } diff --git a/src/modules/server/server.controller.ts b/src/modules/server/server.controller.ts index 395f6796e..52105428a 100644 --- a/src/modules/server/server.controller.ts +++ b/src/modules/server/server.controller.ts @@ -252,6 +252,22 @@ export class ServerController { return this.serverService.setHomebridgePort(body.port) } + @UseGuards(AdminGuard) + @ApiOperation({ summary: 'Get the usable ports as set in the config file.' }) + @Get('/ports') + getUsablePort() { + return this.serverService.getUsablePorts() + } + + @UseGuards(AdminGuard) + @Put('/ports') + @ApiOperation({ summary: 'Update the usable ports for Homebridge.' }) + @ApiBody({ description: 'Object with start and end properties.', type: 'json', isArray: false }) + @Put() + setUsablePorts(@Body() body) { + return this.serverService.setUsablePorts(body) + } + @UseGuards(AdminGuard) @Post('/wallpaper') @ApiOperation({ summary: 'Upload an image file to the Homebridge storage directory and reference this as a wallpaper in the config file.' }) diff --git a/src/modules/server/server.service.ts b/src/modules/server/server.service.ts index b5e035e89..49356c60c 100644 --- a/src/modules/server/server.service.ts +++ b/src/modules/server/server.service.ts @@ -653,6 +653,28 @@ export class ServerService { return { port: config.bridge.port } } + /** + * Get the usable ports + */ + public async getUsablePorts(): Promise<{ start?: number, end?: number }> { + const config = await this.configEditorService.getConfigFile() + + // config.ports may not exist + let start: number + let end: number + + if (config.ports && typeof config.ports === 'object') { + if (config.ports.start) { + start = config.ports.start + } + if (config.ports.end) { + end = config.ports.end + } + } + + return { start, end } + } + /** * Set the Homebridge name */ @@ -685,6 +707,59 @@ export class ServerService { await this.configEditorService.updateConfigFile(config) } + /** + * Set the usable ports in the config file + */ + public async setUsablePorts(value: { start?: number, end?: number }) { + // 1. Get the current config + let config = await this.configEditorService.getConfigFile() + + // 2. Validate the input + if (value.start === null) { + delete value.start + } + if (value.end === null) { + delete value.end + } + + if ('start' in value && (typeof value.start !== 'number' || value.start < 1025 || value.start > 65533)) { + throw new BadRequestException('Port start must be a number between 1025 and 65533.') + } + if ('end' in value && (typeof value.end !== 'number' || value.end < 1025 || value.end > 65533)) { + throw new BadRequestException('Port end must be a number between 1025 and 65533.') + } + if ('start' in value && 'end' in value && value.start >= value.end) { + throw new BadRequestException('Ports start must be less than end.') + } + if ('start' in value && !('end' in value) && config.ports?.end && value.start >= config.ports.end) { + throw new BadRequestException('Ports start must be less than end.') + } + if ('end' in value && !('start' in value) && config.ports?.start && config.ports.start >= value.end) { + throw new BadRequestException('Ports start must be less than end.') + } + + // 3. Update the config with the new ports + // Remove ports if neither start nor end is specified + if (!value.start && !value.end) { + delete config.ports + } else { + config.ports = {} + if (value.start) { + config.ports.start = value.start + } + if (value.end) { + config.ports.end = value.end + } + } + + // 4. Bring the ports object to the front of the config, after the bridge object + const { bridge, ports, ...rest } = config + config = ports ? { bridge, ports, ...rest } : { bridge, ...rest } + + // 5. Save the config file + await this.configEditorService.updateConfigFile(config) + } + /** * Check if the system Node.js version has changed */ diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html index 315d3fbb3..22fb38203 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html @@ -37,6 +37,7 @@ + @if (!service.hidden) {
  • {{ 'accessories.show_on_dashboard' | translate }}
    @@ -50,6 +51,7 @@
  • + }
    @@ -48,7 +50,7 @@

    {{ 'menu.settings.title' | translate }}

    - +
    {{ 'menu.settings.title' | translate }} class="mt-3 hover-pointer" >
    - + {{ 'settings.general.title_general' | translate }}
    @if (showFields.general) { }
    - +
    class="mt-3 hover-pointer" >
    - + {{ 'settings.general.title_display' | translate }}
    @@ -97,12 +97,8 @@
    - + @if ($settings.env.serviceMode || $settings.env.runningInDocker) { -
    -
    -
    - - {{ 'settings.title_startup_options' | translate }} -
    -
    - @if (showFields.startup) { -
    +} } + + +
    +
    + + {{ 'settings.network.title_network' | translate }} +
    +
    +@if (showFields.network) { + +} + + +
    +
    + + {{ 'settings.network.title_security' | translate }} +
    +
    +@if (showFields.security) { + +} - + @if ($settings.env.serviceMode) {
    class="mt-3 hover-pointer" >
    - + {{ 'settings.cache.title' | translate }}
    @@ -487,6 +962,30 @@

    {{ 'settings.cache.desc' | translate }}

    } @if (showFields.cache) {
    } - +
    class="mt-3 hover-pointer" >
    - + {{ 'reset.bridges.title' | translate }}
    diff --git a/ui/src/app/modules/settings/settings.component.ts b/ui/src/app/modules/settings/settings.component.ts index 784640c31..bfce9f273 100644 --- a/ui/src/app/modules/settings/settings.component.ts +++ b/ui/src/app/modules/settings/settings.component.ts @@ -1,7 +1,8 @@ +import { animate, style, transition, trigger } from '@angular/animations' import { NgClass, TitleCasePipe } from '@angular/common' import { Component, inject, OnInit } from '@angular/core' -import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms' -import { RouterLink } from '@angular/router' +import { FormControl, FormsModule, ReactiveFormsModule, UntypedFormControl } from '@angular/forms' +import { Router, RouterLink } from '@angular/router' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' @@ -11,6 +12,7 @@ import { debounceTime } from 'rxjs/operators' import { ApiService } from '@/app/core/api.service' import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' import { SettingsService } from '@/app/core/settings.service' +import { AccessoryControlListsComponent } from '@/app/modules/settings/accessory-control-lists/accessory-control-lists.component' import { BackupComponent } from '@/app/modules/settings/backup/backup.component' import { RemoveAllAccessoriesComponent } from '@/app/modules/settings/remove-all-accessories/remove-all-accessories.component' import { RemoveBridgeAccessoriesComponent } from '@/app/modules/settings/remove-bridge-accessories/remove-bridge-accessories.component' @@ -20,6 +22,39 @@ import { ResetIndividualBridgesComponent } from '@/app/modules/settings/reset-in import { SelectNetworkInterfacesComponent } from '@/app/modules/settings/select-network-interfaces/select-network-interfaces.component' import { WallpaperComponent } from '@/app/modules/settings/wallpaper/wallpaper.component' +interface NetworkAdapterAvailable { + carrierChanges?: number + default?: boolean + dhcp?: boolean + dnsSuffix?: string + duplex?: string + ieee8021xAuth?: string + ieee8021xState?: string + iface: string + ifaceName: string + internal: boolean + ip4: string + ip4subnet: string + ip6: string + ip6subnet: string + mac: string + mtu: number + missing?: boolean + operstate: string + selected: boolean + speed: number + type: string + virtual?: boolean +} + +interface NetworkAdapterSelected { + iface: string + missing: boolean + selected: true + ip4?: string + ip6?: string +} + @Component({ templateUrl: './settings.component.html', standalone: true, @@ -31,159 +66,1034 @@ import { WallpaperComponent } from '@/app/modules/settings/wallpaper/wallpaper.c TitleCasePipe, TranslatePipe, ], + animations: [ + trigger('fadeInOut', [ + transition(':enter', [ + style({ opacity: 0 }), + animate('750ms', style({ opacity: 1 })), + ]), + transition(':leave', [ + animate('750ms', style({ opacity: 0 })), + ]), + ]), + ], }) export class SettingsComponent implements OnInit { private $api = inject(ApiService) private $modal = inject(NgbModal) private $plugin = inject(ManagePluginsService) + private $router = inject(Router) $settings = inject(SettingsService) private $toastr = inject(ToastrService) private $translate = inject(TranslateService) - public originalServiceForm = { - HOMEBRIDGE_DEBUG: false, - HOMEBRIDGE_KEEP_ORPHANS: false, - HOMEBRIDGE_INSECURE: true, - ENV_DEBUG: '', - ENV_NODE_OPTIONS: '', - } - - public originalUiSettingsForm = { - port: 0, - } - - public originalMdnsSetting = '' - public originalBridgeNetworkAdapters: string[] = [] - public originalHbPort = 0 - public originalHbName = '' - - public hasChangedService = false - public hasChangedUiSettings = false - public hasChangedMdns = false - public hasChangedBridgeNetworkAdapters = false - public hasChangedHbPort = false - public hasChangedHbName = false - - public isInvalidHbPort = false - public isInvalidHbName = false - public isInvalidHbUiPort = false - - public serviceForm = new FormGroup({ - HOMEBRIDGE_DEBUG: new FormControl(false), - HOMEBRIDGE_KEEP_ORPHANS: new FormControl(false), - HOMEBRIDGE_INSECURE: new FormControl(true), - ENV_DEBUG: new FormControl(''), - ENV_NODE_OPTIONS: new FormControl(''), - }) + private restartToastIsShown = false - public uiSettingsForm = new FormGroup({ - port: new FormControl(0), - }) - - public legacyMdnsFormControl = new UntypedFormControl(false) - public showAvahiMdnsOption = false - public showResolvedMdnsOption = false - public availableNetworkAdapters: any[] = [] - public bridgeNetworkAdapters: string[] = [] - public hbPortFormControl = new FormControl(0) - public hbNameFormControl = new FormControl('') - public isHbV2 = false public showFields = { general: true, display: true, startup: true, network: true, + security: true, reset: true, cache: true, } + public isHbV2 = false + public showAvahiMdnsOption = false + public showResolvedMdnsOption = false + public adaptersAvailable: NetworkAdapterAvailable[] = [] + public adaptersSelected: NetworkAdapterSelected[] = [] + public showPfxPassphrase = false + + public hbNameIsInvalid = false + public hbNameIsSaving = false + public hbNameFormControl = new FormControl('') + + public uiLangIsSaving = false + public uiLangFormControl = new FormControl('') + + public uiThemeIsSaving = false + public uiThemeFormControl = new FormControl('') + + public uiLightIsSaving = false + public uiLightFormControl = new FormControl('') + + public uiMenuIsSaving = false + public uiMenuFormControl = new FormControl('') + + public uiTempIsSaving = false + public uiTempFormControl = new FormControl('') + + public hbDebugIsSaving = false + public hbDebugFormControl = new FormControl(false) + + public hbInsecureIsSaving = false + public hbInsecureFormControl = new FormControl(false) + + public hbKeepIsSaving = false + public hbKeepFormControl = new FormControl(false) + + public hbEnvDebugIsSaving = false + public hbEnvDebugFormControl = new FormControl('') + + public hbEnvNodeIsSaving = false + public hbEnvNodeFormControl = new FormControl('') + + public hbLogSizeIsInvalid = false + public hbLogSizeIsSaving = false + public hbLogSizeFormControl = new FormControl(-1) + + public hbLogTruncateIsInvalid = false + public hbLogTruncateIsSaving = false + public hbLogTruncateFormControl = new FormControl(0) + + public hbMDnsIsSaving = false + public hbMDnsFormControl = new FormControl('') + + public hbPortIsInvalid = false + public hbPortIsSaving = false + public hbPortFormControl = new FormControl(0) + + public hbStartPortIsInvalid = false + public hbStartPortIsSaving = false + public hbStartPortFormControl = new FormControl(0) + + public hbEndPortIsInvalid = false + public hbEndPortIsSaving = false + public hbEndPortFormControl = new FormControl(0) + + public uiPortIsInvalid = false + public uiPortIsSaving = false + public uiPortFormControl = new FormControl(0) + + public uiAuthIsSaving = false + public uiAuthFormControl = new UntypedFormControl(true) + + public uiSessionTimeoutIsInvalid = false + public uiSessionTimeoutIsSaving = false + public uiSessionTimeoutFormControl = new FormControl(0) + + public uiSslTypeFormControl = new FormControl('off') + + public uiSslKeyIsSaving = false + public uiSslKeyFormControl = new FormControl('') + + public uiSslCertIsSaving = false + public uiSslCertFormControl = new FormControl('') + + public uiSslPfxIsSaving = false + public uiSslPfxFormControl = new FormControl('') + + public uiSslPassphraseIsSaving = false + public uiSslPassphraseFormControl = new FormControl('') + + public uiHostIsSaving = false + public uiHostFormControl = new FormControl('') + + public uiProxyHostIsSaving = false + public uiProxyHostFormControl = new FormControl('') + + public hbPackageIsSaving = false + public hbPackageFormControl = new FormControl('') + + public uiMetricsIsSaving = false + public uiMetricsFormControl = new FormControl(true) + + public uiAccDebugIsSaving = false + public uiAccDebugFormControl = new FormControl(false) + + public uiTempFileIsSaving = false + public uiTempFileFormControl = new FormControl('') + + public hbLinuxShutdownIsSaving = false + public hbLinuxShutdownFormControl = new FormControl('') + + public hbLinuxRestartIsSaving = false + public hbLinuxRestartFormControl = new FormControl('') + public readonly linkDebug = '' constructor() {} - ngOnInit() { + async ngOnInit() { this.isHbV2 = this.$settings.env.homebridgeVersion.startsWith('2') - this.hbNameFormControl.patchValue(this.$settings.env.homebridgeInstanceName) - this.hbNameFormControl.valueChanges.subscribe((name: string) => this.setHomebridgeName(name)) - this.originalHbName = this.$settings.env.homebridgeInstanceName - this.initUiSettingsForm() - this.initNetworkingOptions() + await this.initNetworkingOptions() + if (this.$settings.env.serviceMode) { - this.initServiceModeForm() + await this.initServiceModeForm() } + + this.hbNameFormControl.patchValue(this.$settings.env.homebridgeInstanceName) + this.hbNameFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbNameSave(value)) + + this.uiLangFormControl.patchValue(this.$settings.env.lang) + this.uiLangFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiLangSave(value)) + + this.uiThemeFormControl.patchValue(this.$settings.theme) + this.uiThemeFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiThemeSave(value)) + + this.uiLightFormControl.patchValue(this.$settings.lightingMode) + this.uiLightFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: 'auto' | 'light' | 'dark') => this.uiLightSave(value)) + + this.uiMenuFormControl.patchValue(this.$settings.menuMode) + this.uiMenuFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: 'default' | 'freeze') => this.uiMenuSave(value)) + + this.uiTempFormControl.patchValue(this.$settings.env.temperatureUnits) + this.uiTempFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiTempSave(value)) + + this.hbLogSizeFormControl.patchValue(this.$settings.env.log?.maxSize) + this.hbLogSizeFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: number) => this.hbLogSizeSave(value)) + + this.hbLogTruncateFormControl.patchValue(this.$settings.env.log?.truncateSize) + this.hbLogTruncateFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: number) => this.hbLogTruncateSave(value)) + + this.uiPortFormControl.patchValue(this.$settings.env.port) + this.uiPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: number) => this.uiPortSave(value)) + + this.uiAuthFormControl.patchValue(this.$settings.formAuth) + this.uiAuthFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.uiAuthSave(value)) + + this.uiSessionTimeoutFormControl.patchValue(this.$settings.sessionTimeout) + this.uiSessionTimeoutFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: number) => this.uiSessionTimeoutSave(value)) + + this.uiSslKeyFormControl.patchValue(this.$settings.env.ssl?.key || '') + this.uiSslKeyFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslKeySave(value)) + + this.uiSslCertFormControl.patchValue(this.$settings.env.ssl?.cert || '') + this.uiSslCertFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslCertSave(value)) + + this.uiSslPfxFormControl.patchValue(this.$settings.env.ssl?.pfx || '') + this.uiSslPfxFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslPfxSave(value)) + + this.uiSslPassphraseFormControl.patchValue(this.$settings.env.ssl?.passphrase || '') + this.uiSslPassphraseFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiSslPassphraseSave(value)) + + this.uiSslTypeFormControl.patchValue(this.uiSslKeyFormControl.value || this.uiSslCertFormControl.value + ? 'keycert' + : (this.uiSslPfxFormControl.value || this.uiSslPassphraseFormControl.value) ? 'pfx' : 'off') + this.uiSslTypeFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.uiSslTypeSave(value)) + + this.uiHostFormControl.patchValue(this.$settings.env.host || '') + this.uiHostFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiHostSave(value)) + + this.uiProxyHostFormControl.patchValue(this.$settings.env.proxyHost || '') + this.uiProxyHostFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiProxyHostSave(value)) + + this.hbPackageFormControl.patchValue(this.$settings.env.homebridgePackagePath || '') + this.hbPackageFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbPackageSave(value)) + + this.uiMetricsFormControl.patchValue(!this.$settings.env.disableServerMetricsMonitoring) + this.uiMetricsFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.uiMetricsSave(value)) + + this.uiAccDebugFormControl.patchValue(this.$settings.env.accessoryControl?.debug) + this.uiAccDebugFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.uiAccDebugSave(value)) + + this.uiTempFileFormControl.patchValue(this.$settings.env.temp) + this.uiTempFileFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.uiTempFileSave(value)) + + this.hbLinuxShutdownFormControl.patchValue(this.$settings.env.linux?.shutdown) + this.hbLinuxShutdownFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbLinuxShutdownSave(value)) + + this.hbLinuxRestartFormControl.patchValue(this.$settings.env.linux?.restart) + this.hbLinuxRestartFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbLinuxRestartSave(value)) } - initUiSettingsForm() { - this.originalUiSettingsForm = { - port: this.$settings.env.port, + async initServiceModeForm() { + try { + const serviceModeData = await firstValueFrom(this.$api.get('/platform-tools/hb-service/homebridge-startup-settings')) + + this.hbDebugFormControl.patchValue(serviceModeData.HOMEBRIDGE_DEBUG) + this.hbDebugFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.hbDebugSave(value)) + + this.hbInsecureFormControl.patchValue(serviceModeData.HOMEBRIDGE_INSECURE) + this.hbInsecureFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.hbInsecureSave(value)) + + this.hbKeepFormControl.patchValue(serviceModeData.HOMEBRIDGE_KEEP_ORPHANS) + this.hbKeepFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.hbKeepSave(value)) + + this.hbEnvDebugFormControl.patchValue(serviceModeData.ENV_DEBUG) + this.hbEnvDebugFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbEnvDebugSave(value)) + + this.hbEnvNodeFormControl.patchValue(serviceModeData.ENV_NODE_OPTIONS) + this.hbEnvNodeFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((value: string) => this.hbEnvNodeSave(value)) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) } - this.uiSettingsForm.patchValue({ - port: this.$settings.env.port, - }) - this.uiSettingsForm.valueChanges.pipe(debounceTime(500)).subscribe((data) => { - let hasChangedUiSettings = false - Object.keys(data).forEach((key) => { - if (this.originalUiSettingsForm[key] !== data[key]) { - this.saveUiSettingChange(key, data[key]) - hasChangedUiSettings = true - } - }) - this.hasChangedUiSettings = hasChangedUiSettings + } + + async initNetworkingOptions() { + try { + await this.getNetworkSettings() + const onLinux = ( + this.$settings.env.runningInLinux + || this.$settings.env.runningInDocker + || this.$settings.env.runningInSynologyPackage + || this.$settings.env.runningInPackageMode + ) + if (onLinux) { + this.showAvahiMdnsOption = true + this.showResolvedMdnsOption = true + } + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } + + async getNetworkSettings() { + return Promise.all([ + firstValueFrom(this.$api.get('/server/network-interfaces/system')), + firstValueFrom(this.$api.get('/server/network-interfaces/bridge')), + firstValueFrom(this.$api.get('/server/mdns-advertiser')), + firstValueFrom(this.$api.get('/server/port')), + firstValueFrom(this.$api.get('/server/ports')), + ]).then(([system, adapters, mdnsAdvertiser, port, ports]: [NetworkAdapterAvailable[], string[], { advertiser: string }, { port: number }, { start?: number, end?: number }]) => { + this.adaptersAvailable = system + this.buildBridgeNetworkAdapterList(adapters) + + this.hbMDnsFormControl.patchValue(mdnsAdvertiser.advertiser) + this.hbMDnsFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: string) => this.hbMDnsSave(value)) + + this.hbPortFormControl.patchValue(port.port) + this.hbPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((port: number) => this.hbPortSave(port)) + + this.hbStartPortFormControl.patchValue(ports.start) + this.hbStartPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((port: number) => this.hbStartPortSave(port)) + + this.hbEndPortFormControl.patchValue(ports.end) + this.hbEndPortFormControl.valueChanges + .pipe(debounceTime(1500)) + .subscribe((port: number) => this.hbEndPortSave(port)) }) } - initServiceModeForm() { - this.$api.get('/platform-tools/hb-service/homebridge-startup-settings').subscribe({ - next: (data) => { - Object.keys(data).forEach((key) => { - this.originalServiceForm[key] = data[key] + async saveUiSettingChange(key: string, value: any) { + // Save the new property to the config file + try { + await firstValueFrom(this.$api.put('/config-editor/ui', { key, value })) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } + + async hbNameSave(value: string) { + // https://github.com/homebridge/HAP-NodeJS/blob/ee41309fd9eac383cdcace39f4f6f6a3d54396f3/src/lib/util/checkName.ts#L12 + if (!value || !(/^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u).test(value)) { + this.hbNameIsInvalid = true + return + } + + try { + this.hbNameIsSaving = true + await firstValueFrom(this.$api.put('/server/name', { value })) + this.$settings.setEnvItem('homebridgeInstanceName', value) + this.hbNameIsInvalid = false + setTimeout(() => { + this.hbNameIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbNameIsSaving = false + } + } + + async uiLangSave(value: string) { + try { + this.uiLangIsSaving = true + this.$settings.setLang(value) + await this.saveUiSettingChange('lang', value) + setTimeout(() => { + this.uiLangIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiLangIsSaving = false + } + } + + async uiThemeSave(value: string) { + try { + this.uiThemeIsSaving = true + this.$settings.setTheme(value) + await this.saveUiSettingChange('theme', value) + setTimeout(() => { + this.uiThemeIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiThemeIsSaving = false + } + } + + async uiLightSave(value: 'auto' | 'light' | 'dark') { + try { + this.uiLightIsSaving = true + this.$settings.setLightingMode(value, 'user') + await this.saveUiSettingChange('lightingMode', value) + setTimeout(() => { + this.uiLightIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiLightIsSaving = false + } + } + + async uiMenuSave(value: 'default' | 'freeze') { + try { + this.uiMenuIsSaving = true + this.$settings.setMenuMode(value) + await this.saveUiSettingChange('menuMode', value) + window.location.reload() + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiMenuIsSaving = false + } + } + + async uiTempSave(value: string) { + try { + this.uiTempIsSaving = true + this.$settings.setEnvItem('temperatureUnits', value) + await this.saveUiSettingChange('tempUnits', value) + setTimeout(() => { + this.uiTempIsSaving = false + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiTempIsSaving = false + } + } + + async hbDebugSave(value: boolean) { + try { + this.hbDebugIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbDebugIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, }) - this.serviceForm.patchValue(data) - this.serviceForm.valueChanges.pipe(debounceTime(500)).subscribe(this.saveServiceModeSettings.bind(this)) - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbDebugIsSaving = false + } } - saveUiSettingChange(key: string, value: any) { - // Extra things to do per key - switch (key) { - case 'lang': - this.$settings.setLang(value) - break - case 'lightingMode': - this.$settings.setLightingMode(value, 'user') - break - case 'menuMode': - this.$settings.setMenuMode(value) - window.location.reload() - break - case 'theme': - this.$settings.setTheme(value) - break - case 'tempUnits': - this.$settings.setEnvItem('temperatureUnits', value) + async hbInsecureSave(value: boolean) { + try { + this.hbInsecureIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbInsecureIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbInsecureIsSaving = false + } + } + + async hbKeepSave(value: boolean) { + try { + this.hbKeepIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbKeepIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbKeepIsSaving = false + } + } + + async hbEnvDebugSave(value: string) { + try { + this.hbEnvDebugIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: value, + ENV_NODE_OPTIONS: this.hbEnvNodeFormControl.value, + })) + setTimeout(() => { + this.hbEnvDebugIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbEnvDebugIsSaving = false + } + } + + async hbEnvNodeSave(value: string) { + try { + this.hbEnvNodeIsSaving = true + await firstValueFrom(this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', { + HOMEBRIDGE_DEBUG: this.hbDebugFormControl.value, + HOMEBRIDGE_KEEP_ORPHANS: this.hbKeepFormControl.value, + HOMEBRIDGE_INSECURE: this.hbInsecureFormControl.value, + ENV_DEBUG: this.hbEnvDebugFormControl.value, + ENV_NODE_OPTIONS: value, + })) + setTimeout(() => { + this.hbEnvNodeIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbEnvNodeIsSaving = false + } + } + + async hbLogSizeSave(value: number) { + if (value && (typeof value !== 'number' || value < -1 || Number.isInteger(value) === false)) { + this.hbLogSizeIsInvalid = true + return + } + + try { + this.hbLogSizeIsSaving = true + this.$settings.setEnvItem('log.maxSize', value) + if (!value || value === -1) { + // If the value is -1, we set the log.maxSize to undefined + // This will remove the setting from the config file + await this.saveUiSettingChange('log.truncateSize', null) + this.hbLogTruncateIsInvalid = false + } + await this.saveUiSettingChange('log.maxSize', value) + this.hbLogSizeIsInvalid = false + setTimeout(() => { + this.hbLogSizeIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLogSizeIsSaving = false + } + } + + async hbLogTruncateSave(value: number) { + if (value && (typeof value !== 'number' || value < 0 || Number.isInteger(value) === false)) { + this.hbLogTruncateIsInvalid = true + return + } + + try { + this.hbLogTruncateIsSaving = true + this.$settings.setEnvItem('log.truncateSize', value) + await this.saveUiSettingChange('log.truncateSize', value) + this.hbLogTruncateIsInvalid = false + setTimeout(() => { + this.hbLogTruncateIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLogTruncateIsSaving = false + } + } + + async hbMDnsSave(value: string) { + try { + this.hbMDnsIsSaving = true + await firstValueFrom(this.$api.put('/server/mdns-advertiser', { advertiser: value })) + setTimeout(() => { + this.hbMDnsIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbMDnsIsSaving = false + } + } + + async hbPortSave(value: number) { + if (value === this.uiPortFormControl.value) { + this.hbPortIsInvalid = true + return + } + + try { + this.hbPortIsSaving = true + await firstValueFrom(this.$api.put('/server/port', { port: value })) + this.hbPortIsInvalid = false + setTimeout(() => { + this.hbPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbPortIsSaving = false + } + } + + async hbStartPortSave(value: number) { + try { + this.hbStartPortIsSaving = true + await firstValueFrom(this.$api.put('/server/ports', { start: value, end: this.hbEndPortFormControl.value })) + this.hbStartPortIsInvalid = false + setTimeout(() => { + this.hbStartPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbStartPortIsSaving = false + } + } + + async hbEndPortSave(value: number) { + try { + this.hbEndPortIsSaving = true + await firstValueFrom(this.$api.put('/server/ports', { start: this.hbStartPortFormControl.value, end: value })) + this.hbEndPortIsInvalid = false + setTimeout(() => { + this.hbEndPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbEndPortIsSaving = false + } + } + + async uiPortSave(value: number) { + if (!value || typeof value !== 'number' || value < 1025 || value > 65533 || Number.isInteger(value) === false || value === this.hbPortFormControl.value) { + this.uiPortIsInvalid = true + return + } + + try { + this.uiPortIsSaving = true + this.$settings.setEnvItem('port', value) + await this.saveUiSettingChange('port', value) + this.uiPortIsInvalid = false + setTimeout(() => { + this.uiPortIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiPortIsSaving = false + } + } + + async uiAuthSave(value: boolean) { + try { + this.uiAuthIsSaving = true + this.$settings.setItem('formAuth', value) + await this.saveUiSettingChange('auth', value ? 'form' : 'none') + setTimeout(() => { + this.uiAuthIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiAuthIsSaving = false + } + } + + async uiSessionTimeoutSave(value: number) { + if (value && (typeof value !== 'number' || value < 600 || value > 86400000 || Number.isInteger(value) === false)) { + this.uiSessionTimeoutIsInvalid = true + return + } + + try { + this.uiSessionTimeoutIsSaving = true + this.$settings.setItem('sessionTimeout', value) + await this.saveUiSettingChange('sessionTimeout', value) + this.uiSessionTimeoutIsInvalid = false + setTimeout(() => { + this.uiSessionTimeoutIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSessionTimeoutIsSaving = false + } + } + + async uiSslKeySave(value: string) { + try { + this.uiSslKeyIsSaving = true + this.$settings.setEnvItem('ssl.key', value) + await this.saveUiSettingChange('ssl.key', value) + setTimeout(() => { + this.uiSslKeyIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslKeyIsSaving = false + } + } + + async uiSslCertSave(value: string) { + try { + this.uiSslCertIsSaving = true + this.$settings.setEnvItem('ssl.cert', value) + await this.saveUiSettingChange('ssl.cert', value) + setTimeout(() => { + this.uiSslCertIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslCertIsSaving = false + } + } + + async uiSslPfxSave(value: string) { + try { + this.uiSslPfxIsSaving = true + this.$settings.setEnvItem('ssl.pfx', value) + await this.saveUiSettingChange('ssl.pfx', value) + setTimeout(() => { + this.uiSslPfxIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslPfxIsSaving = false + } + } + + async uiSslPassphraseSave(value: string) { + try { + this.uiSslPassphraseIsSaving = true + this.$settings.setEnvItem('ssl.passphrase', value) + await this.saveUiSettingChange('ssl.passphrase', value) + setTimeout(() => { + this.uiSslPassphraseIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiSslPassphraseIsSaving = false + } + } + + async uiSslTypeSave(value: string) { + switch (value) { + case 'keycert': + this.uiSslPfxFormControl.patchValue('', { emitEvent: false }) + this.uiSslPassphraseFormControl.patchValue('', { emitEvent: false }) + this.$settings.setEnvItem('ssl.pfx', '') + this.$settings.setEnvItem('ssl.passphrase', '') break - case 'port': - if (!value || typeof value !== 'number' || value < 1025 || value > 65533 || Number.isInteger(value) === false || value === this.hbPortFormControl.value) { - this.isInvalidHbUiPort = true - return - } - this.$settings.setEnvItem('port', value) - this.isInvalidHbUiPort = false + case 'pfx': + this.uiSslKeyFormControl.patchValue('', { emitEvent: false }) + this.uiSslCertFormControl.patchValue('', { emitEvent: false }) + this.$settings.setEnvItem('ssl.key', '') + this.$settings.setEnvItem('ssl.cert', '') break + default: + this.uiSslKeyFormControl.patchValue('', { emitEvent: false }) + this.uiSslCertFormControl.patchValue('', { emitEvent: false }) + this.uiSslPfxFormControl.patchValue('', { emitEvent: false }) + this.uiSslPassphraseFormControl.patchValue('', { emitEvent: false }) + this.$settings.setEnvItem('ssl.key', '') + this.$settings.setEnvItem('ssl.cert', '') + this.$settings.setEnvItem('ssl.pfx', '') + this.$settings.setEnvItem('ssl.passphrase', '') + await this.saveUiSettingChange('ssl', '') + this.showRestartToast() } + } - // Save the new property to the config file - firstValueFrom(this.$api.put('/config-editor/ui', { key, value })) - .catch((error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }) + async uiHostSave(value: string) { + try { + this.uiHostIsSaving = true + this.$settings.setEnvItem('host', value) + await this.saveUiSettingChange('host', value) + setTimeout(() => { + this.uiHostIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiHostIsSaving = false + } + } + + async uiProxyHostSave(value: string) { + try { + this.uiProxyHostIsSaving = true + this.$settings.setEnvItem('proxyHost', value) + await this.saveUiSettingChange('proxyHost', value) + setTimeout(() => { + this.uiProxyHostIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiProxyHostIsSaving = false + } + } + + async hbPackageSave(value: string) { + try { + this.hbPackageIsSaving = true + this.$settings.setEnvItem('homebridgePackagePath', value) + await this.saveUiSettingChange('homebridgePackagePath', value) + setTimeout(() => { + this.hbPackageIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbPackageIsSaving = false + } + } + + async uiMetricsSave(value: boolean) { + try { + this.uiMetricsIsSaving = true + this.$settings.setEnvItem('disableServerMetricsMonitoring', !value) + await this.saveUiSettingChange('disableServerMetricsMonitoring', !value) + setTimeout(() => { + this.uiMetricsIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiMetricsIsSaving = false + } + } + + async uiAccDebugSave(value: boolean) { + try { + this.uiAccDebugIsSaving = true + this.$settings.setEnvItem('accessoryControl.debug', value) + await this.saveUiSettingChange('accessoryControl.debug', value) + setTimeout(() => { + this.uiAccDebugIsSaving = false + this.showRestartToast() + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiAccDebugIsSaving = false + } + } + + async uiTempFileSave(value: string) { + try { + this.uiTempFileIsSaving = true + this.$settings.setEnvItem('temp', value) + await this.saveUiSettingChange('temp', value) + setTimeout(() => { + this.uiTempFileIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.uiTempFileIsSaving = false + } + } + + async hbLinuxShutdownSave(value: string) { + try { + this.hbLinuxShutdownIsSaving = true + this.$settings.setEnvItem('linux.shutdown', value) + await this.saveUiSettingChange('linux.shutdown', value) + setTimeout(() => { + this.hbLinuxShutdownIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLinuxShutdownIsSaving = false + } + } + + async hbLinuxRestartSave(value: string) { + try { + this.hbLinuxRestartIsSaving = true + this.$settings.setEnvItem('linux.restart', value) + await this.saveUiSettingChange('linux.restart', value) + setTimeout(() => { + this.hbLinuxRestartIsSaving = false + this.$api.put('/platform-tools/hb-service/set-full-service-restart-flag', {}).subscribe({ + next: () => this.showRestartToast(), + error: (error) => { + console.error(error) + this.showRestartToast() + }, + }) + }, 1000) + } catch (error) { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + this.hbLinuxRestartIsSaving = false + } } openUiSettings() { @@ -209,18 +1119,6 @@ export class SettingsComponent implements OnInit { }) } - saveServiceModeSettings(data = this.serviceForm.value) { - this.$api.put('/platform-tools/hb-service/homebridge-startup-settings', data).subscribe({ - next: () => { - this.hasChangedService = JSON.stringify(data) !== JSON.stringify(this.originalServiceForm) - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) - } - resetHomebridgeState() { this.$modal.open(ResetAllBridgesComponent, { size: 'lg', @@ -242,6 +1140,25 @@ export class SettingsComponent implements OnInit { }) } + async accessoryUiControl() { + try { + const ref = this.$modal.open(AccessoryControlListsComponent, { + size: 'lg', + backdrop: 'static', + }) + + ref.componentInstance.existingBlacklist = this.$settings.env.accessoryControl?.instanceBlacklist || [] + + await ref.result + this.showRestartToast() + } catch (error) { + if (error !== 'Dismiss') { + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } + } + removeSingleCachedAccessories() { this.$modal.open(RemoveIndividualAccessoriesComponent, { size: 'lg', @@ -256,142 +1173,78 @@ export class SettingsComponent implements OnInit { }) } - async initNetworkingOptions() { - try { - this.getNetworkSettings() - const onLinux = ( - this.$settings.env.runningInLinux - || this.$settings.env.runningInDocker - || this.$settings.env.runningInSynologyPackage - || this.$settings.env.runningInPackageMode - ) - if (onLinux) { - this.showAvahiMdnsOption = true - this.showResolvedMdnsOption = true - } - } catch (e) {} - } - - async getNetworkSettings() { - return Promise.all([ - firstValueFrom(this.$api.get('/server/network-interfaces/system')), - firstValueFrom(this.$api.get('/server/network-interfaces/bridge')), - firstValueFrom(this.$api.get('/server/mdns-advertiser')), - firstValueFrom(this.$api.get('/server/port')), - ]).then(([system, adapters, mdnsAdvertiser, port]) => { - this.availableNetworkAdapters = system - this.buildBridgeNetworkAdapterList(adapters) - this.legacyMdnsFormControl.patchValue(mdnsAdvertiser.advertiser) - this.originalMdnsSetting = mdnsAdvertiser.advertiser - this.originalBridgeNetworkAdapters = this.bridgeNetworkAdapters.map((x: any) => x.iface) - this.legacyMdnsFormControl.valueChanges.subscribe((advertiser: string) => { - this.setHomebridgeMdnsSetting(advertiser) - }) - this.hbPortFormControl.patchValue(port.port) - this.hbPortFormControl.valueChanges.subscribe((port: number) => this.setHomebridgePort(port)) - this.originalHbPort = port.port + async selectNetworkInterfaces() { + const ref = this.$modal.open(SelectNetworkInterfacesComponent, { + size: 'lg', + backdrop: 'static', }) - } - async setHomebridgeMdnsSetting(advertiser: string) { - this.$api.put('/server/mdns-advertiser', { advertiser }).subscribe({ - next: () => { - this.hasChangedMdns = advertiser !== this.originalMdnsSetting - }, - error: (error) => { - console.error(error) - this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) - } + ref.componentInstance.adaptersAvailable = this.adaptersAvailable - async setNetworkInterfaces(adapters: string[]) { - this.$api.put('/server/network-interfaces/bridge', { adapters }).subscribe({ - next: () => { - this.hasChangedBridgeNetworkAdapters = this.originalBridgeNetworkAdapters.join(',') !== adapters.join(',') - }, - error: (error) => { + try { + const adapters: string[] = await ref.result + this.buildBridgeNetworkAdapterList(adapters) + await firstValueFrom(this.$api.put('/server/network-interfaces/bridge', { adapters })) + this.showRestartToast() + } catch (error) { + if (error !== 'Dismiss') { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) - }, - }) - } - - async setHomebridgeName(name: string) { - // https://github.com/homebridge/HAP-NodeJS/blob/ee41309fd9eac383cdcace39f4f6f6a3d54396f3/src/lib/util/checkName.ts#L12 - if (!name || !(/^[\p{L}\p{N}][\p{L}\p{N} ']*[\p{L}\p{N}]$/u).test(name)) { - this.isInvalidHbName = true - return - } - - this.$api.put('/server/name', { name }).subscribe({ - next: () => { - this.hasChangedHbName = this.originalHbName !== name - this.$settings.setEnvItem('homebridgeInstanceName', name) - this.isInvalidHbName = false - }, - error: () => { - this.isInvalidHbName = true - }, - }) - } - - async setHomebridgePort(port: number) { - if (port === this.uiSettingsForm.get('port').value) { - this.isInvalidHbPort = true - return + } } - - this.$api.put('/server/port', { port }).subscribe({ - next: () => { - this.hasChangedHbPort = this.originalHbPort !== port - this.isInvalidHbPort = false - }, - error: () => { - this.isInvalidHbPort = true - }, - }) } buildBridgeNetworkAdapterList(adapters: string[]) { if (!adapters.length) { - this.bridgeNetworkAdapters = [] + this.adaptersSelected = [] return } - this.bridgeNetworkAdapters = adapters.map((interfaceName) => { - const i = this.availableNetworkAdapters.find((x: any) => x.iface === interfaceName) + this.adaptersSelected = adapters.map((interfaceName) => { + const i = this.adaptersAvailable.find(x => x.iface === interfaceName) if (i) { - i.selected = true - i.missing = false - return i + return { + iface: i.iface, + selected: true, + missing: false, + ip4: i.ip4, + ip6: i.ip6, + } } else { return { iface: interfaceName, + selected: true, missing: true, } } }) } - selectNetworkInterfaces() { - const ref = this.$modal.open(SelectNetworkInterfacesComponent, { - size: 'lg', - backdrop: 'static', - }) - - ref.componentInstance.availableNetworkAdapters = this.availableNetworkAdapters - ref.componentInstance.bridgeNetworkAdapters = this.bridgeNetworkAdapters - - ref.result - .then((adapters: string[]) => { - this.buildBridgeNetworkAdapterList(adapters) - this.setNetworkInterfaces(adapters) - }) - .catch(() => { /* do nothing */ }) - } - toggleSection(section: string) { this.showFields[section] = !this.showFields[section] } + + showRestartToast() { + if (!this.restartToastIsShown) { + this.restartToastIsShown = true + const ref = this.$toastr.info( + this.$translate.instant('settings.changes.saved'), + this.$translate.instant('menu.hbrestart.title'), + { + timeOut: 0, + closeButton: false, + tapToDismiss: true, + disableTimeOut: true, + positionClass: 'toast-bottom-right', + enableHtml: true, + }, + ) + + if (ref && ref.onTap) { + ref.onTap.subscribe(() => { + this.$router.navigate(['/restart']) + }) + } + } + } } diff --git a/ui/src/app/modules/settings/settings.module.ts b/ui/src/app/modules/settings/settings.module.ts index c2be4fdf4..5f613d788 100644 --- a/ui/src/app/modules/settings/settings.module.ts +++ b/ui/src/app/modules/settings/settings.module.ts @@ -4,6 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { NgbModule } from '@ng-bootstrap/ng-bootstrap' import { TranslateModule } from '@ngx-translate/core' +import { AccessoryControlListsComponent } from '@/app/modules/settings/accessory-control-lists/accessory-control-lists.component' import { BackupComponent } from '@/app/modules/settings/backup/backup.component' import { RestoreComponent } from '@/app/modules/settings/backup/restore/restore.component' import { RemoveAllAccessoriesComponent } from '@/app/modules/settings/remove-all-accessories/remove-all-accessories.component' @@ -25,6 +26,7 @@ import { WallpaperComponent } from '@/app/modules/settings/wallpaper/wallpaper.c NgbModule, SettingsRoutingModule, SettingsComponent, + AccessoryControlListsComponent, ResetAllBridgesComponent, ResetIndividualBridgesComponent, RemoveAllAccessoriesComponent, diff --git a/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts b/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts index 62c567177..258b97076 100644 --- a/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts +++ b/ui/src/app/modules/settings/wallpaper/wallpaper.component.ts @@ -60,6 +60,7 @@ export class WallpaperComponent { formData.append('wallpaper', this.selectedFile, this.selectedFile.name) this.$api.post('/server/wallpaper', formData).subscribe({ next: () => { + this.$settings.setItem('wallpaper', `ui-wallpaper.${this.selectedFile.name.split('.').pop()}`) this.$activeModal.close() this.$toastr.success(this.$translate.instant('settings.display.wallpaper_success'), this.$translate.instant('toast.title_success')) }, diff --git a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html index 4d7206258..316323643 100644 --- a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html +++ b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.html @@ -15,24 +15,17 @@ @for (widget of availableWidgets; track widget) {
  • {{ widget.name }} -
    - - -
    + /> + +
  • } diff --git a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts index 2799e32d9..a6313d4ba 100644 --- a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts +++ b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts @@ -1,4 +1,5 @@ import { Component, inject, Input, OnInit } from '@angular/core' +import { FormsModule } from '@angular/forms' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' @@ -9,6 +10,7 @@ import { SettingsService } from '@/app/core/settings.service' standalone: true, imports: [ TranslatePipe, + FormsModule, ], }) export class WidgetVisibilityComponent implements OnInit { @@ -141,7 +143,7 @@ export class WidgetVisibilityComponent implements OnInit { .sort((a, b) => a.name.localeCompare(b.name)) .map(x => ({ ...x, - shown: !this.dashboard.some((i: any) => i.component === x.component), + shown: this.dashboard.some((i: any) => i.component === x.component), })) } diff --git a/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts index e3714f86d..17063bd86 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts @@ -76,6 +76,7 @@ export class HbV2ModalComponent implements OnInit { hb2Ready, } }) + .sort((a, b) => a.name.localeCompare(b.name)) // Skip if there are no plugins installed if (this.installedPlugins.length === 0) { diff --git a/ui/src/app/modules/support/support.component.html b/ui/src/app/modules/support/support.component.html index 1935acd38..e4dc9df01 100644 --- a/ui/src/app/modules/support/support.component.html +++ b/ui/src/app/modules/support/support.component.html @@ -12,7 +12,10 @@

    {{ 'support.title' | translate }}

    class="mt-3 hover-pointer" >
    - + {{ 'support.links.title' | translate }}
    @@ -95,7 +98,7 @@
    class="mt-3 hover-pointer" >
    - + {{ 'support.dev.title' | translate }}
    diff --git a/ui/src/app/shared/layout/sidebar/sidebar.component.ts b/ui/src/app/shared/layout/sidebar/sidebar.component.ts index 998abf931..edf874eaf 100644 --- a/ui/src/app/shared/layout/sidebar/sidebar.component.ts +++ b/ui/src/app/shared/layout/sidebar/sidebar.component.ts @@ -43,7 +43,6 @@ export class SidebarComponent implements OnInit, OnDestroy { constructor() { const router = this.router - this.isMobile = window.innerWidth < 768 let resizeTimeout: any window.addEventListener('resize', () => { diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 81ea6e04e..73927ce28 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Всички резервни копия са изтрити", "config.title_backup_loaded": "Резервното копие е заредено", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Отказ", "form.button_close": "Затвори", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Промени", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 8f234e503..8af51d492 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Totes les còpies de seguretat eliminades", "config.title_backup_loaded": "Còpia de seguretat carregada", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancel·lar", "form.button_close": "Tancar", @@ -159,7 +160,6 @@ "form.button_download": "Descarregar", "form.button_edit": "Editar", "form.button_enable": "Activar", - "form.button_hide": "Amagar", "form.button_lock": "Bloquejar", "form.button_more_info": "Més Informació", "form.button_remove": "Eliminar", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Aquesta Raspberry Pi informa que actualment està sota tensió; comproveu que estigui connectat a una font d'alimentació adequada. La baixa tensió pot provocar inestabilitat del sistema i corrupció de la targeta SD.", "rpi.throttled.previously_message": "Aquest Raspberry Pi ha informat d'un esdeveniment de baixa tensió des que es va reiniciar per última vegada; comproveu que estigui connectat a una font d'alimentació adequada.", "rpi.throttled.undervoltage_title": "Baixa de Tensió", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Mètode de difusió mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Si tens problemes per connectar a Homebridge, prova d’utilitzar un mètode de difusió mDNS alternatiu.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nom de la interfície", - "settings.network.label_ip_address": "Adreça IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Si no es selecciona cap interfície de xarxa, Homebridge intentarà determinar automàticament quines interfícies difondre.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Xarxa", "settings.network.title_network_interfaces": "Interfícies de xarxa", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opcions d'arrencada", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Començar", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index e17ddcfe6..55fdfae9c 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Všechny zálohy byly smazány", "config.title_backup_loaded": "Záloha byla načtena", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Zpět", "form.button_cancel": "Zrušit", "form.button_close": "Zavřít", @@ -159,7 +160,6 @@ "form.button_download": "Stáhnout", "form.button_edit": "Editovat", "form.button_enable": "Povolit", - "form.button_hide": "Skrýt", "form.button_lock": "Zamknout", "form.button_more_info": "Více informací", "form.button_remove": "Odstranit", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Toto Raspberry Pi hlásí podpětí; zkontrolujte, zda je připojen ke vhodnému zdroji napájení. Podpětí může způsobit nestabilitu systému a poškození SD karty.", "rpi.throttled.previously_message": "Toto Raspberry Pi hlásilo podpětí od posledního restartu; zkontrolujte, zda je připojen ke vhodnému zdroji napájení.", "rpi.throttled.undervoltage_title": "Podpětí", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge uchovává příslušenství v mezipaměti, aby nebylo odstraněno a znovu přidáváno do HomeKitu při každém restartu Homebridge. Někdy může být tato mezipaměť neaktuální ve vztahu k aktuálnímu stavu příslušenství v Homebridge.", "settings.cache.title": "Příslušenství", "settings.changes.saved": "Vaše změny byly uloženy a k jejich použití je třeba restartovat.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Displej", "settings.general.title_general": "Obecné", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Inzerent", "settings.mdns_advertiser_exp": "experimentální", "settings.mdns_advertiser_help": "Pokud máte potíže s připojením k Homebridge, zkuste použít některého z alternativních inzerentů mDNS.", "settings.mdns_advertiser_not_connected": "Není připojeno", "settings.mdns_advertiser_rec": "doporučeno", - "settings.network.label_interface_name": "Jméno rozhraní", - "settings.network.label_ip_address": "IP Adresa", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Pokud nejsou vybrána žádná síťová rozhraní, Homebridge se pokusí automaticky určit, na kterých rozhraních má inzerovat.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Portové číslo, na kterém běží Homebridge most. Toto číslo musí být mezi 1025 a 65533 a nemělo by být stejné jako port pro rozhraní Homebridge UI.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "Port UI", "settings.network.port_ui_desc": "Portové číslo, na kterém běží Homebridge UI.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Síť", "settings.network.title_network_interfaces": "Síťové Rozhraní", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Nepodařilo se resetovat most.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Některé pluginy vyžadují nastavení proměnné prostředí DEBUG pro povolení podrobného protokolování chybové úrovně.", "settings.service.node_tooltip": "Možnosti běhu Node.js pro tento proces. Toto by mělo zůstat prázdné, pokud nevíte, co děláte.", "settings.startup.debug": "Homebridge Režim ladění", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Pro ovládání příslušenství prostřednictvím rozhraní Homebridge UI musíte běžet Homebridge v nezabezpečeném režimu.", "settings.startup.keep_accessories": "Zachovat příslušenství od odinstalovaných pluginů", "settings.startup.keep_accessories_desc": "Pokud je povoleno, příslušenství platformových pluginů zůstane v cache i po odinstalaci pluginu. To může být užitečné, pokud plánujete plugin později znovu nainstalovat.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Možnosti spuštění", "settings.unpair_bridge.load_error": "Spárované mosty nelze načíst.", "setup.button_get_started": "Začněme", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index 079698c3d..0fd537164 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alle Backups gelöscht", "config.title_backup_loaded": "Backup geladen", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Zurück", "form.button_cancel": "Abbrechen", "form.button_close": "Schließen", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Bearbeiten", "form.button_enable": "Aktivieren", - "form.button_hide": "Verstecken", "form.button_lock": "Sperren", "form.button_more_info": "Mehr Informationen", "form.button_remove": "Entfernen", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Dieser Raspberry Pi meldet, dass er derzeit unter zu niedriger Spannung steht; bitte überprüfen Sie, ob er an eine geeignete Stromversorgung angeschlossen ist. Eine Unterspannung kann zur Instabilität des Systems und zur Beschädigung der SD-Karte führen.", "rpi.throttled.previously_message": "Dieser Raspberry Pi hat seit dem letzten Neustart ein Unterspannungsereignis gemeldet; bitte überprüfen Sie, ob er an eine geeignete Stromversorgung angeschlossen ist.", "rpi.throttled.undervoltage_title": "Unterspannung", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge verwaltet Zubehöre im Cache, damit es nicht bei jedem Neustart von Homebridge entfernt und neu zu HomeKit hinzugefügt wird. Manchmal kann dieser Cache nicht mehr mit den tatsächlichen Zubehör in Homebridge synchronisiert werden.", "settings.cache.title": "Zubehör", "settings.changes.saved": "Ihre Änderungen wurden gespeichert und erfordern einen Neustart, um wirksam zu werden..", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Anzeige", "settings.general.title_general": "Allgemein", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimentell", "settings.mdns_advertiser_help": "Wenn du Probleme hast, dich mit Homebridge zu verbinden, versuche einen der alternativen mDNS Advertiser zu verwenden.", "settings.mdns_advertiser_not_connected": "Nicht verbunden", "settings.mdns_advertiser_rec": "empfohlen", - "settings.network.label_interface_name": "Schnittstellen-Name", - "settings.network.label_ip_address": "IP-Adresse", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Wenn keine Netzwerkschnittstellen ausgewählt sind, versucht Homebridge automatisch zu bestimmen, welche Schnittstellen angezeigt werden sollen.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Die Portnummer, unter der die Homebridge-Bridge ausgeführt werden soll. Diese muss zwischen 1025 und 65533 liegen und sollte nicht mit dem Port der Homebridge-Benutzeroberfläche übereinstimmen.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "Die Portnummer, über die die Homebridge UI ausgeführt werden soll.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Netzwerk", "settings.network.title_network_interfaces": "Netzwerkschnittstellen", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Zurücksetzen der Bridge fehlgeschlagen.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Bei einigen Plugins müssen Sie die Umgebungsvariable DEBUG setzen {{ link }}, um die Protokollierung auf Debug-Ebene zu aktivieren.", "settings.service.node_tooltip": "Node.js-Laufzeitoptionen für den Homebridge-Prozess. Dies sollte leer bleiben, wenn Sie nicht wissen, was Sie tun.", "settings.startup.debug": "Homebridge 'Debug' Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Um Ihre Zubehör über die Homebridge-Benutzeroberfläche zu steuern, müssen Sie Homebridge im 'Insecure' Mode ausführen.", "settings.startup.keep_accessories": "Behalte Zubehöre von nicht installierten Plugins", "settings.startup.keep_accessories_desc": "Wenn diese Option aktiviert ist, verbleiben Zubehöre von Plattform-Plugins im Cache, auch wenn das Plugin deinstalliert wird. Dies kann nützlich sein, wenn Sie planen, das Plugin später erneut zu installieren.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startoptionen", "settings.unpair_bridge.load_error": "Gepairte Bridge konnten nicht geladen werden.", "setup.button_get_started": "Los geht's", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index ce56d1811..641482e15 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "All Backups Deleted", "config.title_backup_loaded": "Backup Loaded", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancel", "form.button_close": "Close", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Edit", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine on which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "Homebridge UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on. This must be between 1025 and 65533, and should not be the same as the Homebridge port.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index e4ec03fa9..dfe426529 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Todas las copias de seguridad eliminadas", "config.title_backup_loaded": "Copia de seguridad cargada", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Atrás", "form.button_cancel": "Cancelar", "form.button_close": "Cerrar", @@ -159,7 +160,6 @@ "form.button_download": "Descargar", "form.button_edit": "Editar", "form.button_enable": "Activar", - "form.button_hide": "Ocultar", "form.button_lock": "Bloquear", "form.button_more_info": "Más Información", "form.button_remove": "Eliminar", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Esta Raspberry Pi está reportando una baja de voltaje; por favor, compruebe que está conectada a una fuente de alimentación adecuada. El bajo voltaje puede provocar la inestabilidad del sistema y daños en la tarjeta SD.", "rpi.throttled.previously_message": "Esta Raspberry Pi ha reportado una baja en el voltaje desde que se reinició por última vez; por favor, compruebe que está conectada a una fuente de alimentación adecuada.", "rpi.throttled.undervoltage_title": "Baja de Voltaje", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge mantiene los accesorios en caché para que no sean eliminados y vueltos a añadir a HomeKit cada vez que Homebridge se reinicia. A veces esta caché puede desincronizarse con los accesorios reales en Homebridge.", "settings.cache.title": "Accesorios", "settings.changes.saved": "Tus cambios se han guardado y requieren un reinicio para surtir efecto.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Pantalla", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Difusión mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Si experimentas problemas para conectarte a Homebridge, prueba con alguna de las alternativas de difusión mDNS.", "settings.mdns_advertiser_not_connected": "No Conectado", "settings.mdns_advertiser_rec": "recomendado", - "settings.network.label_interface_name": "Nombre de la Interfaz", - "settings.network.label_ip_address": "Dirección IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Si no se seleccionan interfaces de red, Homebridge intentará determinar automáticamente qué interfaces difundir.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Puerto de Homebridge", "settings.network.port_hb_desc": "El número de puerto en el que se ejecutará el puente Homebridge. Debe estar entre 1025 y 65533, y no debe ser el mismo que el puerto de la interfaz de Homebridge.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "Puerto de la Interfaz", "settings.network.port_ui_desc": "El número de puerto en el que se ejecutará la interfaz de Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Red", "settings.network.title_network_interfaces": "Interfaces de Red", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Error al restablecer el puente.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Algunos plugins requieren que configures la variable DEBUG {{ link }} para habilitar el registro a nivel debug.", "settings.service.node_tooltip": "Opciones de ejecución de Node.js para este proceso. Se recomienda dejar esta sección en blanco a menos que sepas lo que estás haciendo.", "settings.startup.debug": "Modo Debug de Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Para controlar tus accesorios a través de la interfaz de Homebridge, debes ejecutar Homebridge en modo inseguro.", "settings.startup.keep_accessories": "Mantener accesorios de los plugins desinstalados", "settings.startup.keep_accessories_desc": "Si está activado, los accesorios de los plugins de plataforma permanecerán en la caché incluso después de que el plugin sea desinstalado. Esto puede ser útil si planeas reinstalar el plugin más tarde.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opciones de Arranque", "settings.unpair_bridge.load_error": "No se pudieron cargar los puentes emparejados.", "setup.button_get_started": "Empezar", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 4db28522a..20d80a507 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Kaikki varmuuskopiot poistettu", "config.title_backup_loaded": "Varmuuskopio ladattu", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Peru", "form.button_close": "Sulje", @@ -159,7 +160,6 @@ "form.button_download": "Lataa", "form.button_edit": "Muokkaa", "form.button_enable": "Ota käyttöön", - "form.button_hide": "Piilota", "form.button_lock": "Lukitse", "form.button_more_info": "Lisää tietoa", "form.button_remove": "Poista", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi ilmoittaa juuri havainneensa alijännitteen; tarkista, että se on kytketty sopivaan virtalähteeseen. Alijännite voi johtaa järjestelmän epävakauteen ja SD-kortin vioittumiseen.", "rpi.throttled.previously_message": "Raspberry Pi ilmoittaa havainneensa alijännitteen uudelleenkäynnistyksen jälkeenkin; tarkista, että se on kytketty sopivaan virtalähteeseen.", "rpi.throttled.undervoltage_title": "Alijännite", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge säilyttää tietoja laitteista välimuistissa joten niitä ei poisteta ja lisätä uudelleen HomeKit:in joka kerta kun Homebridge käynnistyy uudelleen. Joskus nämä tiedot poikkeavat Homebridgen todellisesta laitteistosta.", "settings.cache.title": "Laitteet", "settings.changes.saved": "Muutokset on tallennettu ja niiden käyttöönotto vaatii uudellenkäynnistyksen.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Näyttö", "settings.general.title_general": "Yleiset", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS mainostaja", "settings.mdns_advertiser_exp": "kokeellinen", "settings.mdns_advertiser_help": "Jos sinulla on ongelmia Homebridgen yhdistämisessä HomeKitiin (kaikki lisävarusteet näyttävät Home-sovelluksessa No Response), yritä käyttää jotakin vaihtoehtoista mDNS-mainostajaa.", "settings.mdns_advertiser_not_connected": "Ei yhdistetty", "settings.mdns_advertiser_rec": "suositeltava", - "settings.network.label_interface_name": "Sovittimen nimi", - "settings.network.label_ip_address": "IP osoite", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Jos verkkosovitinta ei valita, Homebridge yrittää automaattisesti valita sovittimen jota käyttää.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridgen Portti", "settings.network.port_hb_desc": "Homebridgen käyttämän portin numero. On oltava väliltä 1025-65533, ei saa olla sama kuin Homebridge UI:n portti.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "Homebridge UI:n Portti", "settings.network.port_ui_desc": "Homebridge UI:n käyttämän portin numero. On oltava väliltä 1025-65533, ei saa olla sama kuin Homebridgen portti.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Verkkosovitin", "settings.network.title_network_interfaces": "Verkkosovittimet", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Jotkut laajennukset tarvitsevat DEBUG {{ link }} ympäristömuuttujan jotta voivat kirjata debug tason lokitietoja.", "settings.service.node_tooltip": "Node.js ajonaikaiset asetukset tälle prosessille. Jätä tyhjäksi, ellet tiedä mitä olet tekemässä.", "settings.startup.debug": "Homebridge vianhaku tila", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Hallitaksesi laitteitasi Homebridge UI:n kautta Homebridgen on toimittava turvattomassa tilassa.", "settings.startup.keep_accessories": "Pidä poistettujen lisäosien laitteet", "settings.startup.keep_accessories_desc": "Jos valittu, niin laitteiden tiedot säilytetään välimuistissa vaikka siihen liittyvä lisäosa poistetaan. Tästä voi olla hyötyä jos myöhemmin asennat lisäosan uudelleen.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Käynnistäminen ja ympäristö", "settings.unpair_bridge.load_error": "Paritettuja siltoja ei voitu otta käyttöön.", "setup.button_get_started": "Aloitetaan", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 7a6174fc5..2025fa0aa 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Toutes les sauvegardes ont été supprimées", "config.title_backup_loaded": "Sauvegarde chargée", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Annuler", "form.button_close": "Fermer", @@ -159,7 +160,6 @@ "form.button_download": "Télécharger", "form.button_edit": "Modifier", "form.button_enable": "Activer", - "form.button_hide": "Hide", "form.button_lock": "Verrouiller", "form.button_more_info": "Plus d'informations", "form.button_remove": "Supprimer", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Ce Raspberry Pi rencontre actuellement une situation de sous-tension ; Vérifiez qu'il est connecté à une alimentation adaptée. Une sous-tension peut engendrer une instabilité du système et une corruption de sa carte SD.", "rpi.throttled.previously_message": "Ce Raspberry Pi a rencontré une situation de sous-tension depuis son dernier redémarrage ; Vérifiez qu'il est connecté à une alimentation adaptée.", "rpi.throttled.undervoltage_title": "Sous Tension", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "Général", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Diffuseur mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Si vous avez des difficultés à vous connecter à Homebridge, essayez d'utiliser un des diffuseurs mDNS alternatif.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nom de l'Interface", - "settings.network.label_ip_address": "Adresse IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Si aucune interface réseau n'est sélectionnée, Homebridge essaiera de déterminer automatiquement les interfaces à gérer.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Réseau", "settings.network.title_network_interfaces": "Interfaces Réseau", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Certains plugins exigent que vous définissiez la variable d'environnement DEBUG {{ link }} pour activer le niveau de journalisation de débogage.", "settings.service.node_tooltip": "Options d'exécution Node.js pour le processus Homebridge. Ce champ doit rester vide sauf si vous savez ce que vous faites.", "settings.startup.debug": "Mode de débogage Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Conserver les accessoires des plugins non installés", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Options de démarrage", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Démarrer", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index c327c7d5f..1b09924df 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "כל הגיבויים נמחקו", "config.title_backup_loaded": "גיבוי נטען", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "בטל", "form.button_close": "סגור", @@ -159,7 +160,6 @@ "form.button_download": "הורד", "form.button_edit": "ערוך", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "שם ממשק", - "settings.network.label_ip_address": "כתובת איפי", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "רשת", "settings.network.title_network_interfaces": "ממשק רשת", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index 2d8ef7a1a..dbd92a38c 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Minden biztonsági mentés törölve", "config.title_backup_loaded": "Biztonsági mentés visszaállítva", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Mégse", "form.button_close": "Bezár", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Szerkesztés", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 25cc4c68e..e6340fa3c 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Semua Cadangan Dihapus", "config.title_backup_loaded": "Cadangan Dimuat", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Kembali", "form.button_cancel": "Batal", "form.button_close": "Tutup", @@ -159,7 +160,6 @@ "form.button_download": "Unduh", "form.button_edit": "Ubah", "form.button_enable": "Aktifkan", - "form.button_hide": "Sembunyikan", "form.button_lock": "Kunci", "form.button_more_info": "Info Lebih Lanjut", "form.button_remove": "Hapus", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi ini melaporkan saat ini sedang dalam tegangan; Silakan periksa itu terhubung ke catu daya yang sesuai. Di bawah tegangan dapat mengakibatkan ketidakstabilan sistem dan korupsi kartu SD.", "rpi.throttled.previously_message": "Raspberry Pi ini telah melaporkan acara yang kurang tegangan sejak terakhir di-boot ulang; Silakan periksa itu terhubung ke catu daya yang sesuai.", "rpi.throttled.undervoltage_title": "Di bawah tegangan", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge memelihara aksesori dalam cache sehingga tidak dilepas dan ditahan kembali ke HomeKit setiap kali Homebridge restart. Terkadang cache ini bisa tidak selaras dengan aksesori aktual di Homebridge.", "settings.cache.title": "Aksesoris", "settings.changes.saved": "Perubahan Anda telah disimpan dan mengharuskan restart untuk berlaku.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Penampilan", "settings.general.title_general": "Umum", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Pengiklan mDNS", "settings.mdns_advertiser_exp": "Eksperimental", "settings.mdns_advertiser_help": "Jika Anda mengalami masalah saat menghubungkan ke Homebridge, coba gunakan salah satu pengiklan mDNS alternatif.", "settings.mdns_advertiser_not_connected": "Tidak terhubung", "settings.mdns_advertiser_rec": "direkomendasikan", - "settings.network.label_interface_name": "Nama Antarmuka", - "settings.network.label_ip_address": "Alamat IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Jika tidak ada antarmuka jaringan yang terpilih, Homebridge akan mencoba menentukan secara otomatis antarmuka yang akan diumumkan.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Port Homebridge", "settings.network.port_hb_desc": "Nomor port untuk menjalankan Homebridge Bridge menyala.Ini harus antara 1025 dan 65533, dan tidak boleh sama dengan port UI Homebridge.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "Port UI", "settings.network.port_ui_desc": "Nomor port untuk menjalankan Homebridge UI.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Jaringan", "settings.network.title_network_interfaces": "Antarmuka Jaringan", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Gagal mengatur ulang jembatan.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Beberapa plugin mengharuskan Anda untuk mengatur variabel lingkungan debug {{ link }} untuk mengaktifkan pencatatan level debug.", "settings.service.node_tooltip": "Opsi runtime node.js untuk proses ini. Ini harus tetap kosong kecuali Anda tahu apa yang Anda lakukan.", "settings.startup.debug": "Mode Debug Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Untuk mengontrol aksesori Anda melalui Homebridge UI, Anda harus menjalankan Homebridge dalam mode tidak aman.", "settings.startup.keep_accessories": "Simpan aksesoris plugin yang tidak diinstal", "settings.startup.keep_accessories_desc": "Jika diaktifkan, aksesori plugin platform akan tetap berada di cache bahkan setelah plugin tidak diinstal. Ini bisa berguna jika Anda berencana untuk menginstal ulang plugin nanti.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opsi Startup", "settings.unpair_bridge.load_error": "Jembatan berpasangan tidak dapat dimuat.", "setup.button_get_started": "Mulai", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 5065dc54d..b8c5a5882 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Backup eliminati", "config.title_backup_loaded": "Backup caricato", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancella", "form.button_close": "Chiudi", @@ -159,7 +160,6 @@ "form.button_download": "Scarica", "form.button_edit": "Modifica", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Questo Raspberry Pi segnala che la sua tensione di alimentazione è bassa; verificare che sia collegato a un'alimentazione adeguata. Una tensione di alimentazione bassa può causare l'instabilità del sistema e la corruzione della scheda SD.", "rpi.throttled.previously_message": "Questo Raspberry Pi ha segnalato un calo della tensione di alimentazione dall'ultimo riavvio; verificare che sia collegato a un'alimentazione adeguata.", "rpi.throttled.undervoltage_title": "Calo di Tensione", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Annunciatore mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Se stai avendo problemi a collegarti a Homebridge, prova a utilizzare un altro annunciatore mDNS.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nome dell'interfaccia", - "settings.network.label_ip_address": "Indirizzo IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Se nessuna interfaccia di rete è selezionata, Homebridge sceglierà automaticamente su quali annunciarsi.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Rete", "settings.network.title_network_interfaces": "Interfacce di rete", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opzioni di avvio", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Inizia", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 0f994944c..556aadb92 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "バックアップは全て削除されました", "config.title_backup_loaded": "バックアップを読み込みました", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "キャンセル", "form.button_close": "閉じる", @@ -159,7 +160,6 @@ "form.button_download": "ダウンロード", "form.button_edit": "編集", "form.button_enable": "有効化", - "form.button_hide": "Hide", "form.button_lock": "ロック", "form.button_more_info": "詳細情報", "form.button_remove": "削除", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "このRaspberry Piは現在電圧不足であると報告しています。適切な電源に接続されているか確認してください。電圧不足はシステムを不安定にし、SDカードの破損を引き起こす可能性があります。", "rpi.throttled.previously_message": "このRaspberry Piは、最後に再起動してから電圧不足が発生しています。", "rpi.throttled.undervoltage_title": "電圧不足を検出", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS広告主", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Homebridgeへの接続に問題がある場合は、別のmDNS広告主を使用してみてください。", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "インターフェイス名", - "settings.network.label_ip_address": "IPアドレス", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "ネットワークインターフェイスが選択されていない場合、Homebridgeは送受信するインターフェイスを自動的に設定しようとします。", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "ネットワーク", "settings.network.title_network_interfaces": "ネットワークインターフェイス", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "プラグインによっては、デバッグレベルのロギングを有効にするためにDEBUG環境変数を設定する必要があります {{ link }}。", "settings.service.node_tooltip": "HomebridgeプロセスのNode.jsランタイム・オプション。よくわからない場合は、空白のままが良いでしょう。", "settings.startup.debug": "Homebridge デバッグモード", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "未インストールのプラグインのアクセサリーを保管する", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "起動オプション", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "さぁ、始めよう!", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index e8ec9d11f..914bf899e 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "모든 백업을 삭제하였습니다", "config.title_backup_loaded": "백업이 로드되었습니다", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "취소", "form.button_close": "닫기", @@ -159,7 +160,6 @@ "form.button_download": "다운로드", "form.button_edit": "수정", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "이 Raspberry Pi의 전압(Low voltage)이 불안정 합니다. 전압이 낮은경우 시스템이 불안정해지고 SD카드가 손상될 수 있습니다. Pi 버전에 맞게 적절한 전원을 공급 하거나 케이블을 점검 하세요.", "rpi.throttled.previously_message": "마지막 재부팅 이후 Raspberry Pi로 부터 전압 부족 이벤트를 수신하였습니다. Pi 버전에 맞게 적절한 전원을 공급 하거나 케이블을 점검 하세요.", "rpi.throttled.undervoltage_title": "저전압", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge는 액세서리를 캐시에 유지하여 매번 재시작할 때 HomeKit에서 제거되었다가 다시 추가되지 않도록 합니다. 그러나 이 캐시가 실제 Homebridge의 액세서리와 동기화되지 않을 때도 있습니다.", "settings.cache.title": "액세서리", "settings.changes.saved": "변경 사항이 저장되었습니다. 적용하려면 재시작이 필요합니다.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "디스플레이", "settings.general.title_general": "일반", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS 광고자", "settings.mdns_advertiser_exp": "실험적", "settings.mdns_advertiser_help": "Homebridge를 HomeKit에 연결하는 데 문제가 있는 경우(홈 앱에서 모든 액세서리가 '응답 없음'으로 표시되는 경우), 다른 mDNS 광고자를 사용해 보세요.", "settings.mdns_advertiser_not_connected": "연결되지 않음", "settings.mdns_advertiser_rec": "권장", - "settings.network.label_interface_name": "인터페이스 이름", - "settings.network.label_ip_address": "IP 주소", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "네트워크 인터페이스가 선택되지 않으면, Homebridge는 자동으로 발송할 인터페이스 결정합니다.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge 포트", "settings.network.port_hb_desc": "Homebridge Bridge를 실행할 포트 번호입니다. 1025에서 65533 사이여야 하며 Homebridge UI 포트와 동일하지 않아야 합니다.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI 포트", "settings.network.port_ui_desc": "Homebridge UI를 실행할 포트 번호입니다.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "네트워크", "settings.network.title_network_interfaces": "네트워크 인터페이스", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "일부 플러그인은 디버그 수준의 로그를 활성화하려면 DEBUG {{ link }} 환경 변수를 설정해야 합니다.", "settings.service.node_tooltip": "이 프로세스의 Node.js 런타임 옵션입니다. 잘 알고 있는 경우가 아니라면 빈칸으로 두는 것이 좋습니다.", "settings.startup.debug": "Homebridge 디버그 모드", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Homebridge UI를 통해 액세서리를 제어하려면 Homebridge를 비보안 모드에서 실행해야 합니다.", "settings.startup.keep_accessories": "제거된 플러그인의 액세서리 유지", "settings.startup.keep_accessories_desc": "활성화하면, 플랫폼 플러그인의 액세서리는 플러그인을 삭제한 후에도 캐시에 남아 있습니다. 나중에 플러그인을 다시 설치하려는 경우 유용할 수 있습니다.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "시작 옵션", "settings.unpair_bridge.load_error": "페어링된 Bridge를 불러오는 데 실패했습니다.", "setup.button_get_started": "설치 마법사 시작", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index c81c93bbf..a2c217230 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Сите бекапи се избришани", "config.title_backup_loaded": "Вчитан бекап", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Откажи", "form.button_close": "Затвори", @@ -159,7 +160,6 @@ "form.button_download": "Симни", "form.button_edit": "Измени", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Име на интерфејс", - "settings.network.label_ip_address": "IP адреса", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Ако немате одбрано ниеден мрежен интерфејс, Homebridge ќе проба автоматски да одреди на кои интерфејси да испраќа advertisements.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Мрежа", "settings.network.title_network_interfaces": "Мрежни интерфејси", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Опции за стартување", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 0e06449b3..4ff8a4299 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alle backups zijn verwijderd", "config.title_backup_loaded": "Backup Geladen", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Annuleren", "form.button_close": "Sluiten", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Bewerken", "form.button_enable": "Activeren", - "form.button_hide": "Verbergen", "form.button_lock": "Vergrendelen", "form.button_more_info": "Meer Info", "form.button_remove": "Verwijderen", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Deze Raspberry Pi rapporteert een te laag voltage; controleer of verbonden is met een geschikte power supply. Een te laag voltage kan in systeem instabilitei of SD card corruptie veroorzaken.", "rpi.throttled.previously_message": "Deze Raspberry Pi rapporteert een te laag voltage event vanaf de laatste reboot; controleer of verbonden is met een geschikte power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge bewaart accessoires in cache zodat zij niet verwijderd worden en opnieuw toegevoegd aan HomeKit iedere keer dat Homebridge herstart. Soms kan deze cache out of sync raken met de daadwerkelijke accessoires in Homebridge.", "settings.cache.title": "Accessoires", "settings.changes.saved": "Uw wijzigingen zijn opgeslagen en vereisen een herstart om actief te worden.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Scherm", "settings.general.title_general": "Algemeen", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimenteel", "settings.mdns_advertiser_help": "Als U problemen ervaart bij het koppelen met Homebridge, probeer dan een van de alternatieve mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Niet Verbonden", "settings.mdns_advertiser_rec": "aanbevolen", - "settings.network.label_interface_name": "Interface Naam", - "settings.network.label_ip_address": "IP Adres", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Als geen netwerk interfaces geselecteerd zijn, dan zal Homebridge automatisch proberen vast te stellen welke interfaces advertised moeten worden.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Het port nummmer waarop Homebridge bridge moet draaien. Dit moet liggen tussen 1025 en 65533, en mag niet hetzelfde zijn als de Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "Het port number waarop de Homebridge UI moet draaien.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Netwerk", "settings.network.title_network_interfaces": "Netwerk Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Sommige plugins vereisen om de DEBUG environment variabele {{ link }} te configureren om debug level logging te activeren.", "settings.service.node_tooltip": "Node.js runtime opties voor dit proces. Dit moet leeg blijven tenzij je weet wat je doet.", "settings.startup.debug": "Homebridge Debug Modus", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Om accessories via de Homebridge UI te bedienen moet Homebridge in insecure modus opereren.", "settings.startup.keep_accessories": "Bewaar Accessoires Van gedeïnstalleerde Plugins", "settings.startup.keep_accessories_desc": "Indine geactiveerd, zullen accessoires van platform plugins in cache bewaard blijven ook als de plugin is gedeïnstalleerd. Dit kan handig zijn als U van plan bent de plugin later opnieuw te installeren.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup Opties", "settings.unpair_bridge.load_error": "Gekoppelde bridges konden niet geladen worden.", "setup.button_get_started": "Beginnen", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index e4ab789ba..d14d44f0a 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alle sikkerhetskopier slettet", "config.title_backup_loaded": "Backup lastet", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Avbryt", "form.button_close": "Lukk", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Rediger", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Interface Name", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "If no network interfaces are selected, Homebridge will attempt to automatically determine which interfaces to advertise.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Network", "settings.network.title_network_interfaces": "Network Interfaces", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startup & Environment", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index fd40ddf54..a9867b328 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Wszystkie kopie zapasowe zostały usunięte", "config.title_backup_loaded": "Backup został załadowany", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Anuluj", "form.button_close": "Zamknij", @@ -159,7 +160,6 @@ "form.button_download": "Pobierz", "form.button_edit": "Edytuj", "form.button_enable": "Włącz", - "form.button_hide": "Ukryj", "form.button_lock": "Zablokuj", "form.button_more_info": "Więcej info", "form.button_remove": "Usuń", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi zgłasza aktualnie za niskie napięcie - sprawdź czy jest zasilane z odpowiedniego zasilacza. Zbyt niskie napięcie może powodować niestabilną prace i uszkodzić kartę SD.", "rpi.throttled.previously_message": "Raspberry Pi zgłaszało zbyt niskie napięcie od ostatniego uruchomienia - sprawdź czy jest zasilane z odpowiedniego zasilacza.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge utrzymuje pamięć podręczną z informacjami o akcesoriach aby nie były one usuwane i ponownie dodawane do HomeKit za każdym razem gdy Homebridge uruchamia się ponownie. Czasami pamięć podręczna może stać się niezsynchronizowana z rzeczywistymi akcesoriami w Homebridge.", "settings.cache.title": "Akcesoria", "settings.changes.saved": "Twoje zmiany zostały zapisane i wymagają ponownego uruchomienia.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Wygląd", "settings.general.title_general": "Ogólne", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Rozgłaszacz mDNS", "settings.mdns_advertiser_exp": "eksperymentalny", "settings.mdns_advertiser_help": "Jeśli masz problem z połączeniem Homebridge do HomeKit, spróbuj użyć alternatywnego rozgłaszania mDNS.", "settings.mdns_advertiser_not_connected": "Rozłączony", "settings.mdns_advertiser_rec": "zalecane", - "settings.network.label_interface_name": "Nazwa interfejsu", - "settings.network.label_ip_address": "Adres IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Jeśli żaden interfejs nie zostanie wybrany, Homebridge wybierze automatycznie.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "Port Homebridge. Musi być między 1025 a 65533 i nie powinien być taki sam jak port Homebridge UI.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "Port Homebridge UI. Nie powinien być taki sam jak port Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Sieć", "settings.network.title_network_interfaces": "Interfejsy sieciowe", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Niektóre wtyczki wymagają ustawienia zmiennej środowiskowej DEBUG {{ link }} aby umożliwić rejestrowanie poziomu debugowania.", "settings.service.node_tooltip": "Opcje uruchomieniowe Node.js dla procesu Homebridge. To pole powinno być puste, chyba że wiesz co robisz.", "settings.startup.debug": "Tryb Homebridge Debug", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Aby sterować akcesoriami za pomocą interfejsu użytkownika Homebridge, musisz uruchomić Homebridge w trybie niezabezpieczonym (Insecure).", "settings.startup.keep_accessories": "Zachowaj akcesoria odinstalowanych wtyczek", "settings.startup.keep_accessories_desc": "Akcesoria wtyczek (tych typu platform) pozostaną w pamięci podręcznej nawet po odinstalowaniu wtyczki. Może to być przydatne jeśli planujesz ponownie zainstalować wtyczkę w przyszłości.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opcje specjalne", "settings.unpair_bridge.load_error": "Nie można było załadować sparowanych mostków.", "setup.button_get_started": "Rozpocznij", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 4e35f1a73..ad637e71c 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Todos os backups foram removidos", "config.title_backup_loaded": "Backup Carregado", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancelar", "form.button_close": "Fechar", @@ -159,7 +160,6 @@ "form.button_download": "Download", "form.button_edit": "Editar", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Subtensão", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Anunciante mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Se você está tendo problemas ao conectar com o Homebridge, tente usar um dos anunciantes mDNS alternativos.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nome da Interface", - "settings.network.label_ip_address": "Endereço IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Se nenhuma interface de rede for selecionada, Homebridge tentará determinar automaticamente qual interface irá utilizar.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Rede", "settings.network.title_network_interfaces": "Interfaces de Rede", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opções de Inicialização", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 887c6e296..2a829e7bf 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Eliminados Todos os Backups", "config.title_backup_loaded": "Backup Carregado", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Cancelar", "form.button_close": "Fechar", @@ -159,7 +160,6 @@ "form.button_download": "Descarregar", "form.button_edit": "Editar", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Este Raspberry Pi está a reportar que se encontra atualmente em subtensão; por favor verifique se está conectado a uma fonte de alimentação apropriada. Subtensão poderá provocar instabilidade de sistema e corromper o cartão SD.", "rpi.throttled.previously_message": "Este Raspberry Pi reportou um evento de subtensão desde a ultima inicialização; por favor verifique se está conectado a uma fonte de alimentação apropriada.", "rpi.throttled.undervoltage_title": "Subtensão", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Encaminhamento mDNS", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Se estiver a ter problemas a conectar ao Homebridge, tente um dos encaminhamentos mDNS alternativos.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Nome da Interface", - "settings.network.label_ip_address": "Endereço IP", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Se nenhuma interface de rede estiver selecionada, o Homebridge irá tentar determinar automaticamente qual interface a utilizar.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Rede", "settings.network.title_network_interfaces": "Interfaces de Rede", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Opções de Inicio", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Começar", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index 3976f41f4..70f9c3148 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Все резервные копии удалены", "config.title_backup_loaded": "Резервная копия загружена", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Назад", "form.button_cancel": "Отмена", "form.button_close": "Закрыть", @@ -159,7 +160,6 @@ "form.button_download": "Скачать", "form.button_edit": "Редактировать", "form.button_enable": "Включить", - "form.button_hide": "Скрыть", "form.button_lock": "Заблокировать", "form.button_more_info": "Дополнительная информация", "form.button_remove": "Удалить", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Этот Raspberry Pi сообщает о текущем пониженном напряжении; проверьте подключение к подходящему источнику питания. Недостаточное питание может привести к нестабильной работе системы и повреждению SD-карты.", "rpi.throttled.previously_message": "Этот Raspberry Pi зафиксировал событие пониженного напряжения с момента последней перезагрузки; проверьте подключение к подходящему источнику питания.", "rpi.throttled.undervoltage_title": "Пониженное напряжение", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge хранит аксессуары в кэше, чтобы они не удалялись и не добавлялись заново в HomeKit при каждом перезапуске Homebridge. Иногда кэш может стать несогласованным с реальными аксессуарами в Homebridge.", "settings.cache.title": "Аксессуары", "settings.changes.saved": "Ваши изменения сохранены. Для вступления в силу требуется перезапуск.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Отображение", "settings.general.title_general": "Основные", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Рекламодатель mDNS", "settings.mdns_advertiser_exp": "экспериментально", "settings.mdns_advertiser_help": "Если у вас возникают проблемы с подключением Homebridge к HomeKit (все аксессуары отображаются как 'Нет ответа' в приложении Дом), попробуйте использовать альтернативного рекламодателя mDNS.", "settings.mdns_advertiser_not_connected": "Нет подключения", "settings.mdns_advertiser_rec": "рекомендуется", - "settings.network.label_interface_name": "Имя интерфейса", - "settings.network.label_ip_address": "IP-адрес", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Если ни один сетевой интерфейс не выбран, Homebridge попытается определить интерфейсы для рекламы автоматически.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Порт Homebridge", "settings.network.port_hb_desc": "Номер порта, на котором работает мост Homebridge. Диапазон допустимых значений — от 1025 до 65533. Порт не должен совпадать с портом интерфейса Homebridge UI.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "Порт Homebridge UI", "settings.network.port_ui_desc": "Номер порта, на котором работает интерфейс Homebridge UI. Диапазон допустимых значений — от 1025 до 65533. Порт не должен совпадать с портом Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Сеть", "settings.network.title_network_interfaces": "Сетевые интерфейсы", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Не удалось сбросить мост.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Некоторые плагины требуют установки переменной окружения DEBUG {{ link }} для включения журналирования отладки.", "settings.service.node_tooltip": "Параметры выполнения среды Node.js для этого процесса. Оставьте поле пустым, если вы не уверены, что делаете.", "settings.startup.debug": "Режим отладки Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Для управления вашими аксессуарами через Homebridge UI необходимо запустить Homebridge в небезопасном режиме.", "settings.startup.keep_accessories": "Сохранять аксессуары удалённых плагинов", "settings.startup.keep_accessories_desc": "Если включено, аксессуары платформенных плагинов останутся в кэше даже после удаления плагина. Это может быть полезно, если вы планируете переустановить плагин позже.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Параметры запуска и окружения", "settings.unpair_bridge.load_error": "Не удалось загрузить привязанные мосты.", "setup.button_get_started": "Начать работу", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index da7199576..d16684df4 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Vse varnostne kopije so izbrisane", "config.title_backup_loaded": "Varnostna kopija naložena", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Prekini", "form.button_close": "zapri", @@ -159,7 +160,6 @@ "form.button_download": "Prenesi", "form.button_edit": "Uredi", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS oglaševalec", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Če imate težave s povezovanjem z Homebridgeom, poskusite uporabiti enega od nadomestnih oglaševalcev mDNS.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Ime vmesnika", - "settings.network.label_ip_address": "IP naslov", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Če ni izbran noben omrežni vmesnik, bo Homebridge poskušal samodejno določiti, katere vmesnike oglaševati.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Omrežje", "settings.network.title_network_interfaces": "Omrežni vmesniki", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Možnosti zagona", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index 312cbac57..b7224c400 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Alla säkerhetskopior raderade", "config.title_backup_loaded": "Säkerhetskopia återställd", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "Avbryt", "form.button_close": "Stäng", @@ -159,7 +160,6 @@ "form.button_download": "Ladda ner", "form.button_edit": "Redigera", "form.button_enable": "Aktivera", - "form.button_hide": "Dölj", "form.button_lock": "Lås", "form.button_more_info": "Mer info", "form.button_remove": "Ta bort", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Denna Raspberry Pi rapporterar att det för närvarande är underspänning; kontrollera att den är ansluten till en lämplig strömkälla. Underspänning kan resultera i systeminstabilitet och skada på SD-kortet.", "rpi.throttled.previously_message": "Denna Raspberry Pi har rapporterat en underspänningshändelse sedan den startades om senast; kontrollera att den är ansluten till en lämplig strömkälla.", "rpi.throttled.undervoltage_title": "Underspänning", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "Allmänt", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS-annonsör", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "Om du har problem med att ansluta till Homebridge, prova att använda någon av de alternativa mDNS-annonsörerna.", "settings.mdns_advertiser_not_connected": "Ej ansluten", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Gränssnittsnamn", - "settings.network.label_ip_address": "IP-adress", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Om inga nätverksgränssnitt väljs kommer Homebridge att försöka avgöra vilka gränssnitt som ska annonseras automatiskt.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Nätverk", "settings.network.title_network_interfaces": "Nätverksgränssnitt", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Vissa plugins kräver att du sätter miljövariabeln DEBUG {{ link }} för att aktivera debug-loggning.", "settings.service.node_tooltip": "Node.js runtime-alternativ för den här processen. Denna bör vara tom om du inte vet vad du gör.", "settings.startup.debug": "Homebridge Debug-läge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Behåll tillbehör till avinstallerade plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Startalternativ", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Kom igång", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index acb9984a2..ad4cdf576 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "ลบข้อมูลสำรองทั้งหมดแล้ว", "config.title_backup_loaded": "โหลดข้อมูลสำรองแล้ว", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "ย้่อนกลับ", "form.button_cancel": "ยกเลิก", "form.button_close": "ปิด", @@ -159,7 +160,6 @@ "form.button_download": "ดาวน์โหลด", "form.button_edit": "แก้ไข", "form.button_enable": "เปิดการใช้งาน", - "form.button_hide": "ซ่อน", "form.button_lock": "ล๊อค", "form.button_more_info": "ข้อมูลเพิ่มเติม", "form.button_remove": "ลบ", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Raspberry Pi นี้กำลังรายงานว่าปัจจุบันมีแรงดันไฟฟ้าต่ำ โปรดตรวจสอบว่าได้เชื่อมต่อกับแหล่งจ่ายไฟที่เหมาะสมแล้ว แรงดันไฟต่ำอาจส่งผลให้ระบบไม่เสถียรและการ์ด SD เสียหาย", "rpi.throttled.previously_message": "Raspberry Pi นี้รายงานเหตุการณ์ที่มีแรงดันไฟฟ้าต่ำตั้งแต่มีการรีบูตครั้งล่าสุด โปรดตรวจสอบว่าได้เชื่อมต่อกับแหล่งจ่ายไฟที่เหมาะสมแล้ว", "rpi.throttled.undervoltage_title": "ตรวจพบแรงดันไฟฟ้าต่ำ", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge จะเก็บอุปกรณ์เสริมไว้ในแคช เพื่อไม่ให้อุปกรณ์เสริมเหล่านั้นถูกลบออกและเพิ่มกลับเข้าไปใน HomeKit ทุกครั้งที่รีสตาร์ท Homebridge บางครั้งแคชนี้อาจไม่ซิงค์กับอุปกรณ์เสริมจริงใน Homebridge", "settings.cache.title": "อุปกรณ์เสริม", "settings.changes.saved": "การเปลี่ยนแปลงของคุณได้รับการบันทึกแล้วและต้องรีสตาร์ทจึงจะมีผล.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "การแดงผล", "settings.general.title_general": "ทั่วไป", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "การทดลอง", "settings.mdns_advertiser_help": "หากคุณประสบปัญหาในการเชื่อมต่อกับ Homebridge ให้ลองใช้ mDNS รายใดรายหนึ่ง.", "settings.mdns_advertiser_not_connected": "ไม่ได้เชื่อมต่อ", "settings.mdns_advertiser_rec": "ที่แนะนำ", - "settings.network.label_interface_name": "ชื่ออินเทอร์เฟซ", - "settings.network.label_ip_address": "IP Address", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "หากไม่ได้เลือกอินเทอร์เฟซเครือข่าย Homebridge จะพยายามกำหนดโดยอัตโนมัติว่าจะใช้อินเทอร์เฟซใด", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "พอร์ต Homebridge", "settings.network.port_hb_desc": "หมายเลขพอร์ตที่จะเรียกใช้ Homebridge bridge ต้องอยู่ระหว่าง 1025 ถึง 65533 และไม่ควรเป็นหมายเลขเดียวกับพอร์ต Homebridge UI", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "พอร์ต UI", "settings.network.port_ui_desc": "หมายเลขพอร์ตที่จะรัน Homebridge UI", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "เครือข่าย", "settings.network.title_network_interfaces": "การเชื่อมต่อเครือข่าย", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "การรีเซ็ตบริดจ์ล้มเหลว", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "ปลั๊กอินบางตัวต้องการให้คุณตั้งค่าตัวแปรสภาพแวดล้อม DEBUG {{ link }} เพื่อเปิดใช้งานการบันทึกระดับการดีบัก", "settings.service.node_tooltip": "ตัวเลือกรันไทม์ Node.js สำหรับกระบวนการ Homebridge ควรเว้นว่างไว้ ยกเว้นแต่คุณจะรู้ว่าคุณกำลังทำอะไรอยู่", "settings.startup.debug": "โหมด Debug Homebridge", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "หากต้องการควบคุมอุปกรณ์เสริมของคุณผ่าน Homebridge UI คุณต้องใช้งาน Homebridge ในโหมดไม่ปลอดภัย", "settings.startup.keep_accessories": "เก็บอุปกรณ์เสริมของปลั๊กอินที่ถอนการติดตั้งไว้", "settings.startup.keep_accessories_desc": "หากเปิดใช้งาน อุปกรณ์เสริมของปลั๊กอินแพลตฟอร์มจะยังคงอยู่ในแคชแม้ว่าจะถอนการติดตั้งปลั๊กอินแล้วก็ตาม ซึ่งอาจมีประโยชน์หากคุณวางแผนจะติดตั้งปลั๊กอินใหม่ในภายหลัง", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "ตัวเลือกการเริ่มต้น", "settings.unpair_bridge.load_error": "บริดจ์จับคู่ไม่สามารถโหลดได้", "setup.button_get_started": "เริ่ม", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index 2988dbbc8..7600524e9 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Tüm Yedeklemeler Silindi", "config.title_backup_loaded": "Yedekleme Yüklendi", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "İptal Et", "form.button_close": "Kapat", @@ -159,7 +160,6 @@ "form.button_download": "İndir", "form.button_edit": "Düzenle", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "If you have trouble connecting Homebridge to HomeKit (all accessories showing 'No Response' in the Home app), try using one of the alternate mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "Arayüz Adı", - "settings.network.label_ip_address": "IP Adresi", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Eğer herhangi bir ağ arayüzü seçilmezse, Homebridge otomatik olarak yayın yapması gereken arayüzü tesip etmeyi deneyecektir.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Ağ", "settings.network.title_network_interfaces": "Ağ Arayüzleri", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Başlangıç Seçenekleri", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 43693817e..11e730bab 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "Всі резервні копії видалено", "config.title_backup_loaded": "Резервна копія завантажена", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Назад", "form.button_cancel": "Відмінити", "form.button_close": "Закрити", @@ -159,7 +160,6 @@ "form.button_download": "Завантажити", "form.button_edit": "Редагувати", "form.button_enable": "Увімкнути", - "form.button_hide": "Приховати", "form.button_lock": "Заблокувати", "form.button_more_info": "Більше інформації", "form.button_remove": "Видалити", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "Цей Raspberry Pi повідомляє, що зараз він перебуває під низькою напругою. Переконайтеся, що він під'єднаний до відповідного джерела живлення. Низька напруга може призвести до нестабільності системи та пошкодження SD-карти.", "rpi.throttled.previously_message": "Цей Raspberry Pi повідомив про подію низької напруги з моменту останнього перезавантаження. Будь ласка, перевірте, чи під’єднано його до відповідного джерела живлення.", "rpi.throttled.undervoltage_title": "Низька Напруга", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge зберігає аксесуари в кеш-пам’яті, тому вони не видаляються та не додаються повторно до HomeKit кожного разу, коли Homebridge перезапускається. Іноді цей кеш може не синхронізуватися з фактичними аксесуарами в Homebridge.", "settings.cache.title": "Аксесуари", "settings.changes.saved": "Ваші зміни збережено. Щоб вони набрали чинності, потрібно перезавантажити.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Дисплей", "settings.general.title_general": "Загальні", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "Рекламіст mDNS", "settings.mdns_advertiser_exp": "експериментальний", "settings.mdns_advertiser_help": "Якщо у Вас виникли проблеми з підключенням до Homebridge, спробуйте скористатися одним із альтернативних рекламвстів mDNS.", "settings.mdns_advertiser_not_connected": "Не з'єднано", "settings.mdns_advertiser_rec": "рекомендований", - "settings.network.label_interface_name": "Назва інтерфейсу", - "settings.network.label_ip_address": "IP Адреса", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "Якщо не обрано жодного мережевого інтерфейсу, Homebridge спробує автоматично визначити, які інтерфейси рекламувати.", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge порт", "settings.network.port_hb_desc": "Номер порту для запуску мосту Homebridge. Він має бути між 1025 і 65533 і не повинен збігатися з портом інтерфейсу користувача Homebridge.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI порт", "settings.network.port_ui_desc": "Номер порту для запуску UI Homebridge.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "Мережа", "settings.network.title_network_interfaces": "Інтерфейс мережі", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Не вдалося скинути міст.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Деякі плагіни вимагають встановлення змінного середовища DEBUG {{ link }}, щоб увімкнути ведення журналу на рівні налагодження.", "settings.service.node_tooltip": "Параметри середовища виконання Node.js для процесу Homebridge. Це має бути пустим, якщо Ви не знаєте, що робите.", "settings.startup.debug": "Homebridge режим «Налагодження»", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "Щоб керувати аксесуарами через UI Homebridge, необхідно запустити Homebridge у незахищеному режимі.", "settings.startup.keep_accessories": "Зберігайте аксесуари видалених плагінів", "settings.startup.keep_accessories_desc": "Якщо ввімкнено, аксесуари плагінів платформи залишатимуться в кеші навіть після видалення плагіна. Це може бути корисним, якщо Ви плануєте перевстановити плагін пізніше.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "Пареметри запуску", "settings.unpair_bridge.load_error": "Не вдалося завантажити парні мости.", "setup.button_get_started": "Розпочати", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 00b3af8b3..dc493ced4 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "所有备份已删除", "config.title_backup_loaded": "已载入备份", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "取消", "form.button_close": "关闭", @@ -159,7 +160,6 @@ "form.button_download": "下载", "form.button_edit": "编辑", "form.button_enable": "Enable", - "form.button_hide": "Hide", "form.button_lock": "Lock", "form.button_more_info": "More Info", "form.button_remove": "Remove", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "如果你无法链接到 Homebridge, 请尝试更换 mDNS advertisers.", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "端口名称", - "settings.network.label_ip_address": "IP 地址", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "如果没有网络端口被选中, Homebridge 将会尝试自动搜索端口并广播。", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "网络", "settings.network.title_network_interfaces": "网络端口", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "启动选项", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index a6c0f76ad..61b4b666f 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -151,6 +151,7 @@ "config.restore.toast_backups_deleted": "已刪除所有備份", "config.title_backup_loaded": "已讀取備份", "form.auto_save": "Changes are automatically saved.", + "form.button_allow": "Allow", "form.button_back": "Back", "form.button_cancel": "取消", "form.button_close": "關閉", @@ -159,7 +160,6 @@ "form.button_download": "下載", "form.button_edit": "編輯", "form.button_enable": "啟用", - "form.button_hide": "隱藏", "form.button_lock": "上鎖", "form.button_more_info": "更多資訊", "form.button_remove": "移除", @@ -382,6 +382,8 @@ "rpi.throttled.currently_message": "This Raspberry Pi is reporting it is currently under-voltage; please check it is connected to an appropriate power supply. Under-voltage can result in system instability and SD card corruption.", "rpi.throttled.previously_message": "This Raspberry Pi has reported an under-voltage event since it was last rebooted; please check it is connected to an appropriate power supply.", "rpi.throttled.undervoltage_title": "Under Voltage", + "settings.accessory.debug": "Accessory Debug Mode", + "settings.accessory.debug_desc": "If enabled, the Homebridge UI will log debug level messages to the console.", "settings.cache.desc": "Homebridge maintains accessories in cache so they aren't removed and re-added to HomeKit each time Homebridge restarts. Sometimes this cache can become out of sync with the actual accessories in Homebridge.", "settings.cache.title": "Accessories", "settings.changes.saved": "Your changes have been saved and require a restart to take effect.", @@ -417,21 +419,50 @@ "settings.display.wallpaper_success": "Wallpaper was successfully updated.", "settings.general.title_display": "Display", "settings.general.title_general": "General", + "settings.linux.restart": "Restart Command", + "settings.linux.restart_desc": "If no restart command is set the process will terminate with a non-zero exit code.", + "settings.linux.shutdown": "Shutdown Command", + "settings.linux.shutdown_desc": "If no shutdown command is set the process will terminate with a non-zero exit code.", + "settings.linux.temp": "Temperature File Path", + "settings.linux.temp_desc": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temperature file here. This will display the current temperature on the UI status page.", "settings.mdns_advertiser": "mDNS Advertiser", "settings.mdns_advertiser_exp": "experimental", "settings.mdns_advertiser_help": "假如於連線 Homebridge 時遇到問題,請試著使用替代的 mDNS Advertiser。", "settings.mdns_advertiser_not_connected": "Not Connected", "settings.mdns_advertiser_rec": "recommended", - "settings.network.label_interface_name": "介面名稱", - "settings.network.label_ip_address": "IP 位址", + "settings.name": "Homebridge Name", + "settings.network.hb_package": "Homebridge Module Path", + "settings.network.hb_package_desc": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", + "settings.network.host": "Host IP Address", + "settings.network.host_desc": "The host IP address to listen on. In most cases this will be :: or 0.0.0.0.", "settings.network.message_network_interface": "如果沒有選擇網路介面,Homebridge 將會自動偵測所要使用的網路介面。", + "settings.network.port_end": "End Port", + "settings.network.port_end_desc": "Control the end of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and more than the start port above.", "settings.network.port_hb": "Homebridge Port", "settings.network.port_hb_desc": "The port number to run the Homebridge bridge on. This must be between 1025 and 65533, and should not be the same as the Homebridge UI port.", + "settings.network.port_start": "Start Port", + "settings.network.port_start_desc": "Control the start of the range of ports that separate accessories (like camera or television) should run on. This must be between 1025 and 65533, and less than the end port below.", "settings.network.port_ui": "UI Port", "settings.network.port_ui_desc": "The port number to run the Homebridge UI on.", + "settings.network.proxy": "Reverse Proxy Hostname", + "settings.network.proxy_desc": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI.", "settings.network.title_network": "網路", "settings.network.title_network_interfaces": "網路介面", + "settings.network.title_security": "Security", "settings.reset_bridge.error": "Failed to reset bridge.", + "settings.security.auth": "Authentication", + "settings.security.auth_desc": "Whether to enable authentication for the Homebridge UI with a username and password.", + "settings.security.cert": "Certificate Path", + "settings.security.https": "Enable HTTPS", + "settings.security.https_desc": "Enable HTTPS by providing your own certificate files stored on your Homebridge server.", + "settings.security.https_keycert": "Private Key + Certificate", + "settings.security.https_pfx": "PKCS#12 Certificate + Passphrase", + "settings.security.key": "Private Key Path", + "settings.security.pass": "PKCS#12 Certificate Passphrase", + "settings.security.pfx": "PKCS#12 Certificate Path", + "settings.security.ui_control": "Accessory Control Lists", + "settings.security.ui_control_desc": "Define which bridges and bridged accessories can be controlled or blocked by the Homebridge UI.", + "settings.security.ui_control_desc_2": "Allow the UI to control the accessories on a bridge by toggling on the switch below.", "settings.service.debug_tooltip": "Some plugins require you to set the DEBUG environment variable {{ link }} to enable debug level logging.", "settings.service.node_tooltip": "Node.js runtime options for this process. This should be kept blank unless you know what you are doing.", "settings.startup.debug": "Homebridge Debug Mode", @@ -441,6 +472,14 @@ "settings.startup.insecure_desc": "To control your accessories via the Homebridge UI you must be running Homebridge in insecure mode.", "settings.startup.keep_accessories": "Keep Accessories Of Uninstalled Plugins", "settings.startup.keep_accessories_desc": "If enabled, accessories of platform plugins will remain in the cache even after the plugin is uninstalled. This can be useful if you plan to reinstall the plugin later.", + "settings.startup.log_max": "Log Max Size", + "settings.startup.log_max_desc": "The max log size (bytes). Set to -1 to disable log truncation.", + "settings.startup.log_truncate": "Log Truncate Size", + "settings.startup.log_truncate_desc": "The size (bytes) to truncate the log to once it goes over the max size specified above.", + "settings.startup.metrics": "Enable Server Metric Monitoring", + "settings.startup.metrics_desc": "When enabled, the Homebridge UI will collect and show CPU and memory stats on the status page.", + "settings.startup.session": "Session Timeout", + "settings.startup.session_desc": "The number of seconds before a user will be logged out of the UI. Defaults to 8 hours.", "settings.title_startup_options": "啟動選項", "settings.unpair_bridge.load_error": "Paired bridges could not be loaded.", "setup.button_get_started": "Get Started", From ed8e360bd0a3218f8636131e5a5bb8e7ada7c7b9 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 15 Jun 2025 05:33:43 +0100 Subject: [PATCH 07/22] add support for `uiSchema` within plugin configurations --- CHANGELOG.md | 1 + .../app/core/components/schema-form/schema-form.component.html | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12adc8faa..c68ea3ab7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - style HBv2/UIv5 icons on status page based on readiness - security system modal only show valid modes - refactor settings page with immediate saving +- add support for `uiSchema` within plugin configurations ### Homebridge Dependencies diff --git a/ui/src/app/core/components/schema-form/schema-form.component.html b/ui/src/app/core/components/schema-form/schema-form.component.html index ab8feed2b..462b7b0f1 100644 --- a/ui/src/app/core/components/schema-form/schema-form.component.html +++ b/ui/src/app/core/components/schema-form/schema-form.component.html @@ -4,6 +4,7 @@ [jsfPatch]="configSchema.fixArrays" [options]="jsonFormOptions" [schema]="configSchema.schema" + [UISchema]="configSchema.uiSchema" [layout]="configSchema.layout" [form]="configSchema.form" [data]="currentData" From 9f20633505a07bc258d3ae09723bf91830cd279e Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 15 Jun 2025 12:20:08 +0100 Subject: [PATCH 08/22] add option to hide update notifications for specific plugins --- CHANGELOG.md | 1 + config.schema.json | 17 +++++++ src/core/config/config.service.ts | 6 +++ .../config-editor/config-editor.controller.ts | 9 ++++ .../config-editor/config-editor.service.ts | 21 ++++++++ .../manage-plugin/manage-plugin.component.ts | 2 +- .../manage-version.component.html | 21 ++++++++ .../manage-version.component.ts | 39 +++++++++++++- ui/src/app/core/settings.service.ts | 3 ++ .../app/modules/plugins/plugins.component.ts | 51 +++++++++++++------ .../update-info-widget.component.ts | 3 +- ui/src/i18n/bg.json | 2 + ui/src/i18n/ca.json | 2 + ui/src/i18n/cs.json | 2 + ui/src/i18n/de.json | 2 + ui/src/i18n/en.json | 2 + ui/src/i18n/es.json | 2 + ui/src/i18n/fi.json | 2 + ui/src/i18n/fr.json | 2 + ui/src/i18n/he.json | 2 + ui/src/i18n/hu.json | 2 + ui/src/i18n/id.json | 2 + ui/src/i18n/it.json | 2 + ui/src/i18n/ja.json | 2 + ui/src/i18n/ko.json | 2 + ui/src/i18n/mk.json | 2 + ui/src/i18n/nl.json | 2 + ui/src/i18n/no.json | 2 + ui/src/i18n/pl.json | 2 + ui/src/i18n/pt-BR.json | 2 + ui/src/i18n/pt.json | 2 + ui/src/i18n/ru.json | 2 + ui/src/i18n/sl.json | 2 + ui/src/i18n/sv.json | 2 + ui/src/i18n/th.json | 2 + ui/src/i18n/tr.json | 2 + ui/src/i18n/uk.json | 2 + ui/src/i18n/zh-CN.json | 2 + ui/src/i18n/zh-TW.json | 2 + 39 files changed, 211 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c68ea3ab7..32e314428 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - security system modal only show valid modes - refactor settings page with immediate saving - add support for `uiSchema` within plugin configurations +- add option to hide update notifications for specific plugins ### Homebridge Dependencies diff --git a/config.schema.json b/config.schema.json index 809c11f6e..da6edc5ce 100644 --- a/config.schema.json +++ b/config.schema.json @@ -633,6 +633,23 @@ "title": "Disable Server Metrics Monitoring", "type": "boolean", "description": "When enabled, the Homebridge UI will not collect or report CPU or memory stats." + }, + "plugins": { + "title": "Plugins", + "type": "object", + "description": "Settings surrounding plugins used by the Homebridge UI.", + "properties": { + "hideUpdatesFor": { + "type": "array", + "title": "Hide Plugin Updates For", + "description": "A list of plugin names for which frontend update notifications will be hidden.", + "items": { + "type": "string", + "title": "Plugin Name", + "pattern": "^(?:[A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$" + } + } + } } } }, diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index eeaa89b0f..dbe9e73a2 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -107,6 +107,9 @@ export class ConfigService { debug?: boolean instanceBlacklist?: string[] } + plugins?: { + hideUpdatesFor?: string[] + } temp?: string tempUnits?: string wallpaper?: string @@ -253,6 +256,9 @@ export class ConfigService { debug: this.ui.accessoryControl?.debug, instanceBlacklist: this.ui.accessoryControl?.instanceBlacklist || [], }, + plugins: { + hideUpdatesFor: this.ui.plugins?.hideUpdatesFor || [], + }, linux: { shutdown: this.ui.linux?.shutdown, restart: this.ui.linux?.restart, diff --git a/src/modules/config-editor/config-editor.controller.ts b/src/modules/config-editor/config-editor.controller.ts index 2c29ff8dd..b9ef4af75 100644 --- a/src/modules/config-editor/config-editor.controller.ts +++ b/src/modules/config-editor/config-editor.controller.ts @@ -102,6 +102,15 @@ export class ConfigEditorController { return this.configEditorService.setAccessoryControlInstanceBlacklist(body) } + @UseGuards(AdminGuard) + @Put('/ui/plugins/hide-updates-for') + @ApiOperation({ summary: 'Update the plugins hide updates for.' }) + @ApiBody({ description: 'Array of plugin names to hide updates for in the UI.', type: 'json', isArray: true }) + @Put() + setPluginsHideUpdatesFor(@Body() { body }) { + return this.configEditorService.setPluginsHideUpdatesFor(body) + } + @UseGuards(AdminGuard) @ApiOperation({ summary: 'List the available Homebridge `config.json` backups.' }) @Get('/backups') diff --git a/src/modules/config-editor/config-editor.service.ts b/src/modules/config-editor/config-editor.service.ts index 06b445eac..c4de83543 100644 --- a/src/modules/config-editor/config-editor.service.ts +++ b/src/modules/config-editor/config-editor.service.ts @@ -358,6 +358,27 @@ export class ConfigEditorService { await this.updateConfigFile(config) } + /** + * Set the plugin hide update list (this request is not partial) + */ + public async setPluginsHideUpdatesFor(value: string[]) { + // 1. Get the current config for the Homebridge UI + const config = await this.getConfigFile() + const pluginConfig = config.platforms.find(x => x.platform === 'config') + + // 2. Ensure the plugins object exists and set the hideUpdatesFor property + if (!pluginConfig.plugins) { + pluginConfig.plugins = {} + } + pluginConfig.plugins.hideUpdatesFor = (value || []) + .filter(x => typeof x === 'string' && x.trim() !== '' && /^(?:@[\w-]+(?:\.[\w-]+)*\/)?homebridge-[\w-]+$/i.test(x.trim())) + .map(x => x.trim().toLowerCase()) + + // 3. Clean and save the UI config block + config.platforms[config.platforms.findIndex(x => x.platform === 'config')] = this.cleanUpUiConfig(pluginConfig) + await this.updateConfigFile(config) + } + /** * Mark a plugin as disabled */ diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts index 24649bd89..247349580 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.ts @@ -145,7 +145,7 @@ export class ManagePluginComponent implements OnInit, OnDestroy { next: () => { this.$activeModal.close() this.$toastr.success(`${this.pastTenseVerb} ${this.pluginName}`, this.toastSuccess) - window.location.href = `/plugins?installed=${this.pluginName}` + window.location.href = `/plugins?action=just-installed&plugin=${this.pluginName}` }, error: (error) => { this.actionFailed = true diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html index dcead1d7d..86fa7e32d 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.html @@ -76,6 +76,27 @@
    {{ 'plugins.manage.select_version' | translate }}
    } + + @if (plugin.installedVersion && !['homebridge', 'homebridge-config-ui-x'].includes(plugin.name)) { + + } } diff --git a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts index f6026f840..f39334215 100644 --- a/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts +++ b/ui/src/app/core/manage-plugins/manage-version/manage-version.component.ts @@ -1,11 +1,15 @@ import { Component, inject, Input, OnInit } from '@angular/core' -import { FormsModule } from '@angular/forms' +import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms' +import { Router } from '@angular/router' import { NgbActiveModal, NgbAlert } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' +import { firstValueFrom } from 'rxjs' +import { debounceTime } from 'rxjs/operators' import { rcompare } from 'semver' import { ApiService } from '@/app/core/api.service' +import { SettingsService } from '@/app/core/settings.service' interface VersionData { version: string @@ -22,16 +26,21 @@ interface VersionData { FormsModule, TranslatePipe, NgbAlert, + ReactiveFormsModule, ], }) export class ManageVersionComponent implements OnInit { $activeModal = inject(NgbActiveModal) private $api = inject(ApiService) + private $router = inject(Router) + private $settings = inject(SettingsService) private $toastr = inject(ToastrService) private $translate = inject(TranslateService) @Input() plugin: any + public isUpdateHidden: boolean = false + public hideUpdatesFormControl = new FormControl(false) public loading = true public versions: Array = [] public versionsWithTags: Array<{ version: string, tag: string }> = [] @@ -42,6 +51,12 @@ export class ManageVersionComponent implements OnInit { ngOnInit(): void { this.versionSelect = this.plugin.installedVersion || this.plugin.latestVersion this.lookupVersions() + + this.isUpdateHidden = this.$settings.env.plugins.hideUpdatesFor && this.$settings.env.plugins.hideUpdatesFor.includes(this.plugin.name) + this.hideUpdatesFormControl.patchValue(this.isUpdateHidden) + this.hideUpdatesFormControl.valueChanges + .pipe(debounceTime(750)) + .subscribe((value: boolean) => this.toggleHideUpdates(value)) } lookupVersions() { @@ -98,4 +113,26 @@ export class ManageVersionComponent implements OnInit { action: this.plugin.installedVersion ? 'alternate' : 'install', }) } + + async toggleHideUpdates(value: boolean) { + let currentSetting = this.$settings.env.plugins?.hideUpdatesFor || [] + if (value) { + if (!currentSetting.includes(this.plugin.name)) { + currentSetting = [...currentSetting, this.plugin.name].sort((a, b) => a.localeCompare(b)) + } + } else { + currentSetting = currentSetting.filter(x => x !== this.plugin.name) + } + try { + await firstValueFrom(this.$api.put('/config-editor/ui/plugins/hide-updates-for', { + body: currentSetting, + })) + this.$settings.setEnvItem('plugins.hideUpdatesFor', currentSetting) + window.location.href = `/plugins?action=open-manage-version&plugin=${this.plugin.name}` + } catch (error) { + this.hideUpdatesFormControl.patchValue(this.isUpdateHidden, { emitEvent: false }) + console.error(error) + this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) + } + } } diff --git a/ui/src/app/core/settings.service.ts b/ui/src/app/core/settings.service.ts index b653b654e..d51fb4d67 100644 --- a/ui/src/app/core/settings.service.ts +++ b/ui/src/app/core/settings.service.ts @@ -52,6 +52,9 @@ interface EnvInterface { debug?: boolean instanceBlacklist?: string[] } + plugins?: { + hideUpdatesFor?: string[] + } linux?: { shutdown?: string restart?: string diff --git a/ui/src/app/modules/plugins/plugins.component.ts b/ui/src/app/modules/plugins/plugins.component.ts index cd6a1c504..2e6992329 100644 --- a/ui/src/app/modules/plugins/plugins.component.ts +++ b/ui/src/app/modules/plugins/plugins.component.ts @@ -60,24 +60,41 @@ export class PluginsComponent implements OnInit, OnDestroy { this.io.socket.emit('monitor-child-bridge-status') // Load list of installed plugins - this.loadInstalledPlugins().then(() => { - // Get query parameters - const justInstalled = this.$router.parseUrl(this.$router.url).queryParams.installed - if (justInstalled) { - const plugin = this.installedPlugins.find(x => x.name === justInstalled) - if (plugin) { - if (plugin.isConfigured) { - this.$modal.open(RestartHomebridgeComponent, { - size: 'lg', - backdrop: 'static', - }) - } else { - this.$plugin.settings(plugin) + await this.loadInstalledPlugins() + + // Get any query parameters + const { action: queryAction, plugin: queryPlugin } = this.$router.parseUrl(this.$router.url).queryParams + if (queryAction) { + const plugin = this.installedPlugins.find(x => x.name === queryPlugin) + switch (queryAction) { + case 'just-installed': { + if (plugin) { + if (plugin.isConfigured) { + this.$modal.open(RestartHomebridgeComponent, { + size: 'lg', + backdrop: 'static', + }) + } else { + this.$plugin.settings(plugin) + } + } + break + } + case 'open-manage-version': { + if (plugin) { + this.$plugin.installAlternateVersion(plugin) } + break } - this.$router.navigate(['/plugins']) } - }) + + // Clear the query parameters so that we don't keep showing the same action + this.$router.navigate([], { + queryParams: {}, + replaceUrl: true, + queryParamsHandling: '', + }) + } }) this.io.socket.on('child-bridge-status-update', (data) => { @@ -177,6 +194,10 @@ export class PluginsComponent implements OnInit, OnDestroy { const pluginChildBridges = this.getPluginChildBridges(plugin) plugin.hasChildBridgesUnpaired = pluginChildBridges.some(x => !x.paired) + + if (this.$settings.env.plugins?.hideUpdatesFor?.includes(plugin.name)) { + plugin.updateAvailable = false + } } catch (err) { // May not be technically correct, but if we can't load the config, assume it is configured plugin.isConfigured = true diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts index 114d8799d..482855d28 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts @@ -133,7 +133,8 @@ export class UpdateInfoWidgetComponent implements OnInit { async getOutOfDatePlugins() { try { const outOfDatePlugins = await firstValueFrom(this.io.request('get-out-of-date-plugins')) - this.homebridgePluginStatus = outOfDatePlugins.filter((x: any) => x.name !== 'homebridge-config-ui-x') + this.homebridgePluginStatus = outOfDatePlugins + .filter((x: any) => x.name !== 'homebridge-config-ui-x' && !this.$settings.env.plugins?.hideUpdatesFor?.includes(x.name)) this.homebridgePluginStatusDone = true } catch (error) { console.error(error) diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 73927ce28..0477b4621 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Инсталирай", "plugins.manage.installed": "Инсталиран", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 8af51d492..2ce9f4ab5 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Activar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informació del plugin", "plugins.manage.install": "Instal·lar", "plugins.manage.installed": "Instal·lat", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 55fdfae9c..415b189ac 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Povolit", "plugins.manage.github_support": "Můžete vyjádřit svou podporu tomuto pluginu tím, že mu na GitHubu dáte {{ iconStar }} (nebo této verzi {{ iconThumbsUp }})!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informace o pluginu", "plugins.manage.install": "Instalovat", "plugins.manage.installed": "Instalováno", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index 0fd537164..af547aad7 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Aktivieren", "plugins.manage.github_support": "Sie können Ihre Unterstützung zeigen, indem Sie dieses Plugin mit einem {{ iconStar }} (oder dem Release ein {{ iconThumbsUp }}) auf GitHub geben!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installieren", "plugins.manage.installed": "Installiert", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 641482e15..063dff9ec 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Install", "plugins.manage.installed": "Installed", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index dfe426529..78a10a49c 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Habilitar", "plugins.manage.github_support": "Puedes mostrar tu apoyo dando a este plugin una {{ iconStar }} (o a la versión una {{ iconThumbsUp }}) en GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Información del Plugin", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 20d80a507..78d4e103c 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Ota käyttöön", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Tietoja laajennuksesta", "plugins.manage.install": "Asenna", "plugins.manage.installed": "Asennettu", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 2025fa0aa..d68b624bb 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Activer", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informations sur le plugin", "plugins.manage.install": "Installer", "plugins.manage.installed": "Installé", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 1b09924df..23ee20c08 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "מאופשר", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "התקן", "plugins.manage.installed": "הותקן", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index dbd92a38c..b672cfd04 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Telepítés", "plugins.manage.installed": "Telepítve", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index e6340fa3c..3cfc0a293 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Aktifkan", "plugins.manage.github_support": "Anda dapat menunjukkan dukungan Anda dengan memberikan plugin ini {{ iconStar }} (atau rilis A {{ iconThumbsUp }}) di github!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informasi Plugin", "plugins.manage.install": "Pasang", "plugins.manage.installed": "Terpasang", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index b8c5a5882..6958356ab 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Attiva", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installa", "plugins.manage.installed": "Installato", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 556aadb92..2fcbd632d 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "有効化", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "プラグイン情報", "plugins.manage.install": "インストール", "plugins.manage.installed": "インストール済", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 914bf899e..49a2790b0 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "활성화", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "플러그인 정보", "plugins.manage.install": "설치", "plugins.manage.installed": "설치됨", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index a2c217230..734668dd8 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Инсталирај", "plugins.manage.installed": "Инсталирано", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 4ff8a4299..01f88cf2c 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Activeren", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installeer", "plugins.manage.installed": "Geïnstalleerd", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index d14d44f0a..5585b9054 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Installere", "plugins.manage.installed": "Installert", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index a9867b328..945f68570 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Włącz", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Informacje wtyczki", "plugins.manage.install": "Instaluj", "plugins.manage.installed": "Zainstalowane", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index ad637e71c..08592861e 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Ativar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 2a829e7bf..27de2ec6f 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Ativar", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Instalar", "plugins.manage.installed": "Instalado", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index 70f9c3148..35b896437 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Включить", "plugins.manage.github_support": "Вы можете поддержать проект, поставив {{ iconStar }} плагину (или {{ iconThumbsUp }} релизу) на GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Информация о плагине", "plugins.manage.install": "Установить", "plugins.manage.installed": "Установлен", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index d16684df4..881eea225 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Omogoči", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Namestite", "plugins.manage.installed": "Nameščeno", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index b7224c400..d23d2e5de 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Aktivera", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin-information", "plugins.manage.install": "Installera", "plugins.manage.installed": "Installerad", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index ad4cdf576..3a1c10a6b 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "เปิดการใช้งาน", "plugins.manage.github_support": "คุณสามารถแสดงการสนับสนุนของคุณโดยมอบ {{ iconStar }} ให้กับปลั๊กอินนี้ (หรือเผยแพร่ {{ iconThumbsUp }}) บน GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "ข้อมูลปลั๊กอิน", "plugins.manage.install": "ติดตั้ง", "plugins.manage.installed": "ติดตั้งแล้ว", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index 7600524e9..6c48f8d10 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Etkinleştir", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "Yükle", "plugins.manage.installed": "Yüklü", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 11e730bab..a6adfb0cf 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Увімкнути", "plugins.manage.github_support": "Ви можете продемонструвати свою підтримку, поставивши цьому плагіну {{ iconStar }} (або випуску {{ iconThumbsUp }}) на GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Інформація про плагін", "plugins.manage.install": "Встановлення", "plugins.manage.installed": "Плагін встановлено", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index dc493ced4..070e3a369 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "Enable", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "安装", "plugins.manage.installed": "已安装", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index 61b4b666f..4d5a4748d 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -266,6 +266,8 @@ "plugins.manage.enable": "開啟", "plugins.manage.github_support": "You can show your support by giving this plugin a {{ iconStar }} (or the release a {{ iconThumbsUp }}) on GitHub!", "plugins.manage.hb_restart": "Homebridge and the UI will automatically restart after any version change.", + "plugins.manage.hide_updates": "Disable Update Notifications", + "plugins.manage.hide_updates_desc": "If you don't want to see update notifications for this plugin, you can turn them off here.", "plugins.manage.information": "Plugin Information", "plugins.manage.install": "安裝", "plugins.manage.installed": "已安裝", From 5355751c2566ef23a4daa89845fe31535c784457 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Tue, 17 Jun 2025 18:35:23 +0100 Subject: [PATCH 09/22] improve plugin search and result ordering Co-Authored-By: Just Jam <4944618+justjam2013@users.noreply.github.com> --- CHANGELOG.md | 1 + src/modules/plugins/plugins.service.ts | 165 +++++++++++++++---------- 2 files changed, 99 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32e314428..f0ba9cb2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - refactor settings page with immediate saving - add support for `uiSchema` within plugin configurations - add option to hide update notifications for specific plugins +- improve plugin search and result ordering (@justjam2013) ### Homebridge Dependencies diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index dfbd2157c..3058d5e44 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -248,6 +248,47 @@ export class PluginsService { } } + private extractTerms(query: string, separator: RegExp): string[] { + return query + .toLowerCase() + .split(separator) + .map(term => term.trim()) + .filter(term => term && term !== 'homebridge' && term !== 'plugin') + } + + private getPluginKeywords(plugin: any): string[] { + return Array.isArray(plugin.keywords) + ? plugin.keywords.map(k => k.toLowerCase()) + : [] + } + + private matchesPlugin(plugin: HomebridgePlugin, searchTerms: string[]): 'exactName' | 'exactKeyword' | 'partial' | null { + const pluginName = plugin.name.toLowerCase() + const pluginKeywords = this.getPluginKeywords(plugin) + const pluginDescription = (plugin.description || '').toLowerCase() + + // Separator: '-' character, only get the terms from the plugin name, ignoring any scope + const nameTerms = this.extractTerms(pluginName.substring(pluginName.lastIndexOf('/') + 1), /-/) + + // The search terms contain all the parts of the name + if (nameTerms.every(term => searchTerms.includes(term))) { + return 'exactName' + } + // The keywords or name contain all the search terms + if (searchTerms.every(term => pluginKeywords.includes(term)) + || searchTerms.every(term => nameTerms.includes(term))) { + return 'exactKeyword' + } + if ( + searchTerms.some(term => pluginName.includes(term)) + || searchTerms.some(term => pluginKeywords.some(k => k.includes(term))) + || searchTerms.some(term => pluginDescription.includes(term)) + ) { + return 'partial' + } + return null + } + /** * Search the npm registry for homebridge plugins * @param query @@ -257,21 +298,26 @@ export class PluginsService { await this.getInstalledPlugins() } - query = query.trim().toLowerCase() + const searchTerms = this.extractTerms(query, /\s+/) // Separator: whitespace (spaces, tabs and new lines) characters + const normalizedQuery = searchTerms.length > 0 ? searchTerms.join(' ') : 'homebridge' - if ((query.startsWith('homebridge-') || this.isScopedPlugin(query)) && !this.hiddenPlugins.includes(query)) { - // Change the query to the scoped version if it exists, and the 'old' version is not installed - if (!this.installedPlugins.find(x => x.name === query) && Object.keys(this.newScopePlugins).includes(query)) { - query = `@homebridge-plugins/${query}` + if ( + (normalizedQuery.startsWith('homebridge-') || this.isScopedPlugin(normalizedQuery)) + && !this.hiddenPlugins.includes(normalizedQuery) + ) { + if ( + !this.installedPlugins.find(x => x.name === normalizedQuery) + && Object.keys(this.newScopePlugins).includes(normalizedQuery) + ) { + return await this.searchNpmRegistrySingle(`@homebridge-plugins/${normalizedQuery}`) } - return await this.searchNpmRegistrySingle(query) + return await this.searchNpmRegistrySingle(normalizedQuery) } // There seems to be a new 64-character limit on the text query (which allows for 15 characters of a query) // Get the top 99 plugins now, later we filter down to the top 30 - const q = `${(!query || !query.length) ? '' : `${query.substring(0, 15)}+`}keywords:homebridge-plugin+not:deprecated&size=99` + const q = `${normalizedQuery.substring(0, 15)}+keywords:homebridge-plugin+not:deprecated&size=99` let searchResults: INpmSearchResults - try { searchResults = (await firstValueFrom(this.httpService.get(`https://registry.npmjs.org/-/v1/search?text=${q}`))).data } catch (e) { @@ -279,79 +325,64 @@ export class PluginsService { throw new InternalServerErrorException(`Failed to search the npm registry as ${e.message}, see logs.`) } - const result: HomebridgePlugin[] = searchResults.objects - .filter(x => x.package.name.indexOf('homebridge-') === 0 || this.isScopedPlugin(x.package.name)) + const plugins: HomebridgePlugin[] = searchResults.objects + .filter(x => x.package.name.startsWith('homebridge-') || this.isScopedPlugin(x.package.name)) .filter(x => !this.hiddenPlugins.includes(x.package.name)) .map((pkg) => { - let plugin: HomebridgePlugin = { - name: pkg.package.name, - displayName: this.pluginNames[pkg.package.name], - private: false, - } + const isInstalled = this.installedPlugins.find(x => x.name === pkg.package.name) // See if the plugin is already installed - const isInstalled = this.installedPlugins.find(x => x.name === plugin.name) if (isInstalled) { - plugin = isInstalled - plugin.lastUpdated = pkg.package.date - plugin.keywords = pkg.package.keywords - return plugin + return { + ...isInstalled, + lastUpdated: pkg.package.date, + keywords: pkg.package.keywords || [], + } } // It's not installed; finish building the response - plugin.publicPackage = true - plugin.installedVersion = null - plugin.latestVersion = pkg.package.version - plugin.lastUpdated = pkg.package.date - plugin.description = (pkg.package.description) - ? pkg.package.description.replace(/\(?(?:https?|ftp):\/\/[\n\S]+/g, '').trim() - : pkg.package.name - plugin.keywords = pkg.package.keywords - plugin.links = pkg.package.links - plugin.author = this.pluginAuthors[pkg.package.name] || ((pkg.package.publisher) ? pkg.package.publisher.username : null) - plugin.verifiedPlugin = this.verifiedPlugins.includes(pkg.package.name) - plugin.verifiedPlusPlugin = this.verifiedPlusPlugins.includes(pkg.package.name) - plugin.icon = this.pluginIcons[pkg.package.name] - ? `${this.pluginListUrl}${this.pluginIcons[pkg.package.name]}` - : null - plugin.isHbScoped = pkg.package.name.startsWith('@homebridge-plugins/') - plugin.newHbScope = this.newScopePlugins[pkg.package.name] - plugin.isHbMaintained = this.maintainedPlugins.includes(pkg.package.name) - return plugin + return { + name: pkg.package.name, + displayName: this.pluginNames[pkg.package.name], + private: false, + publicPackage: true, + installedVersion: null, + latestVersion: pkg.package.version, + lastUpdated: pkg.package.date, + description: (pkg.package.description || pkg.package.name).replace(/\(?(?:https?|ftp):\/\/[\n\S]+/g, '').trim(), + keywords: pkg.package.keywords || [], + links: pkg.package.links, + author: this.pluginAuthors[pkg.package.name] || (pkg.package.publisher ? pkg.package.publisher.username : null), + verifiedPlugin: this.verifiedPlugins.includes(pkg.package.name), + verifiedPlusPlugin: this.verifiedPlusPlugins.includes(pkg.package.name), + icon: this.pluginIcons[pkg.package.name] ? `${this.pluginListUrl}${this.pluginIcons[pkg.package.name]}` : null, + isHbScoped: pkg.package.name.startsWith('@homebridge-plugins/'), + newHbScope: this.newScopePlugins[pkg.package.name], + isHbMaintained: this.maintainedPlugins.includes(pkg.package.name), + } }) - const searchTerm: string = query - .replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, '') // remove punctuation - - const searchTerms: string[] = searchTerm - .split(/\s+/) // split into words - .filter(term => term.length > 0) // remove empty strings - - // Separate lists for exact matches and partial matches - const exactMatchPlugins: HomebridgePlugin[] = [] - const partialMatchPlugins: HomebridgePlugin[] = [] + const matchGroups = { + exactName: [] as HomebridgePlugin[], + exactKeyword: [] as HomebridgePlugin[], + partial: [] as HomebridgePlugin[], + } - // Filter matching plugins - result.forEach((plugin) => { - const pluginKeywords = plugin.keywords.map(keyword => keyword.toLowerCase()) - const isExactMatch = pluginKeywords.includes(searchTerm) - if (isExactMatch) { - exactMatchPlugins.push(plugin) - return + for (const plugin of plugins) { + const matchType = this.matchesPlugin(plugin, searchTerms) + if (matchType) { + matchGroups[matchType].push(plugin) } + } - const pluginName = plugin.name.toLowerCase() - const pluginDescription = plugin.description.toLowerCase() - const isPartialMatch = searchTerms.some(term => pluginName.includes(term)) - || searchTerms.some(term => pluginKeywords.some(keyword => keyword.includes(term))) - || searchTerms.some(term => pluginDescription.includes(term)) - - if (isPartialMatch) { - partialMatchPlugins.push(plugin) - } - }) + const orderPlugins = (arr: HomebridgePlugin[]) => + orderBy(arr, ['isHbScoped', 'verifiedPlusPlugin', 'verifiedPlugin', 'lastUpdated'], ['desc', 'desc', 'desc']) - return orderBy([...exactMatchPlugins, ...partialMatchPlugins], ['verifiedPlusPlugin', 'verifiedPlugin'], ['desc', 'desc']) + return [ + ...orderPlugins(matchGroups.exactName), + ...orderPlugins(matchGroups.exactKeyword), + ...orderPlugins(matchGroups.partial), + ] .slice(0, 30) .map(plugin => this.fixDisplayName(plugin)) } From 8b02b6a073b550e9e21fcfd10cb87226807b504d Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Thu, 19 Jun 2025 16:05:20 +0100 Subject: [PATCH 10/22] Remove Redundant GSH Components Co-Authored-By: Northern Man <19808920+NorthernMan54@users.noreply.github.com> --- CHANGELOG.md | 4 + .../custom-plugins/custom-plugins.module.ts | 2 - .../custom-plugins/custom-plugins.service.ts | 5 +- ...homebridge-google-smarthome.component.html | 74 -------- .../homebridge-google-smarthome.component.ts | 171 ------------------ ui/src/i18n/bg.json | 2 - ui/src/i18n/ca.json | 2 - ui/src/i18n/cs.json | 2 - ui/src/i18n/de.json | 2 - ui/src/i18n/en.json | 2 - ui/src/i18n/es.json | 2 - ui/src/i18n/fi.json | 2 - ui/src/i18n/fr.json | 2 - ui/src/i18n/he.json | 2 - ui/src/i18n/hu.json | 2 - ui/src/i18n/id.json | 2 - ui/src/i18n/it.json | 2 - ui/src/i18n/ja.json | 2 - ui/src/i18n/ko.json | 2 - ui/src/i18n/mk.json | 2 - ui/src/i18n/nl.json | 2 - ui/src/i18n/no.json | 2 - ui/src/i18n/pl.json | 2 - ui/src/i18n/pt-BR.json | 2 - ui/src/i18n/pt.json | 2 - ui/src/i18n/ru.json | 2 - ui/src/i18n/sl.json | 2 - ui/src/i18n/sv.json | 2 - ui/src/i18n/th.json | 2 - ui/src/i18n/tr.json | 2 - ui/src/i18n/uk.json | 2 - ui/src/i18n/zh-CN.json | 2 - ui/src/i18n/zh-TW.json | 2 - 33 files changed, 5 insertions(+), 307 deletions(-) delete mode 100644 ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html delete mode 100644 ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f0ba9cb2d..961b8b581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - add option to hide update notifications for specific plugins - improve plugin search and result ordering (@justjam2013) +### Other Changes + +- Removed redundant Google Smart Home components (@NorthernMan54) + ### Homebridge Dependencies - `@homebridge/hap-client` @ `v2.2.0` diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts index a67c04ea1..85b21b5ad 100644 --- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts +++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.module.ts @@ -9,7 +9,6 @@ import { NgxMdModule } from 'ngx-md' import { CustomPluginsComponent } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.component' import { CustomPluginsService } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.service' import { HomebridgeDeconzComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-deconz/homebridge-deconz.component' -import { HomebridgeGoogleSmarthomeComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component' import { HomebridgeHueComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-hue/homebridge-hue.component' @NgModule({ @@ -23,7 +22,6 @@ import { HomebridgeHueComponent } from '@/app/core/manage-plugins/custom-plugins NgxMdModule, CustomPluginsComponent, HomebridgeDeconzComponent, - HomebridgeGoogleSmarthomeComponent, HomebridgeHueComponent, ], providers: [ diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts index 85df9739f..0a14bbdee 100644 --- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts +++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.service.ts @@ -4,7 +4,6 @@ import { firstValueFrom } from 'rxjs' import { ApiService } from '@/app/core/api.service' import { CustomPluginsComponent } from '@/app/core/manage-plugins/custom-plugins/custom-plugins.component' -import { HomebridgeGoogleSmarthomeComponent } from '@/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component' @Injectable({ providedIn: 'root', @@ -13,9 +12,7 @@ export class CustomPluginsService { private $api = inject(ApiService) private $modal = inject(NgbModal) - public plugins = { - 'homebridge-gsh': HomebridgeGoogleSmarthomeComponent, - } + public plugins = {} constructor() {} diff --git a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html b/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html deleted file mode 100644 index cf8392066..000000000 --- a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.html +++ /dev/null @@ -1,74 +0,0 @@ - diff --git a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts b/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts deleted file mode 100644 index 2fdb09330..000000000 --- a/ui/src/app/core/manage-plugins/custom-plugins/homebridge-google-smarthome/homebridge-google-smarthome.component.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { TitleCasePipe } from '@angular/common' -import { Component, inject, Input, OnDestroy, OnInit } from '@angular/core' -import { JwtHelperService } from '@auth0/angular-jwt' -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { TranslatePipe, TranslateService } from '@ngx-translate/core' -import { NgxMdModule } from 'ngx-md' -import { ToastrService } from 'ngx-toastr' -import { firstValueFrom } from 'rxjs' - -/* global NodeJS */ -import { ApiService } from '@/app/core/api.service' -import { SchemaFormComponent } from '@/app/core/components/schema-form/schema-form.component' -import { PluginsMarkdownDirective } from '@/app/core/directives/plugins.markdown.directive' -import { SettingsService } from '@/app/core/settings.service' - -@Component({ - selector: 'app-homebridge-google-smarthome', - templateUrl: './homebridge-google-smarthome.component.html', - standalone: true, - imports: [ - NgxMdModule, - PluginsMarkdownDirective, - SchemaFormComponent, - TitleCasePipe, - TranslatePipe, - ], -}) -export class HomebridgeGoogleSmarthomeComponent implements OnInit, OnDestroy { - $activeModal = inject(NgbActiveModal) - private $api = inject(ApiService) - private $jwtHelper = inject(JwtHelperService) - $settings = inject(SettingsService) - private $toastr = inject(ToastrService) - private $translate = inject(TranslateService) - - @Input() public plugin: any - @Input() public schema: any - @Input() pluginConfig: Record[] - - public justLinked = false - public gshConfig: Record - public linkType: string - public readonly linkInsecure = '' - - private linkDomain = 'https://homebridge-gsh.iot.oz.nu' - private linkUrl = `${this.linkDomain}/link-account` - private popup: Window - private originCheckInterval: NodeJS.Timeout - - constructor() { - // Listen for sign in events from the link account popup - window.addEventListener('message', this.windowMessageListener, false) - } - - ngOnInit() { - if (!this.pluginConfig.length) { - this.pluginConfig.push({ name: 'Google Smart Home', platform: this.schema.pluginAlias }) - } - - this.gshConfig = this.pluginConfig[0] - - this.parseToken() - } - - windowMessageListener = (e: MessageEvent) => { - if (e.origin !== this.linkDomain) { - console.error('Refusing to process message from', e.origin) - console.error(e) - } - - try { - const data = JSON.parse(e.data) - if (data.token) { - this.processToken(data.token) - } - } catch (error) { - console.error(error) - } - } - - linkAccount() { - const w = 450 - const h = 700 - const y = window.top.outerHeight / 2 + window.top.screenY - (h / 2) - const x = window.top.outerWidth / 2 + window.top.screenX - (w / 2) - this.popup = window.open( - this.linkUrl, - 'oznu-google-smart-home-auth', - 'toolbar=no, location=no, directories=no, status=no, menubar=no scrollbars=no, resizable=no, copyhistory=no, ' - + `width=${w}, height=${h}, top=${y}, left=${x}`, - ) - - // Simple message popup to provide the current hostname - this.originCheckInterval = setInterval(() => { - this.popup.postMessage('origin-check', this.linkDomain) - }, 2000) - } - - unlinkAccount() { - this.gshConfig = { - name: 'Google Smart Home', - platform: this.schema.pluginAlias, - } - - this.pluginConfig.splice(0, this.pluginConfig.length) - this.saveConfig() - } - - processToken(token: string) { - clearInterval(this.originCheckInterval) - if (this.popup) { - this.popup.close() - } - this.gshConfig.token = token - this.gshConfig.notice = 'Keep your token a secret!' - - if (!this.pluginConfig.length) { - this.pluginConfig.push(this.gshConfig) - } - - this.parseToken() - this.saveConfig() - } - - parseToken() { - if (this.gshConfig.token) { - try { - const decoded = this.$jwtHelper.decodeToken(this.gshConfig.token) - this.linkType = decoded.id.split('|')[0].split('-')[0] - } catch (error) { - console.error(error) - this.$toastr.error(this.$translate.instant('plugins.settings.custom.homebridge-gsh.message_invalid_token'), this.$translate.instant('toast.title_error')) - delete this.gshConfig.token - } - } - } - - async saveConfig() { - try { - await firstValueFrom(this.$api.post(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`, this.pluginConfig)) - this.justLinked = true - this.$toastr.success( - this.$translate.instant('plugins.settings.restart_required'), - this.$translate.instant('plugins.settings.plugin_config_saved'), - ) - } catch (error) { - console.error(error) - this.$toastr.error(this.$translate.instant('config.failed_to_save_config'), this.$translate.instant('toast.title_error')) - } - } - - async saveAndClose() { - this.gshConfig.platform = this.schema.pluginAlias - this.pluginConfig[0] = this.gshConfig - - await this.saveConfig() - this.$activeModal.close() - } - - close() { - this.$activeModal.close() - } - - ngOnDestroy() { - clearInterval(this.originCheckInterval) - window.removeEventListener('message', this.windowMessageListener) - if (this.popup) { - this.popup.close() - } - } -} diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 0477b4621..1ef2b17eb 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Търсете добавки, които да инсталирате…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Linked", "plugins.settings.custom.homebridge-gsh.label_link_account": "Link Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Unlink Account", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge requires restarting for the changes to take effect.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 2ce9f4ab5..56ba30ed5 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Cercar plugins per instal·lar…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Compte vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular compte", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular compte", "plugins.settings.custom.homebridge-gsh.message_about": "El plugin Homebridge Google Smart Home et permet controlar les accessoris de Homebridge des d'un altaveu intel·ligent Google Home o des de l'aplicació mòbil Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Per activar aquesta funcionalitat has d'iniciar sessió amb el teu compte Google o GitHub; assegura't que fas servir el mateix compte quan estiguis afegint l'acció de Homebridge en l'aplicació mòbil Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge necessita reiniciar perquè els canvis tinguin efecte.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Obrir editor de configuració", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 415b189ac..21e95b6b7 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Vyhledejte pluginy k instalaci…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Účet propojen", "plugins.settings.custom.homebridge-gsh.label_link_account": "Propojit účet", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Odpojit účet", "plugins.settings.custom.homebridge-gsh.message_about": "Plugin Homebridge Google Smart Home vám umožňuje ovládat příslušenství Homebridge z chytrého reproduktoru s aktivovanou službou Google Home nebo z mobilní aplikace Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Chcete-li tuto funkci povolit, musíte se přihlásit pomocí účtu Google nebo GitHub; Při přidávání akce Homebridge do mobilní aplikace Google Home se ujistěte, že používáte stejný účet.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Aby se změny projevily, Homebridge vyžaduje restartování.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Neplatný token propojení účtu v config.json", "plugins.settings.deconz.dump_no_exist": "Soubor dumpu Homebridge deCONZ ještě neexistuje.", "plugins.settings.hue.dump_no_exist": "Soubor dumpu Homebridge Hue ještě neexistuje.", "plugins.settings.label_open_config_editor": "Otevřít editor konfigurace", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index af547aad7..e130ab965 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Suche nach installierbaren Plugins …", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto verbunden", "plugins.settings.custom.homebridge-gsh.label_link_account": "Konto verbinden", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Kontoverbindung aufheben", "plugins.settings.custom.homebridge-gsh.message_about": "Das Homebridge Google Smart Home-Plugin erlaubt es dir, deine Homebridge-Geräte durch einen Google Home-fähigen smarten Lautsprecher oder durch die Google Home Mobile-App zu steuern.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Um diese Funktionalität zu aktivieren, musst du dich mit deinem Google- or GitHub-Konto anmelden. Stelle sicher, dass du dasselbe Konto verwendest, wenn du die Homebridge-Aktion in der Google Home Mobile-App hinzufügst.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge muss neugestartet werden, damit die Änderungen wirksam werden.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Ungültiger Account-Token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ Dump-Datei existiert noch nicht.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue Dump-Datei existiert noch nicht.", "plugins.settings.label_open_config_editor": "Konfigurations-Editor öffnen", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index 063dff9ec..a4bc46b32 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Search for plugins to install…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Linked", "plugins.settings.custom.homebridge-gsh.label_link_account": "Link Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Unlink Account", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge requires restarting for the changes to take effect.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 78a10a49c..545a8bcff 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Buscar plugins disponibles para instalar…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Cuenta vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular cuenta", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular cuenta", "plugins.settings.custom.homebridge-gsh.message_about": "El plugin Homebridge Google Smart Home te permite controlar tus accesorios de Homebridge desde un altavoz inteligente Google Home o desde la aplicación móvil Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Para activar esta funcionalidad debes iniciar sesión con tu cuenta Google o GitHub; asegúrate que usas la misma cuenta cuando estés añadiendo la acción de Homebridge en la aplicación móvil Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge necesita reiniciarse para que los cambios tengan efecto.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Token de vinculación de cuenta inválido en config.json", "plugins.settings.deconz.dump_no_exist": "El archivo de volcado de Homebridge deCONZ aún no existe.", "plugins.settings.hue.dump_no_exist": "El archivo de volcado de Homebridge Hue aún no existe.", "plugins.settings.label_open_config_editor": "Abrir Editor de Configuración", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 78d4e103c..31c524d8e 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Etsi aennettavia laajennuksia", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Tili Linkitetty", "plugins.settings.custom.homebridge-gsh.label_link_account": "Linkitä Tili", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Pura tilin linkitys", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home laajennus mahdollistaa Homebridge laitteidesi hallinnan Google Home älykaiuttimella tai sovelluksella.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Toiminnon käyttöönottamiseksi sinun on kirjauduttava Google tai GitHub tilillesi; varmista että käytät samaa tiliä kun lisäät Homebridge toiminnon Google Home sovellukseesi.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge täytyy uudelleenkäynnistää toimintojen käyttöönottamiseksi.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Virheellinen tilin linkitys config.json:ssa", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump tiedostoa ei vielä ole.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump tiedostoa ei vielä ole.", "plugins.settings.label_open_config_editor": "Avaa Asetusten muokkain", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index d68b624bb..3a4b499fb 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Rechercher des plugins à installer…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Compte associé", "plugins.settings.custom.homebridge-gsh.label_link_account": "Associer le compte", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Dissocier le compte", "plugins.settings.custom.homebridge-gsh.message_about": "Le plugin Homebridge Google Smart Home vous permet de contrôler vos accessoires Homebridge à partir d'un haut-parleur intelligent compatible avec Google Home ou de l'application mobile Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Pour activer cette fonctionnalité, vous devez vous connecter avec votre compte Google ou GitHub. Assurez-vous d'utiliser le même compte lors de l'ajout de l'action Homebridge dans l'application mobile Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge nécessite un redémarrage pour que les modifications prennent effet.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Ouvrir l'éditeur de Config", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index 23ee20c08..df650eb64 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "חפש תוספים להתקנה…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "חשבון קושר", "plugins.settings.custom.homebridge-gsh.label_link_account": "קשר חשבון", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "נתק קשר לחשבון", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "הומברידג' חייב להיות מאותחל על מנת שהשינויים יחולו", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "פתח עורך קונפיגורציה", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index b672cfd04..aea7587eb 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Pluginek keresése…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Linked", "plugins.settings.custom.homebridge-gsh.label_link_account": "Link Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Unlink Account", "plugins.settings.custom.homebridge-gsh.message_about": "The Homebridge Google Smart Home plugin allows you to control your Homebridge accessories from a Google Home enabled smart speaker or the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "To enable this functionality you must sign in with your Google or GitHub account; make sure you use the same account when adding the Homebridge action in the Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge requires restarting for the changes to take effect.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 3cfc0a293..97bce998c 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Cari plugin untuk dipasang…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Akun Terhubung", "plugins.settings.custom.homebridge-gsh.label_link_account": "Hubungkan Akun", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Putuskan Hubungan Akun", "plugins.settings.custom.homebridge-gsh.message_about": "Plugin Homebridge Google Smart Home memungkinkan anda untuk mengontrol aksesoris Homebridge dari pengeras suara berkemampuan Google Home atau aplikasi seluler Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Untuk mengaktifkan fungsi ini, anda harus masuk dengan akun Google atau GitHub anda; pastikan anda menggunakan akun yang sama saat menambahkan tindakan Homebridge di aplikasi seluler Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge membutuhkan pengaktifan ulang agar perubahan dapat diterapkan.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Akun tidak valid menautkan token di config.json", "plugins.settings.deconz.dump_no_exist": "Berkas dump homebridge deCONZ belum ada.", "plugins.settings.hue.dump_no_exist": "Berkas dump Homebridge Hue belum ada.", "plugins.settings.label_open_config_editor": "Buka Editor Konfigurasi", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 6958356ab..154c2709c 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Cerca plugin da installare…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account collegato", "plugins.settings.custom.homebridge-gsh.label_link_account": "Collega account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Scollega account", "plugins.settings.custom.homebridge-gsh.message_about": "Il plugin Homebridge Google Smart Home permette di controllare gli accessori Homebridge da un altoparlante intelligente Google Home abilitato o dall'applicazione Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "L'attivazione di questa funzione richiede l'accesso con un account Google or GitHub; assicurarsi di usare lo stesso account quanto si aggiunge l'azione Homebridge nell'applicazione Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge deve essere riavviato affinché le modifiche abbiano effetto.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Apri l'editor della configurazione", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index 2fcbd632d..ba3470e1f 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "インストールするプラグインを検索…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "アカウント連携済み", "plugins.settings.custom.homebridge-gsh.label_link_account": "アカウントと連携する", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "アカウントとの連携を解除する", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home プラグインを使用すると、Google Home対応小野スマートスピーカーやGoogle HomeモバイルアプリからHomebridgeアクセサリを制御することができます。", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "この機能を有効にするには、GoogleまたはGitHubアカウントでログインする必要があります。Google HomeモバイルアプリにHomebridgeアクションを追加する際には、同じアカウントを使用してください。", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "変更を反映するには、Homebridgeの再起動が必要です。", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "コンフィグエディタを開く", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 49a2790b0..3d815e345 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "설치할 플러그인 검색…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "계정 연결됨", "plugins.settings.custom.homebridge-gsh.label_link_account": "계정 연결", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "계정 연결해제", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home 플러그인을 사용하면 Google Home 지원 스마트 스피커 또는 Google Home 모바일 앱에서 Homebridge 액세서리를 제어 할 수 있습니다.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "이 기능을 사용하려면 Google 또는 GitHub 계정으로 로그인해야합니다; Google Home 모바일 앱에 Homebridge 작업을 추가할 때 동일한 계정을 사용해야합니다.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "변경사항을 반영하려면 Homebridge를 다시 시작해야합니다.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "config.json에 잘못된 계정 연결 토큰이 있습니다.", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ 덤프 파일이 아직 존재하지 않습니다.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue 덤프 파일이 아직 존재하지 않습니다.", "plugins.settings.label_open_config_editor": "Config 에디터 열기", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index 734668dd8..419a284c8 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Барајте плагини достапни за инсталација…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Поврзана корисничка сметка", "plugins.settings.custom.homebridge-gsh.label_link_account": "Поврзи корисничка сметка", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Откажи поврзување на корисничка сметка", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home плагинот овозможува контрола на Homebridge уредите од Google Home smart speaker или од Google Home мобилната апликација.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "За да ја овозможите оваа функција мора да се најавите со Вашата Google или GitHub корисничка сметка; осигурајте се дека истата сметка ја користите при додавање на Homebridge акцијата во Google Home мобилната апликација.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge бара рестарт за промените да бидат рефлектирани.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Отвори уредник за конфигурација", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 01f88cf2c..1b0ec2e3c 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Zoeken naar plug-ins om te installeren…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Account Gekoppeld", "plugins.settings.custom.homebridge-gsh.label_link_account": "Koppel Account", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Verwijder account koppeling", "plugins.settings.custom.homebridge-gsh.message_about": "De Homebridge Google Smart Home plugin maakt het mogelijk om je Homebridge accessoires te besturen met een Google Home geschikte smart speaker of de Google Home mobile app.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Om deze functionaliteit te activeren moet je inloggen met je Google of GitHub account; zorg er voor dat je hetzelfde account gebruikt als je de Homebridge actie toevoegt in de Google Home mobiele app.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge vereist een herstart om de wijzigingen te activeren.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Ongeldig account koppel token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump bestand bestaat nog niet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump bestand bestaat nog niet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index 5585b9054..6a75d5c4b 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Søk etter plugins å installere…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto tilknyttet", "plugins.settings.custom.homebridge-gsh.label_link_account": "Tilknytt konto", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Ta bort tilknytting til konto", "plugins.settings.custom.homebridge-gsh.message_about": "Med Homebridge Google Smart Home- plugin kan du kontrollere dine Homebridge-tilbehør fra en Google Home-aktivert smarthøytaler eller Google Home-mobilappen.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "For å aktivere denne funksjonen må du logge inn med din Google- eller GitHub-konto; pass på at du bruker samme konto når du legger til Homebridge-infoen i mobilappen Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge krever omstart for at endringene skal tre i kraft.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Open Config Editor", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index 945f68570..2f8f9a1bf 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Wyszukaj dostępne wtyczki…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto podłączone", "plugins.settings.custom.homebridge-gsh.label_link_account": "Podłącz konto", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Odłącz konto", "plugins.settings.custom.homebridge-gsh.message_about": "Wtyczka Homebridge Google Smart Home umożliwia kontrolę akcesoriów za pomocą głośników lub aplikacji mobilnej Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Aby włączyć tą funkcjonalność, musisz zalogować się swoim kontem Google lub GitHub - pamiętaj aby użyć tego samego konta dla Homebridge i aplikacji Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Serwer wymaga zrestartowania, aby zastosować zmiany.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Otwórz edytor konfiguracji", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 08592861e..02b7c7784 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Procurar plugins para instalação…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Conta Vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular Conta", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular Conta", "plugins.settings.custom.homebridge-gsh.message_about": "O plugin Homebridge Google Smart Home permite que faça o controle dos acessórios do Homebridge através de um coluna inteligente com Google Home ou com o app do Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Para ativar esta funcionalidade é necessário iniciar sessão com a sua conta Google ou GitHub; utilize a mesma conta ao adicionar a ação do Homebridge no app do Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "É necessário reiniciar o Homebridge para que as mudanças surtam efeito.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Abrir editor de configurações", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 27de2ec6f..4c2122d72 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Procurar plugins para instalação…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Conta Vinculada", "plugins.settings.custom.homebridge-gsh.label_link_account": "Vincular Conta", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Desvincular Conta", "plugins.settings.custom.homebridge-gsh.message_about": "O plugin Homebridge Google Smart Home permite que faça o controlo dos acessórios do Homebridge através de um coluna inteligente com Google Home ou com a aplicação móvel do Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Para ativar esta funcionalidade é necessário iniciar sessão com a sua conta Google ou GitHub; utilize a mesma conta ao adicionar a ação do Homebridge na aplicação móvel do Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "É necessário reiniciar o Homebridge para que as mudanças surtam efeito.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Abrir o Editor de Configuração", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index 35b896437..ae46eb9e9 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Поиск плагинов для установки…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Учётная запись связана", "plugins.settings.custom.homebridge-gsh.label_link_account": "Связать учётную запись", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Отвязать учётную запись", "plugins.settings.custom.homebridge-gsh.message_about": "Плагин Homebridge Google Smart Home позволяет управлять вашими аксессуарами Homebridge через колонки Google Home или мобильное приложение Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Чтобы включить эту функцию, необходимо войти с учётной записью Google или GitHub; убедитесь, что используете ту же учётную запись при добавлении действия Homebridge в мобильном приложении Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Необходимо перезапустить Homebridge для применения изменений.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Неверный токен привязки учётной записи в config.json", "plugins.settings.deconz.dump_no_exist": "Файл дампа Homebridge deCONZ ещё не существует.", "plugins.settings.hue.dump_no_exist": "Файл дампа Homebridge Hue ещё не существует.", "plugins.settings.label_open_config_editor": "Открыть редактор конфигурации", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index 881eea225..dfcd88e65 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Poiščite vtičnike za namestitev …", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Račun povezan", "plugins.settings.custom.homebridge-gsh.label_link_account": "Povežite račun", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Prekini povezavo med računom", "plugins.settings.custom.homebridge-gsh.message_about": "Vtičnik Homebridge Google Smart Home omogoča upravljanje pripomočkov Homebridge iz pametnega zvočnika, ki podpira Google Home ali mobilne aplikacije Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Če želite omogočiti to funkcijo, se morate prijaviti s svojim računom za Google ali GitHub; pri dodajanju dejanja Homebridge v aplikacijo Google Home za mobilne naprave uporabite isti račun.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Za uveljavitev sprememb je treba znova zagnati Homebridge.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Odpri Config Urejevalec", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index d23d2e5de..622095e24 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Sök efter plugins att installera…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Konto länkat", "plugins.settings.custom.homebridge-gsh.label_link_account": "Länka konto", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Ta bort länkat konto", "plugins.settings.custom.homebridge-gsh.message_about": "Med pluginet Homebridge Google Smart Home kan du kontrollera dina Homebridge-tillbehör från en Google Home-aktiverad smarthögtalare eller Google Home-mobilappen.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "För att aktivera den här funktionen måste du logga in med ditt Google- eller GitHub-konto; se till att du använder samma konto när du lägger till Homebridge-åtgärden i mobilappen Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge kräver omstart för att ändringarna ska träda i kraft.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Öppna konfigurationsredigerare", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index 3a1c10a6b..f839fd4ab 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "ค้นหาปลั๊กอินที่จะติดตั้ง…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "เชื่อมโยงบัญชีแล้ว", "plugins.settings.custom.homebridge-gsh.label_link_account": "เชื่อมโยงบัญชี", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "ยกเลิกการเชื่อมโยงบัญชี", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home ปลั๊กอินช่วยให้คุณควบคุมอุปกรณ์เสริม Homebridge จากลำโพงอัจฉริยะที่เปิดใช้งาน Google Home หรือแอป Google Home บนอุปกรณ์เคลื่อนที่", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "ในการเปิดใช้งานฟังก์ชันนี้คุณต้องลงชื่อเข้าใช้ด้วยบัญชี Google หรือ GitHub ของคุณ; ตรวจสอบให้แน่ใจว่าคุณใช้บัญชีเดียวกันเมื่อเพิ่มการดำเนินการ Homebridge ในแอป Google Home บนอุปกรณ์เคลื่อนที่", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge ต้องรีสตาร์ทเพื่อให้การเปลี่ยนแปลงมีผล", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "โทเค็นการเชื่อมโยงบัญชีไม่ถูกต้องใน config.json", "plugins.settings.deconz.dump_no_exist": "ไฟล์ดัมพ์ Homebridge deCONZ ยังไม่มีอยู่", "plugins.settings.hue.dump_no_exist": "ไฟล์ดัมพ์ Homebridge Hue ยังไม่มีอยู่", "plugins.settings.label_open_config_editor": "เปิด Config Editor", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index 6c48f8d10..1c60b01c2 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Yüklemek için eklentiler arayın…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Hesap Bağlandı", "plugins.settings.custom.homebridge-gsh.label_link_account": "Hesabı Bağla", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Hesabın Bağlantısını Kaldır", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home eklentisi Homebridge aksesuarlarınızı Google Home kullanan akıllı hoparlörlerinizden veya Google Home mobil uygulamasından kontrol etmenize olanak sağlar.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Bu özelliği etkinleştirmek için Google veya Github hesabınız ile giriş yapmanız gerekli; Google Home mobil uygulamasında Homebridge'i eklerken aynı hesabı kullandığınızdan emin olun.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Değişikliklerin yürürlüğe girmesi için Homebridge yeniden başlatılmaya ihtiyaç duyar.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "Yapılandırma Düzenleyiciyi Aç", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index a6adfb0cf..27e5e2229 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "Пошук плагінів для встановлення…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "Аккаунт прив'язаний", "plugins.settings.custom.homebridge-gsh.label_link_account": "Прив'язати аккаунт", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "Відв'язати аккаунт", "plugins.settings.custom.homebridge-gsh.message_about": "Плагін Homebridge Google Smart Home дозволяє курувати аксесуарами Homebridge за допомогою розумної колонки з підтримкою Google Home або мобільного додатка Google Home.", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "Щоб увімкнути цю функцію, Ви повинні увійти в свій аккаунт Google або GitHub; переконайтеся, що Ви використовуєте той же аккаунт при додаванні Homebridge action в мобильному додатку Google Home.", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Потрібен перезапуск Homebridge, щоб зміни почали діяти.", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Недійсний маркер зв’язування облікового запису в config.json", "plugins.settings.deconz.dump_no_exist": "Файл дампа Homebridge deCONZ ще не існує.", "plugins.settings.hue.dump_no_exist": "Файл дампа Homebridge Hue ще не існує.", "plugins.settings.label_open_config_editor": "Відкрийте редактор конфігурацій", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 070e3a369..14d7b0163 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "搜索插件…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "已绑定", "plugins.settings.custom.homebridge-gsh.label_link_account": "绑定账号", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "解绑账号", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge 谷歌智能家庭 插件将允许您通过支持谷歌家庭的智能音箱或者手机上的谷歌家庭软件上操作 Homebridge。", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "若要使用该功能您需要使用您的谷歌账号或者 GitHub 账号登陆; 请确保您在设备间登陆的为同一账号。", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge 需要重启以生效", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "打开配置编辑器", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index 4d5a4748d..fb6d148e7 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -300,11 +300,9 @@ "plugins.placeholder_search_plugin": "搜尋 Plugin 並且安裝…", "plugins.settings.custom.homebridge-gsh.label_account_linked": "帳號已連結", "plugins.settings.custom.homebridge-gsh.label_link_account": "連結帳號", - "plugins.settings.custom.homebridge-gsh.label_unlink_account": "解除帳號連結", "plugins.settings.custom.homebridge-gsh.message_about": "Homebridge Google Smart Home Plugin 可供透過 Google Home 智能音箱或 Google Home app 控制 Homebridge 配件。", "plugins.settings.custom.homebridge-gsh.message_account_link_required": "欲啟用此功能,必須先登入 Google 或 Github 帳號;確定於 Google Home app 中新增 Homebridge 時使用了相同的帳號。", "plugins.settings.custom.homebridge-gsh.message_homebridge_restart_required": "Homebridge 需要重新啟動以期變更進行套用。", - "plugins.settings.custom.homebridge-gsh.message_invalid_token": "Invalid account linking token in config.json", "plugins.settings.deconz.dump_no_exist": "Homebridge deCONZ dump file does not exist yet.", "plugins.settings.hue.dump_no_exist": "Homebridge Hue dump file does not exist yet.", "plugins.settings.label_open_config_editor": "開啟 Config 編輯器", From c189478ecc0075042fb66c6ea692dd085f5fb6c8 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Wed, 18 Jun 2025 19:41:11 +0100 Subject: [PATCH 11/22] show lock management service info on lock mechanism info modal --- CHANGELOG.md | 1 + .../accessory-info.component.html | 24 +++++++++++++++++++ .../accessory-info.component.ts | 8 +++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 961b8b581..6a7eb579b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - improve wallpaper selection with new modal to upload a file - refactor HBv2 and UIv5 readiness modals - move backup settings from ui advanced settings to backup/restore modal +- show lock management service info on lock mechanism info modal ### Other Changes diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html index 22fb38203..d9eafa318 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html @@ -75,6 +75,30 @@
    {{ 'accessories.service_info' | translate }}
    } + @for (extraService of extraServices; track extraService) { +
      +
    • +
      {{ 'accessories.service_info' | translate }}
      +
    • +
    • + {{ 'accessories.service' | translate }} + {{ extraService.humanType }} +
    • +
    • + {{ 'accessories.name' | translate }} + {{ extraService.serviceName }} +
    • + @for (characteristic of extraService.serviceCharacteristics; track characteristic) { +
    • + {{ characteristic.description }} + + @switch (characteristic.unit) { @case ('percentage') { {{ characteristic.value }}% } @case ('celsius') { {{ + characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } +
    • + } +
    + }
    • {{ 'accessories.accessory_info' | translate }}
      diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts index ee7de7867..f7263a2d3 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts @@ -23,7 +23,9 @@ export class AccessoryInfoComponent implements OnInit { @Input() public service: ServiceTypeX @Input() private accessoryCache: any[] @Input() private pairingCache: any[] + public accessoryInformation: Array + public extraServices: ServiceTypeX[] = [] public matchedCachedAccessory: any = null constructor() {} @@ -31,6 +33,12 @@ export class AccessoryInfoComponent implements OnInit { ngOnInit() { this.accessoryInformation = Object.entries(this.service.accessoryInformation).map(([key, value]) => ({ key, value })) this.matchedCachedAccessory = this.matchToCachedAccessory() + + if (this.service.type === 'LockMechanism') { + Object.values(this.service.linkedServices) + .filter(service => service.type === 'LockManagement') + .forEach(service => this.extraServices.push(service)) + } } matchToCachedAccessory() { From 1f23e1cb023590d3201f3ec9f5565f46c6c1f36d Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Thu, 19 Jun 2025 13:48:19 +0100 Subject: [PATCH 12/22] show characteristic descriptions in info modal when available --- CHANGELOG.md | 1 + .../accessory-info/accessory-info.component.html | 12 ++++++++---- .../accessory-info/accessory-info.component.ts | 4 ++++ ui/src/app/core/pipes/prettify.pipe.ts | 16 ++++++++++++++++ 4 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 ui/src/app/core/pipes/prettify.pipe.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a7eb579b..9c1fb4e14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - refactor HBv2 and UIv5 readiness modals - move backup settings from ui advanced settings to backup/restore modal - show lock management service info on lock mechanism info modal +- show characteristic descriptions in info modal when available ### Other Changes diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html index d9eafa318..1c4736b05 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.html +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.html @@ -70,8 +70,10 @@
      {{ 'accessories.service_info' | translate }}
      {{ characteristic.description }} @switch (characteristic.unit) { @case ('percentage') { {{ characteristic.value }}% } @case ('celsius') { {{ - characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } + characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } @if + (enums[characteristic.type]?.[characteristic.value]) { ({{ enums[characteristic.type][characteristic.value] | + prettify }}) } +
    • }
    @@ -93,8 +95,10 @@
    {{ 'accessories.service_info' | translate }}
    {{ characteristic.description }} @switch (characteristic.unit) { @case ('percentage') { {{ characteristic.value }}% } @case ('celsius') { {{ - characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } + characteristic.value | convertTemp }}° } @default { {{ characteristic.value }} } } @if + (enums[characteristic.type]?.[characteristic.value]) { ({{ enums[characteristic.type][characteristic.value] | + prettify }}) } + } diff --git a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts index f7263a2d3..6e3f0cce5 100644 --- a/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts +++ b/ui/src/app/core/accessories/accessory-info/accessory-info.component.ts @@ -1,10 +1,12 @@ import { Component, inject, Input, OnInit } from '@angular/core' import { FormsModule } from '@angular/forms' +import { Enums } from '@homebridge/hap-client/dist/hap-types' import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe } from '@ngx-translate/core' import { ServiceTypeX } from '@/app/core/accessories/accessories.interfaces' import { ConvertTempPipe } from '@/app/core/pipes/convert-temp.pipe' +import { PrettifyPipe } from '@/app/core/pipes/prettify.pipe' import { RemoveIndividualAccessoriesComponent } from '@/app/modules/settings/remove-individual-accessories/remove-individual-accessories.component' @Component({ @@ -14,6 +16,7 @@ import { RemoveIndividualAccessoriesComponent } from '@/app/modules/settings/rem FormsModule, TranslatePipe, ConvertTempPipe, + PrettifyPipe, ], }) export class AccessoryInfoComponent implements OnInit { @@ -27,6 +30,7 @@ export class AccessoryInfoComponent implements OnInit { public accessoryInformation: Array public extraServices: ServiceTypeX[] = [] public matchedCachedAccessory: any = null + public enums = Enums constructor() {} diff --git a/ui/src/app/core/pipes/prettify.pipe.ts b/ui/src/app/core/pipes/prettify.pipe.ts new file mode 100644 index 000000000..8061fb182 --- /dev/null +++ b/ui/src/app/core/pipes/prettify.pipe.ts @@ -0,0 +1,16 @@ +import { Pipe, PipeTransform } from '@angular/core' + +@Pipe({ name: 'prettify' }) +export class PrettifyPipe implements PipeTransform { + transform(value: string): string { + if (typeof value !== 'string') { + return value + } + + return value + .replace(/_/g, ' ') // Replace underscores with spaces + .toLowerCase() + .replace(/\b\w/g, char => char.toUpperCase()) // Capitalize the first letter of each word + .replace(/([a-z])([A-Z])/g, '$1 $2') // Add space before uppercase letters that follow lowercase letters + } +} From 7498448cce1b341cdbd82b579ed9b04ea636dc6a Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:07:43 +0100 Subject: [PATCH 13/22] _deps_v4 --- CHANGELOG.md | 2 +- package-lock.json | 979 +++++++++++++++++++++++-------------------- package.json | 18 +- ui/package-lock.json | 340 +++++++-------- ui/package.json | 48 +-- 5 files changed, 720 insertions(+), 667 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c1fb4e14..0a5ccae0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. ### Homebridge Dependencies -- `@homebridge/hap-client` @ `v2.2.0` +- `@homebridge/hap-client` @ `v3.1.0` - `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` - `@homebridge/plugin-ui-utils` @ `v2.1.0` diff --git a/package-lock.json b/package-lock.json index cc31816d3..afe446660 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@fastify/helmet": "11.1.1", "@fastify/multipart": "8.3.1", "@fastify/static": "7.0.4", - "@homebridge/hap-client": "2.2.0", + "@homebridge/hap-client": "3.1.0", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.1.3", "@nestjs/common": "10.4.18", @@ -33,7 +33,7 @@ "@nestjs/platform-socket.io": "10.4.18", "@nestjs/swagger": "8.1.1", "@nestjs/websockets": "10.4.18", - "axios": "1.9.0", + "axios": "1.10.0", "bash-color": "0.0.4", "class-transformer": "0.5.1", "class-validator": "0.14.2", @@ -53,7 +53,7 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.2", "semver": "7.7.2", - "systeminformation": "5.27.1", + "systeminformation": "5.27.5", "tail": "2.2.6", "tar": "7.4.3", "tcp-port-used": "1.0.2", @@ -64,19 +64,19 @@ "homebridge-config-ui-x": "dist/bin/standalone.js" }, "devDependencies": { - "@antfu/eslint-config": "^4.14.1", + "@antfu/eslint-config": "^4.15.0", "@nestjs/testing": "^10.4.18", "@prettier/plugin-xml": "^3.4.1", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.17", - "@types/node": "^22.15.30", + "@types/lodash": "^4.17.18", + "@types/node": "^24.0.3", "@types/node-schedule": "^2.1.7", "@types/passport-jwt": "^4.0.1", "@types/semver": "^7.7.0", "@types/tail": "^2.2.3", "@types/tcp-port-used": "^1.0.4", "@types/unzipper": "^0.10.11", - "@vitest/coverage-v8": "^3.2.2", + "@vitest/coverage-v8": "^3.2.4", "concurrently": "^9.1.2", "eslint-plugin-format": "^1.0.1", "form-data": "^4.0.3", @@ -86,8 +86,8 @@ "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.8.3", - "unplugin-swc": "^1.5.4", - "vitest": "^3.2.2" + "unplugin-swc": "^1.5.5", + "vitest": "^3.2.4" }, "engines": { "homebridge": "^1.8.0 || ^2.0.0-beta.0", @@ -109,9 +109,9 @@ } }, "node_modules/@antfu/eslint-config": { - "version": "4.14.1", - "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.14.1.tgz", - "integrity": "sha512-SVGR33/jSUwMWvC8q3NGF/XEHWFJVfMg8yaQJDtRSGISXm23DVA/ANTADpRKhXpk7IjfnjzPpbT/+T6wFzOmUA==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/@antfu/eslint-config/-/eslint-config-4.15.0.tgz", + "integrity": "sha512-wNn8eDUR+L48nGqX0j8uS19+lHjlhjJsTuhOIbp5aUtnNzAqUuzeoGa7S7rfIbK3XnzcRXJ1AW+xWXsMSGu0YA==", "dev": true, "license": "MIT", "dependencies": { @@ -119,10 +119,10 @@ "@clack/prompts": "^0.11.0", "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/markdown": "^6.5.0", - "@stylistic/eslint-plugin": "^5.0.0-beta.1", - "@typescript-eslint/eslint-plugin": "^8.33.1", - "@typescript-eslint/parser": "^8.33.1", - "@vitest/eslint-plugin": "^1.2.1", + "@stylistic/eslint-plugin": "^5.0.0-beta.4", + "@typescript-eslint/eslint-plugin": "^8.34.1", + "@typescript-eslint/parser": "^8.34.1", + "@vitest/eslint-plugin": "^1.2.7", "ansis": "^4.1.0", "cac": "^6.7.14", "eslint-config-flat-gitignore": "^2.1.0", @@ -130,13 +130,14 @@ "eslint-merge-processors": "^2.0.0", "eslint-plugin-antfu": "^3.1.1", "eslint-plugin-command": "^3.2.1", - "eslint-plugin-jsdoc": "^50.7.1", + "eslint-plugin-import-lite": "^0.3.0", + "eslint-plugin-jsdoc": "^51.0.3", "eslint-plugin-jsonc": "^2.20.1", - "eslint-plugin-n": "^17.19.0", + "eslint-plugin-n": "^17.20.0", "eslint-plugin-no-only-tests": "^3.3.0", - "eslint-plugin-perfectionist": "^4.14.0", + "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^0.3.1", - "eslint-plugin-regexp": "^2.8.0", + "eslint-plugin-regexp": "^2.9.0", "eslint-plugin-toml": "^0.12.0", "eslint-plugin-unicorn": "^59.0.1", "eslint-plugin-unused-imports": "^4.1.4", @@ -866,9 +867,9 @@ } }, "node_modules/@eslint/compat": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.9.tgz", - "integrity": "sha512-gCdSY54n7k+driCadyMNv8JSPzYLeDVM/ikZRtvtROBpRdFSkS8W9A82MqsaY7lZuwL0wiapgD0NT1xT0hyJsA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.3.0.tgz", + "integrity": "sha512-ZBygRBqpDYiIHsN+d1WyHn3TYgzgpzLEcgJUxTATyiInQbKZz6wZb6+ljwdg8xeeOe4v03z6Uh6lELiw0/mVhQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -884,9 +885,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", + "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -900,9 +901,9 @@ } }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -926,9 +927,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.2.tgz", - "integrity": "sha512-+GPzk8PlG0sPpzdU5ZvIRMPidzAnZDl/s9L+y13iodqvb8leL53bTannOrQ/Im7UkpsmFU5Ily5U60LWixnmLg==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", + "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -975,9 +976,9 @@ } }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -1015,9 +1016,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", - "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.29.0.tgz", + "integrity": "sha512-3PIF4cBw/y+1u2EazflInpV+lYsSG0aByVIQzAgb1m1MhHFSbqTyNqtBKHgWf/9Ykud+DhILS9EGkmekVhbKoQ==", "dev": true, "license": "MIT", "peer": true, @@ -1059,19 +1060,32 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", - "integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", + "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.14.0", + "@eslint/core": "^0.15.0", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", + "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@fastify/accept-negotiator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz", @@ -1282,12 +1296,12 @@ } }, "node_modules/@homebridge/hap-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.2.0.tgz", - "integrity": "sha512-ko50uTJosoogBotV2Wf1eGKjgMe9Iy0wg6WEPSlorQnIu3Li+dcnm2SlOpE/8ijMexyMPqTVFoeU1Bo+nm4+6Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-3.1.0.tgz", + "integrity": "sha512-8w2ciWvtNqBspFN/WVpkGEOqCEg1w3XPC/haU7pJbE/GIh4g/Nt8+2t5nOivunpsE+9TY44Ily3MBEsfxFru2A==", "license": "MIT", "dependencies": { - "axios": "1.9.0", + "axios": "1.10.0", "bonjour-service": "1.3.0", "decamelize": "5.0.1", "inflection": "3.0.2", @@ -1376,6 +1390,29 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1718,9 +1755,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.18.tgz", - "integrity": "sha512-oTeGjnh1qeSZMFqze1Rz5lEtAOBRDApulWDoLYSyzh+8/jFflhCYAGeOHncItkGq9wBRe1R1Ct2GyRFdTmpcjg==", + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.19.tgz", + "integrity": "sha512-YfzkjTmwEcoWqo8xr8YiTZMC4FjBEOg4uRTAPI2p6iGLWu+27tYau1CtAKFHY0uSAK3FzgtsAuYoxBSlfr9mWA==", "dev": true, "license": "MIT", "dependencies": { @@ -1908,9 +1945,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.4.tgz", - "integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -1931,9 +1968,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz", - "integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.0.tgz", + "integrity": "sha512-xEiEE5oDW6tK4jXCAyliuntGR+amEMO7HLtdSshVuhFnKTYoeYMyXQK7pLouAJJj5KHdwdn87bfHAR2nSdNAUA==", "cpu": [ "arm" ], @@ -1945,9 +1982,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz", - "integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.0.tgz", + "integrity": "sha512-uNSk/TgvMbskcHxXYHzqwiyBlJ/lGcv8DaUfcnNwict8ba9GTTNxfn3/FAoFZYgkaXXAdrAA+SLyKplyi349Jw==", "cpu": [ "arm64" ], @@ -1959,9 +1996,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz", - "integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.0.tgz", + "integrity": "sha512-VGF3wy0Eq1gcEIkSCr8Ke03CWT+Pm2yveKLaDvq51pPpZza3JX/ClxXOCmTYYq3us5MvEuNRTaeyFThCKRQhOA==", "cpu": [ "arm64" ], @@ -1973,9 +2010,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz", - "integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.0.tgz", + "integrity": "sha512-fBkyrDhwquRvrTxSGH/qqt3/T0w5Rg0L7ZIDypvBPc1/gzjJle6acCpZ36blwuwcKD/u6oCE/sRWlUAcxLWQbQ==", "cpu": [ "x64" ], @@ -1987,9 +2024,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz", - "integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.0.tgz", + "integrity": "sha512-u5AZzdQJYJXByB8giQ+r4VyfZP+walV+xHWdaFx/1VxsOn6eWJhK2Vl2eElvDJFKQBo/hcYIBg/jaKS8ZmKeNQ==", "cpu": [ "arm64" ], @@ -2001,9 +2038,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz", - "integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.0.tgz", + "integrity": "sha512-qC0kS48c/s3EtdArkimctY7h3nHicQeEUdjJzYVJYR3ct3kWSafmn6jkNCA8InbUdge6PVx6keqjk5lVGJf99g==", "cpu": [ "x64" ], @@ -2015,9 +2052,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz", - "integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.0.tgz", + "integrity": "sha512-x+e/Z9H0RAWckn4V2OZZl6EmV0L2diuX3QB0uM1r6BvhUIv6xBPL5mrAX2E3e8N8rEHVPwFfz/ETUbV4oW9+lQ==", "cpu": [ "arm" ], @@ -2029,9 +2066,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz", - "integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.0.tgz", + "integrity": "sha512-1exwiBFf4PU/8HvI8s80icyCcnAIB86MCBdst51fwFmH5dyeoWVPVgmQPcKrMtBQ0W5pAs7jBCWuRXgEpRzSCg==", "cpu": [ "arm" ], @@ -2043,9 +2080,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz", - "integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.0.tgz", + "integrity": "sha512-ZTR2mxBHb4tK4wGf9b8SYg0Y6KQPjGpR4UWwTFdnmjB4qRtoATZ5dWn3KsDwGa5Z2ZBOE7K52L36J9LueKBdOQ==", "cpu": [ "arm64" ], @@ -2057,9 +2094,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz", - "integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.0.tgz", + "integrity": "sha512-GFWfAhVhWGd4r6UxmnKRTBwP1qmModHtd5gkraeW2G490BpFOZkFtem8yuX2NyafIP/mGpRJgTJ2PwohQkUY/Q==", "cpu": [ "arm64" ], @@ -2071,9 +2108,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz", - "integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.0.tgz", + "integrity": "sha512-xw+FTGcov/ejdusVOqKgMGW3c4+AgqrfvzWEVXcNP6zq2ue+lsYUgJ+5Rtn/OTJf7e2CbgTFvzLW2j0YAtj0Gg==", "cpu": [ "loong64" ], @@ -2085,9 +2122,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz", - "integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.0.tgz", + "integrity": "sha512-bKGibTr9IdF0zr21kMvkZT4K6NV+jjRnBoVMt2uNMG0BYWm3qOVmYnXKzx7UhwrviKnmK46IKMByMgvpdQlyJQ==", "cpu": [ "ppc64" ], @@ -2099,9 +2136,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz", - "integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.0.tgz", + "integrity": "sha512-vV3cL48U5kDaKZtXrti12YRa7TyxgKAIDoYdqSIOMOFBXqFj2XbChHAtXquEn2+n78ciFgr4KIqEbydEGPxXgA==", "cpu": [ "riscv64" ], @@ -2113,9 +2150,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz", - "integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.0.tgz", + "integrity": "sha512-TDKO8KlHJuvTEdfw5YYFBjhFts2TR0VpZsnLLSYmB7AaohJhM8ctDSdDnUGq77hUh4m/djRafw+9zQpkOanE2Q==", "cpu": [ "riscv64" ], @@ -2127,9 +2164,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz", - "integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.0.tgz", + "integrity": "sha512-8541GEyktXaw4lvnGp9m84KENcxInhAt6vPWJ9RodsB/iGjHoMB2Pp5MVBCiKIRxrxzJhGCxmNzdu+oDQ7kwRA==", "cpu": [ "s390x" ], @@ -2141,9 +2178,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz", - "integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.0.tgz", + "integrity": "sha512-iUVJc3c0o8l9Sa/qlDL2Z9UP92UZZW1+EmQ4xfjTc1akr0iUFZNfxrXJ/R1T90h/ILm9iXEY6+iPrmYB3pXKjw==", "cpu": [ "x64" ], @@ -2155,9 +2192,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz", - "integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.0.tgz", + "integrity": "sha512-PQUobbhLTQT5yz/SPg116VJBgz+XOtXt8D1ck+sfJJhuEsMj2jSej5yTdp8CvWBSceu+WW+ibVL6dm0ptG5fcA==", "cpu": [ "x64" ], @@ -2169,9 +2206,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz", - "integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.0.tgz", + "integrity": "sha512-M0CpcHf8TWn+4oTxJfh7LQuTuaYeXGbk0eageVjQCKzYLsajWS/lFC94qlRqOlyC2KvRT90ZrfXULYmukeIy7w==", "cpu": [ "arm64" ], @@ -2183,9 +2220,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz", - "integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.0.tgz", + "integrity": "sha512-3XJ0NQtMAXTWFW8FqZKcw3gOQwBtVWP/u8TpHP3CRPXD7Pd6s8lLdH3sHWh8vqKCyyiI8xW5ltJScQmBU9j7WA==", "cpu": [ "ia32" ], @@ -2197,9 +2234,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz", - "integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.0.tgz", + "integrity": "sha512-Q2Mgwt+D8hd5FIPUuPDsvPR7Bguza6yTkJxspDGkZj7tBRn2y4KSWYuIXpftFSjBra76TbKerCV7rgFPQrn+wQ==", "cpu": [ "x64" ], @@ -2224,9 +2261,9 @@ "license": "MIT" }, "node_modules/@stylistic/eslint-plugin": { - "version": "5.0.0-beta.3", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.0.0-beta.3.tgz", - "integrity": "sha512-ItDjyhRyc5hx4W/IBy4/EhgPLbTrjeVPgcYG65pZApTg8Prf1nsWz0j7AY/nYd7OqzBAuRSmzrYFlab86ybePw==", + "version": "5.0.0-beta.4", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.0.0-beta.4.tgz", + "integrity": "sha512-PAaqrIp/MthaP6D9x+hACiddzM3hI5mf2ZfqGVy6Ohp5xY1yJUT95L2m8Q8oerHLGnpOF1jy6Z4CRbOdZeUM3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2244,16 +2281,16 @@ } }, "node_modules/@swc/core": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.31.tgz", - "integrity": "sha512-mAby9aUnKRjMEA7v8cVZS9Ah4duoRBnX7X6r5qrhTxErx+68MoY1TPrVwj/66/SWN3Bl+jijqAqoB8Qx0QE34A==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.12.3.tgz", + "integrity": "sha512-c4NeXW8P3gPqcFwtm+4aH+F2Cj5KJLMiLaKhSj3mpv19glq+jmekomdktAw/VHyjsXlsmouOeNWrk8rVlkCRsg==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", "peer": true, "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.21" + "@swc/types": "^0.1.23" }, "engines": { "node": ">=10" @@ -2263,16 +2300,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.11.31", - "@swc/core-darwin-x64": "1.11.31", - "@swc/core-linux-arm-gnueabihf": "1.11.31", - "@swc/core-linux-arm64-gnu": "1.11.31", - "@swc/core-linux-arm64-musl": "1.11.31", - "@swc/core-linux-x64-gnu": "1.11.31", - "@swc/core-linux-x64-musl": "1.11.31", - "@swc/core-win32-arm64-msvc": "1.11.31", - "@swc/core-win32-ia32-msvc": "1.11.31", - "@swc/core-win32-x64-msvc": "1.11.31" + "@swc/core-darwin-arm64": "1.12.3", + "@swc/core-darwin-x64": "1.12.3", + "@swc/core-linux-arm-gnueabihf": "1.12.3", + "@swc/core-linux-arm64-gnu": "1.12.3", + "@swc/core-linux-arm64-musl": "1.12.3", + "@swc/core-linux-x64-gnu": "1.12.3", + "@swc/core-linux-x64-musl": "1.12.3", + "@swc/core-win32-arm64-msvc": "1.12.3", + "@swc/core-win32-ia32-msvc": "1.12.3", + "@swc/core-win32-x64-msvc": "1.12.3" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -2284,9 +2321,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.31.tgz", - "integrity": "sha512-NTEaYOts0OGSbJZc0O74xsji+64JrF1stmBii6D5EevWEtrY4wlZhm8SiP/qPrOB+HqtAihxWIukWkP2aSdGSQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.3.tgz", + "integrity": "sha512-QCV9vQ/s27AMxm8j8MTDL/nDoiEMrANiENRrWnb0Fxvz/O39CajPVShp/W7HlOkzt1GYtUXPdQJpSKylugfrWw==", "cpu": [ "arm64" ], @@ -2302,9 +2339,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.31.tgz", - "integrity": "sha512-THSGaSwT96JwXDwuXQ6yFBbn+xDMdyw7OmBpnweAWsh5DhZmQkALEm1DgdQO3+rrE99MkmzwAfclc0UmYro/OA==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.12.3.tgz", + "integrity": "sha512-LylCMfzGhdvl5tyKaTT9ePetHUX7wSsST7hxWiHzS+cUMj7FnhcfdEr6kcNVT7y1RJn3fCvuv7T98ZB+T2q3HA==", "cpu": [ "x64" ], @@ -2320,9 +2357,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.31.tgz", - "integrity": "sha512-laKtQFnW7KHgE57Hx32os2SNAogcuIDxYE+3DYIOmDMqD7/1DCfJe6Rln2N9WcOw6HuDbDpyQavIwZNfSAa8vQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.12.3.tgz", + "integrity": "sha512-DQODb7S+q+pwQY41Azcavwb2rb4rGxP70niScRDxB9X68hHOM9D0w9fxzC+Nr3AHcPSmVJUYUIiq5h38O5hVgQ==", "cpu": [ "arm" ], @@ -2338,9 +2375,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.31.tgz", - "integrity": "sha512-T+vGw9aPE1YVyRxRr1n7NAdkbgzBzrXCCJ95xAZc/0+WUwmL77Z+js0J5v1KKTRxw4FvrslNCOXzMWrSLdwPSA==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.3.tgz", + "integrity": "sha512-nTxtJSq78AjeaQBueYImoFBs5j7qXbgOxtirpyt8jE29NQBd0VFzDzRBhkr6I9jq0hNiChgMkqBN4eUkEQjytg==", "cpu": [ "arm64" ], @@ -2356,9 +2393,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.31.tgz", - "integrity": "sha512-Mztp5NZkyd5MrOAG+kl+QSn0lL4Uawd4CK4J7wm97Hs44N9DHGIG5nOz7Qve1KZo407Y25lTxi/PqzPKHo61zQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.12.3.tgz", + "integrity": "sha512-lBGvC5UgPSxqLr/y1NZxQhyRQ7nXy3/Ec1Z47YNXtqtpKiG1EcOGPyS0UZgwiYQkXqq8NBFMHnyHmpKnXTvRDA==", "cpu": [ "arm64" ], @@ -2374,9 +2411,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.31.tgz", - "integrity": "sha512-DDVE0LZcXOWwOqFU1Xi7gdtiUg3FHA0vbGb3trjWCuI1ZtDZHEQYL4M3/2FjqKZtIwASrDvO96w91okZbXhvMg==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.3.tgz", + "integrity": "sha512-61wZ8hwxNYzBY9MCWB50v90ICzdIhOuPk1O1qXswz9AXw5O6iQStEBHQ1rozPkfQ/rmhepk0pOf/6LCwssJOwg==", "cpu": [ "x64" ], @@ -2392,9 +2429,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.31.tgz", - "integrity": "sha512-mJA1MzPPRIfaBUHZi0xJQ4vwL09MNWDeFtxXb0r4Yzpf0v5Lue9ymumcBPmw/h6TKWms+Non4+TDquAsweuKSw==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.12.3.tgz", + "integrity": "sha512-NNeBiTpCgWt80vumTKVoaj6Fa/ZjUcaNQNM7np3PIgB8EbuXfyztboV7vUxpkmD/lUgsk8GlEFYViHvo6VMefQ==", "cpu": [ "x64" ], @@ -2410,9 +2447,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.31.tgz", - "integrity": "sha512-RdtakUkNVAb/FFIMw3LnfNdlH1/ep6KgiPDRlmyUfd0WdIQ3OACmeBegEFNFTzi7gEuzy2Yxg4LWf4IUVk8/bg==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.12.3.tgz", + "integrity": "sha512-fxraM7exaPb1/W0CoHW45EFNOQUQh0nonBEcNFm2iv095mziBwttyxZyQBoDkQocpkd5NtsZw3xW5FTBPnn+Vw==", "cpu": [ "arm64" ], @@ -2428,9 +2465,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.31.tgz", - "integrity": "sha512-hErXdCGsg7swWdG1fossuL8542I59xV+all751mYlBoZ8kOghLSKObGQTkBbuNvc0sUKWfWg1X0iBuIhAYar+w==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.12.3.tgz", + "integrity": "sha512-FFIhMPXIDjRcewomwbYGPvem7Fj76AsuzbRahnAyp+OzJwrrtxVmra/kyUCfj4kix7vdGByY0WvVfiVCf5b7Mg==", "cpu": [ "ia32" ], @@ -2446,9 +2483,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.31", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.31.tgz", - "integrity": "sha512-5t7SGjUBMMhF9b5j17ml/f/498kiBJNf4vZFNM421UGUEETdtjPN9jZIuQrowBkoFGJTCVL/ECM4YRtTH30u/A==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.12.3.tgz", + "integrity": "sha512-Sf4iSg+IYT5AzFSDDmii08DfeKcvtkVxIuo+uS8BJMbiLjFNjgMkkVlBthknGyJcSK15ncg9248XjnM4jU8DZA==", "cpu": [ "x64" ], @@ -2472,9 +2509,9 @@ "peer": true }, "node_modules/@swc/types": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.22.tgz", - "integrity": "sha512-D13mY/ZA4PPEFSy6acki9eBT/3WgjMoRqNcdpIvjaYLQ44Xk5BdaL7UkDxAh6Z9UOe7tCCp67BVmZCojYp9owg==", + "version": "0.1.23", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.23.tgz", + "integrity": "sha512-u1iIVZV9Q0jxY+yM2vw/hZGDNudsN85bBpTqzAQ9rzkxW9D+e3aEM4Han+ow518gSewkXgjmEK0BD79ZcNVgPw==", "dev": true, "license": "Apache-2.0", "peer": true, @@ -2692,9 +2729,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.18.tgz", + "integrity": "sha512-KJ65INaxqxmU6EoCiJmRPZC9H9RVWCRd349tXM2M3O5NA7cY6YL7c0bHAHQ93NOfTObEQ004kd2QVHs/r0+m4g==", "dev": true, "license": "MIT" }, @@ -2723,12 +2760,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz", + "integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/node-schedule": { @@ -2849,23 +2886,23 @@ } }, "node_modules/@types/validator": { - "version": "13.15.1", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.1.tgz", - "integrity": "sha512-9gG6ogYcoI2mCMLdcO0NYI0AYrbxIjv0MDmy/5Ywo6CpWWrqYayc+mmgxRsCgtcGJm9BSbXkMsmxGah1iGHAAQ==", + "version": "13.15.2", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.2.tgz", + "integrity": "sha512-y7pa/oEJJ4iGYBxOpfAKn5b9+xuihvzDVnC/OSvlVnGxVg0pOqmjiMafiJ1KVNQEaPZf9HsEp5icEwGg8uIe5Q==", "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", - "integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.34.1.tgz", + "integrity": "sha512-STXcN6ebF6li4PxwNeFnqF8/2BNDvBupf2OPx2yWNzr6mKNGF7q49VM00Pz5FaomJyqvbXpY6PhO+T9w139YEQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/type-utils": "8.33.1", - "@typescript-eslint/utils": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.34.1", + "@typescript-eslint/type-utils": "8.34.1", + "@typescript-eslint/utils": "8.34.1", + "@typescript-eslint/visitor-keys": "8.34.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -2879,7 +2916,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.33.1", + "@typescript-eslint/parser": "^8.34.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } @@ -2895,16 +2932,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz", - "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.34.1.tgz", + "integrity": "sha512-4O3idHxhyzjClSMJ0a29AcoK0+YwnEqzI6oz3vlRf3xw0zbzt15MzXwItOlnr5nIth6zlY2RENLsOPvhyrKAQA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/scope-manager": "8.34.1", + "@typescript-eslint/types": "8.34.1", + "@typescript-eslint/typescript-estree": "8.34.1", + "@typescript-eslint/visitor-keys": "8.34.1", "debug": "^4.3.4" }, "engines": { @@ -2920,14 +2957,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz", - "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.34.1.tgz", + "integrity": "sha512-nuHlOmFZfuRwLJKDGQOVc0xnQrAmuq1Mj/ISou5044y1ajGNp2BNliIqp7F2LPQ5sForz8lempMFCovfeS1XoA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.33.1", - "@typescript-eslint/types": "^8.33.1", + "@typescript-eslint/tsconfig-utils": "^8.34.1", + "@typescript-eslint/types": "^8.34.1", "debug": "^4.3.4" }, "engines": { @@ -2942,14 +2979,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz", - "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.34.1.tgz", + "integrity": "sha512-beu6o6QY4hJAgL1E8RaXNC071G4Kso2MGmJskCFQhRhg8VOH/FDbC8soP8NHN7e/Hdphwp8G8cE6OBzC8o41ZA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1" + "@typescript-eslint/types": "8.34.1", + "@typescript-eslint/visitor-keys": "8.34.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2960,9 +2997,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz", - "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.34.1.tgz", + "integrity": "sha512-K4Sjdo4/xF9NEeA2khOb7Y5nY6NSXBnod87uniVYW9kHP+hNlDV8trUSFeynA2uxWam4gIWgWoygPrv9VMWrYg==", "dev": true, "license": "MIT", "engines": { @@ -2977,14 +3014,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz", - "integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.34.1.tgz", + "integrity": "sha512-Tv7tCCr6e5m8hP4+xFugcrwTOucB8lshffJ6zf1mF1TbU67R+ntCc6DzLNKM+s/uzDyv8gLq7tufaAhIBYeV8g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.33.1", - "@typescript-eslint/utils": "8.33.1", + "@typescript-eslint/typescript-estree": "8.34.1", + "@typescript-eslint/utils": "8.34.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3001,9 +3038,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", - "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.34.1.tgz", + "integrity": "sha512-rjLVbmE7HR18kDsjNIZQHxmv9RZwlgzavryL5Lnj2ujIRTeXlKtILHgRNmQ3j4daw7zd+mQgy+uyt6Zo6I0IGA==", "dev": true, "license": "MIT", "engines": { @@ -3015,16 +3052,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz", - "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.34.1.tgz", + "integrity": "sha512-rjCNqqYPuMUF5ODD+hWBNmOitjBWghkGKJg6hiCHzUvXRy6rK22Jd3rwbP2Xi+R7oYVvIKhokHVhH41BxPV5mA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.33.1", - "@typescript-eslint/tsconfig-utils": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/visitor-keys": "8.33.1", + "@typescript-eslint/project-service": "8.34.1", + "@typescript-eslint/tsconfig-utils": "8.34.1", + "@typescript-eslint/types": "8.34.1", + "@typescript-eslint/visitor-keys": "8.34.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3044,16 +3081,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz", - "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.34.1.tgz", + "integrity": "sha512-mqOwUdZ3KjtGk7xJJnLbHxTuWVn3GO2WZZuM+Slhkun4+qthLdXx32C8xIXbO1kfCECb3jIs3eoxK3eryk7aoQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.33.1", - "@typescript-eslint/types": "8.33.1", - "@typescript-eslint/typescript-estree": "8.33.1" + "@typescript-eslint/scope-manager": "8.34.1", + "@typescript-eslint/types": "8.34.1", + "@typescript-eslint/typescript-estree": "8.34.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3068,14 +3105,14 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.33.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz", - "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==", + "version": "8.34.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.34.1.tgz", + "integrity": "sha512-xoh5rJ+tgsRKoXnkBPFRLZ7rjKM0AfVbC68UZ/ECXoDbfggb9RbEySN359acY1vS3qZ0jVTVWzbtfapwm5ztxw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.33.1", - "eslint-visitor-keys": "^4.2.0" + "@typescript-eslint/types": "8.34.1", + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3086,9 +3123,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.2.tgz", - "integrity": "sha512-RVAi5xnqedSKvaoQyCTWvncMk8eYZcTTOsLK7XmnfOEvdGP/O/upA0/MA8Ss+Qs++mj0GcSRi/whR0S5iBPpTQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz", + "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3110,8 +3147,8 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "@vitest/browser": "3.2.2", - "vitest": "3.2.2" + "@vitest/browser": "3.2.4", + "vitest": "3.2.4" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -3120,13 +3157,13 @@ } }, "node_modules/@vitest/eslint-plugin": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.1.tgz", - "integrity": "sha512-JQr1jdVcrsoS7Sdzn83h9sq4DvREf9Q/onTZbJCqTVlv/76qb+TZrLv/9VhjnjSMHweQH5FdpMDeCR6aDe2fgw==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@vitest/eslint-plugin/-/eslint-plugin-1.2.7.tgz", + "integrity": "sha512-7WHcGZo6uXsE4SsSnpGDqKyGrd6NfOMM52WKoHSpTRZLbjMuDyHfA5P7m8yrr73tpqYjsiAdSjSerOnx8uEhpA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/utils": "^8.24.0" + "@typescript-eslint/utils": "^8.24.1" }, "peerDependencies": { "eslint": ">= 8.57.0", @@ -3143,15 +3180,15 @@ } }, "node_modules/@vitest/expect": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.2.tgz", - "integrity": "sha512-ipHw0z669vEMjzz3xQE8nJX1s0rQIb7oEl4jjl35qWTwm/KIHERIg/p/zORrjAaZKXfsv7IybcNGHwhOOAPMwQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" }, @@ -3160,13 +3197,13 @@ } }, "node_modules/@vitest/mocker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", - "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "3.2.2", + "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, @@ -3197,9 +3234,9 @@ } }, "node_modules/@vitest/pretty-format": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", - "integrity": "sha512-FY4o4U1UDhO9KMd2Wee5vumwcaHw7Vg4V7yR4Oq6uK34nhEJOmdRYrk3ClburPRUA09lXD/oXWZ8y/Sdma0aUQ==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", "dev": true, "license": "MIT", "dependencies": { @@ -3210,27 +3247,28 @@ } }, "node_modules/@vitest/runner": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.2.tgz", - "integrity": "sha512-GYcHcaS3ejGRZYed2GAkvsjBeXIEerDKdX3orQrBJqLRiea4NSS9qvn9Nxmuy1IwIB+EjFOaxXnX79l8HFaBwg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/utils": "3.2.2", - "pathe": "^2.0.3" + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.2.tgz", - "integrity": "sha512-aMEI2XFlR1aNECbBs5C5IZopfi5Lb8QJZGGpzS8ZUHML5La5wCbrbhLOVSME68qwpT05ROEEOAZPRXFpxZV2wA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", + "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" }, @@ -3239,9 +3277,9 @@ } }, "node_modules/@vitest/spy": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.2.tgz", - "integrity": "sha512-6Utxlx3o7pcTxvp0u8kUiXtRFScMrUg28KjB3R2hon7w4YqOFAEA9QwzPVVS1QNL3smo4xRNOpNZClRVfpMcYg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", "dev": true, "license": "MIT", "dependencies": { @@ -3252,14 +3290,14 @@ } }, "node_modules/@vitest/utils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.2.tgz", - "integrity": "sha512-qJYMllrWpF/OYfWHP32T31QCaLa3BAzT/n/8mNGhPdVcjY+JYazQFO1nsJvXU12Kp1xMpNY4AGuljPTNjQve6A==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "3.2.2", - "loupe": "^3.1.3", + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" }, "funding": { @@ -3267,67 +3305,67 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.16.tgz", - "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.17.tgz", + "integrity": "sha512-Xe+AittLbAyV0pabcN7cP7/BenRBNcteM4aSDCtRvGw0d9OL+HG1u/XHLY/kt1q4fyMeZYXyIYrsHuPSiDPosA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.2", - "@vue/shared": "3.5.16", + "@babel/parser": "^7.27.5", + "@vue/shared": "3.5.17", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz", - "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.17.tgz", + "integrity": "sha512-+2UgfLKoaNLhgfhV5Ihnk6wB4ljyW1/7wUIog2puUqajiC29Lp5R/IKDdkebh9jTbTogTbsgB+OY9cEWzG95JQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-core": "3.5.16", - "@vue/shared": "3.5.16" + "@vue/compiler-core": "3.5.17", + "@vue/shared": "3.5.17" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz", - "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.17.tgz", + "integrity": "sha512-rQQxbRJMgTqwRugtjw0cnyQv9cP4/4BxWfTdRBkqsTfLOHWykLzbOc3C4GGzAmdMDxhzU/1Ija5bTjMVrddqww==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@babel/parser": "^7.27.2", - "@vue/compiler-core": "3.5.16", - "@vue/compiler-dom": "3.5.16", - "@vue/compiler-ssr": "3.5.16", - "@vue/shared": "3.5.16", + "@babel/parser": "^7.27.5", + "@vue/compiler-core": "3.5.17", + "@vue/compiler-dom": "3.5.17", + "@vue/compiler-ssr": "3.5.17", + "@vue/shared": "3.5.17", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", - "postcss": "^8.5.3", + "postcss": "^8.5.6", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz", - "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.17.tgz", + "integrity": "sha512-hkDbA0Q20ZzGgpj5uZjb9rBzQtIHLS78mMilwrlpWk2Ep37DYntUz0PonQ6kr113vfOEdM+zTBuJDaceNIW0tQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@vue/compiler-dom": "3.5.16", - "@vue/shared": "3.5.16" + "@vue/compiler-dom": "3.5.17", + "@vue/shared": "3.5.17" } }, "node_modules/@vue/shared": { - "version": "3.5.16", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.16.tgz", - "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==", + "version": "3.5.17", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.17.tgz", + "integrity": "sha512-CabR+UN630VnsJO/jHWYBC1YVXyMq94KKp6iF5MQgZJs5I8cmjw6oVMO1oDbtBkENSHSSn/UadWlW/OAgdmKrg==", "dev": true, "license": "MIT", "peer": true @@ -3554,9 +3592,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3813,9 +3851,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3912,9 +3950,9 @@ "license": "ISC" }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -4050,9 +4088,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "dev": true, "funding": [ { @@ -4503,13 +4541,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.25.0" }, "funding": { "type": "opencollective", @@ -4617,9 +4655,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", - "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -4833,9 +4871,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "version": "1.5.170", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz", + "integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==", "dev": true, "license": "ISC" }, @@ -4846,9 +4884,9 @@ "license": "MIT" }, "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -5060,20 +5098,20 @@ } }, "node_modules/eslint": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", - "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", + "version": "9.29.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.29.0.tgz", + "integrity": "sha512-GsGizj2Y1rCWDu6XoEekL3RLilp0voSePurjZIkxL3wlm5o5EC9VpgaP7lrCvjnkuLvzFBQWB3vWB3K5KQTveQ==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", + "@eslint/config-array": "^0.20.1", "@eslint/config-helpers": "^0.2.1", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.28.0", + "@eslint/js": "9.29.0", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", @@ -5085,9 +5123,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5313,10 +5351,33 @@ "eslint": "^8.40.0 || ^9.0.0" } }, + "node_modules/eslint-plugin-import-lite": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import-lite/-/eslint-plugin-import-lite-0.3.0.tgz", + "integrity": "sha512-dkNBAL6jcoCsXZsQ/Tt2yXmMDoNt5NaBh/U7yvccjiK8cai6Ay+MK77bMykmqQA2bTF6lngaLCDij6MTO3KkvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.34.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=4.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/eslint-plugin-jsdoc": { - "version": "50.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-50.7.1.tgz", - "integrity": "sha512-XBnVA5g2kUVokTNUiE1McEPse5n9/mNUmuJcx52psT6zBs2eVcXSmQBvjfa7NZdfLVSy3u1pEDDUxoxpwy89WA==", + "version": "51.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-51.0.3.tgz", + "integrity": "sha512-9BRR+b5nKwp6LGTffnrxKxduhzO/DzyBmRNqyt1wIlBFP+q9mq+sq1hIQCVetZAn1PaOl0Evo4PUOlT+xbtctQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5332,7 +5393,7 @@ "spdx-expression-parse": "^4.0.0" }, "engines": { - "node": ">=18" + "node": ">=20.11.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" @@ -5394,9 +5455,9 @@ } }, "node_modules/eslint-plugin-n": { - "version": "17.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.19.0.tgz", - "integrity": "sha512-qxn1NaDHtizbhVAPpbMT8wWFaLtPnwhfN/e+chdu2i6Vgzmo/tGM62tcJ1Hf7J5Ie4dhse3DOPMmDxduzfifzw==", + "version": "17.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.20.0.tgz", + "integrity": "sha512-IRSoatgB/NQJZG5EeTbv/iAx1byOGdbbyhQrNvWdCfTnmPxUT0ao9/eGOeG7ljD8wJBsxwE8f6tES5Db0FRKEw==", "dev": true, "license": "MIT", "dependencies": { @@ -5445,14 +5506,14 @@ } }, "node_modules/eslint-plugin-perfectionist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.14.0.tgz", - "integrity": "sha512-BkhiOqzdum8vQSFgj1/q5+6UUWPMn4GELdxuX7uIsGegmAeH/+LnWsiVxgMrxalD0p68sYfMeKaHF1NfrpI/mg==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.15.0.tgz", + "integrity": "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "^8.33.1", - "@typescript-eslint/utils": "^8.33.1", + "@typescript-eslint/types": "^8.34.1", + "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "engines": { @@ -5491,9 +5552,9 @@ } }, "node_modules/eslint-plugin-regexp": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.8.0.tgz", - "integrity": "sha512-xme90IvkMgdyS+NJC21FM0H6ek4urGsdlIFTXpZRqH2BKJKVSd8hRbyrCpbcqfGBi2jth3eQoLiO3RC1gxZHiw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-2.9.0.tgz", + "integrity": "sha512-9WqJMnOq8VlE/cK+YAo9C9YHhkOtcEtEk9d12a+H7OSZFwlpI6stiHmYPGa2VE0QhTzodJyhlyprUaXDZLgHBw==", "dev": true, "license": "MIT", "dependencies": { @@ -5672,9 +5733,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -5689,9 +5750,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -5702,9 +5763,9 @@ } }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "peer": true, @@ -5728,15 +5789,15 @@ } }, "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.14.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" + "eslint-visitor-keys": "^4.2.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5830,9 +5891,9 @@ } }, "node_modules/exsolve": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.5.tgz", - "integrity": "sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.6.tgz", + "integrity": "sha512-Q05uIdxhPBVBwK29gcPsl2K220xSBy52TZQPdeYWE0zOs8jM+yJ6y5h7jm6cpAo1p+OOMZRIj/Ftku4EQQBLnQ==", "dev": true, "license": "MIT" }, @@ -6097,9 +6158,9 @@ } }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -7328,9 +7389,9 @@ } }, "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.4.tgz", + "integrity": "sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==", "dev": true, "license": "MIT" }, @@ -8668,9 +8729,9 @@ } }, "node_modules/nodemon/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -9054,19 +9115,6 @@ "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" }, - "node_modules/peek-readable": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-7.0.0.tgz", - "integrity": "sha512-nri2TO5JE3/mRryik9LlHFT53cgHfRK0Lt0BAZQXku/AW3E6XLt2GaY8siWi7dvW/m1z0ecn+J+bpDa9ZN3IsQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -9183,9 +9231,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -9329,9 +9377,9 @@ "license": "MIT" }, "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -9658,15 +9706,15 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", - "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "dev": true, "license": "ISC", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -9708,13 +9756,13 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "@isaacs/brace-expansion": "^5.0.0" }, "engines": { "node": "20 || >=22" @@ -9741,13 +9789,13 @@ } }, "node_modules/rollup": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz", - "integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.0.tgz", + "integrity": "sha512-qHcdEzLCiktQIfwBq420pn2dP+30uzqYxv9ETm91wdt2R9AFcWfjNAmje4NWlnCIQ5RMTzVf0ZyisOKqHR6RwA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -9757,36 +9805,29 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.42.0", - "@rollup/rollup-android-arm64": "4.42.0", - "@rollup/rollup-darwin-arm64": "4.42.0", - "@rollup/rollup-darwin-x64": "4.42.0", - "@rollup/rollup-freebsd-arm64": "4.42.0", - "@rollup/rollup-freebsd-x64": "4.42.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.42.0", - "@rollup/rollup-linux-arm-musleabihf": "4.42.0", - "@rollup/rollup-linux-arm64-gnu": "4.42.0", - "@rollup/rollup-linux-arm64-musl": "4.42.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.42.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-musl": "4.42.0", - "@rollup/rollup-linux-s390x-gnu": "4.42.0", - "@rollup/rollup-linux-x64-gnu": "4.42.0", - "@rollup/rollup-linux-x64-musl": "4.42.0", - "@rollup/rollup-win32-arm64-msvc": "4.42.0", - "@rollup/rollup-win32-ia32-msvc": "4.42.0", - "@rollup/rollup-win32-x64-msvc": "4.42.0", + "@rollup/rollup-android-arm-eabi": "4.44.0", + "@rollup/rollup-android-arm64": "4.44.0", + "@rollup/rollup-darwin-arm64": "4.44.0", + "@rollup/rollup-darwin-x64": "4.44.0", + "@rollup/rollup-freebsd-arm64": "4.44.0", + "@rollup/rollup-freebsd-x64": "4.44.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.0", + "@rollup/rollup-linux-arm-musleabihf": "4.44.0", + "@rollup/rollup-linux-arm64-gnu": "4.44.0", + "@rollup/rollup-linux-arm64-musl": "4.44.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.0", + "@rollup/rollup-linux-riscv64-gnu": "4.44.0", + "@rollup/rollup-linux-riscv64-musl": "4.44.0", + "@rollup/rollup-linux-s390x-gnu": "4.44.0", + "@rollup/rollup-linux-x64-gnu": "4.44.0", + "@rollup/rollup-linux-x64-musl": "4.44.0", + "@rollup/rollup-win32-arm64-msvc": "4.44.0", + "@rollup/rollup-win32-ia32-msvc": "4.44.0", + "@rollup/rollup-win32-x64-msvc": "4.44.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -10458,14 +10499,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/strtok3": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.2.2.tgz", - "integrity": "sha512-Xt18+h4s7Z8xyZ0tmBoRmzxcop97R4BAh+dXouUDCYn+Em+1P3qpkUfI5ueWLT8ynC5hZ+q4iPEmGG1urvQGBg==", + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.1.tgz", + "integrity": "sha512-3JWEZM6mfix/GCJBBUrkA8p2Id2pBkyTkVCJKto55w080QBKZ+8R171fGrbiSp+yMO/u6F8/yUh7K4V9K+YCnw==", "license": "MIT", "dependencies": { - "@tokenizer/token": "^0.3.0", - "peek-readable": "^7.0.0" + "@tokenizer/token": "^0.3.0" }, "engines": { "node": ">=18" @@ -10514,9 +10567,9 @@ } }, "node_modules/systeminformation": { - "version": "5.27.1", - "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.1.tgz", - "integrity": "sha512-FgkVpT6GgATtNvADgtEzDxI/SVaBisfnQ4fmgQZhCJ4335noTgt9q6O81ioHwzs9HgnJaaFSdHSEMIkneZ55iA==", + "version": "5.27.5", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.5.tgz", + "integrity": "sha512-Kw8gAew7cvOMbCYISLeyf7e18p8/XaMz9lxARPlIsDatROB3yIS3xulfzD+lYHWe63vsddOCzDZBHt4E2yuq0Q==", "license": "MIT", "os": [ "darwin", @@ -10643,9 +10696,9 @@ "license": "MIT" }, "node_modules/terser": { - "version": "5.41.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.41.0.tgz", - "integrity": "sha512-H406eLPXpZbAX14+B8psIuvIr8+3c+2hkuYzpMkoE0ij+NdsVATbA78vb8neA/eqrj7rywa2pIkdmWRsXW6wmw==", + "version": "5.43.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", + "integrity": "sha512-+6erLbBm0+LROX2sPXlUYx/ux5PyE9K/a92Wrt6oA+WDAoFTdpHE5tCYCI5PNzq2y8df4rA+QgHLJuR4jNymsg==", "dev": true, "license": "BSD-2-Clause", "peer": true, @@ -10776,9 +10829,9 @@ } }, "node_modules/tinypool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.0.tgz", - "integrity": "sha512-7CotroY9a8DKsKprEy/a14aCCm8jYVmR7aFy4fpkZM8sdpNJbKkixuNjgM50yCmip2ezc8z4N7k3oe2+rfRJCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", "dev": true, "license": "MIT", "engines": { @@ -11118,9 +11171,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "license": "MIT" }, "node_modules/unist-util-is": { @@ -11207,13 +11260,13 @@ } }, "node_modules/unplugin-swc": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.4.tgz", - "integrity": "sha512-NYa0rEUI8+Ckr+azVyAWIBWOrqnoWsDeHPLCMAsEWXJzkNwG1GtYf/Fe872ulOPKRmQsY1VEd20d5Y3fLiiZQQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/unplugin-swc/-/unplugin-swc-1.5.5.tgz", + "integrity": "sha512-BahYtYvQ/KSgOqHoy5FfQgp/oZNAB7jwERxNeFVeN/PtJhg4fpK/ybj9OwKtqGPseOadS7+TGbq6tH2DmDAYvA==", "dev": true, "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.1.4", + "@rollup/pluginutils": "^5.2.0", "load-tsconfig": "^0.2.5", "unplugin": "^2.3.5" }, @@ -11392,9 +11445,9 @@ } }, "node_modules/vite-node": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.2.tgz", - "integrity": "sha512-Xj/jovjZvDXOq2FgLXu8NsY4uHUMWtzVmMC2LkCu9HWdr9Qu1Is5sanX3Z4jOFKdohfaWDnEJWp9pRP0vVpAcA==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, "license": "MIT", "dependencies": { @@ -11415,20 +11468,20 @@ } }, "node_modules/vitest": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz", - "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", "dependencies": { "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.2", - "@vitest/mocker": "3.2.2", - "@vitest/pretty-format": "^3.2.2", - "@vitest/runner": "3.2.2", - "@vitest/snapshot": "3.2.2", - "@vitest/spy": "3.2.2", - "@vitest/utils": "3.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", @@ -11439,10 +11492,10 @@ "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", - "tinypool": "^1.1.0", + "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.2", + "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "bin": { @@ -11458,8 +11511,8 @@ "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.2", - "@vitest/ui": "3.2.2", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, diff --git a/package.json b/package.json index 626f9b241..b10b5ee8e 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@fastify/helmet": "11.1.1", "@fastify/multipart": "8.3.1", "@fastify/static": "7.0.4", - "@homebridge/hap-client": "2.2.0", + "@homebridge/hap-client": "3.1.0", "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", "@nestjs/axios": "3.1.3", "@nestjs/common": "10.4.18", @@ -93,7 +93,7 @@ "@nestjs/platform-socket.io": "10.4.18", "@nestjs/swagger": "8.1.1", "@nestjs/websockets": "10.4.18", - "axios": "1.9.0", + "axios": "1.10.0", "bash-color": "0.0.4", "class-transformer": "0.5.1", "class-validator": "0.14.2", @@ -113,26 +113,26 @@ "reflect-metadata": "0.2.2", "rxjs": "7.8.2", "semver": "7.7.2", - "systeminformation": "5.27.1", + "systeminformation": "5.27.5", "tail": "2.2.6", "tar": "7.4.3", "tcp-port-used": "1.0.2", "unzipper": "0.12.3" }, "devDependencies": { - "@antfu/eslint-config": "^4.14.1", + "@antfu/eslint-config": "^4.15.0", "@nestjs/testing": "^10.4.18", "@prettier/plugin-xml": "^3.4.1", "@types/fs-extra": "^11.0.4", - "@types/lodash": "^4.17.17", - "@types/node": "^22.15.30", + "@types/lodash": "^4.17.18", + "@types/node": "^24.0.3", "@types/node-schedule": "^2.1.7", "@types/passport-jwt": "^4.0.1", "@types/semver": "^7.7.0", "@types/tail": "^2.2.3", "@types/tcp-port-used": "^1.0.4", "@types/unzipper": "^0.10.11", - "@vitest/coverage-v8": "^3.2.2", + "@vitest/coverage-v8": "^3.2.4", "concurrently": "^9.1.2", "eslint-plugin-format": "^1.0.1", "form-data": "^4.0.3", @@ -142,8 +142,8 @@ "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", "typescript": "^5.8.3", - "unplugin-swc": "^1.5.4", - "vitest": "^3.2.2" + "unplugin-swc": "^1.5.5", + "vitest": "^3.2.4" }, "overrides": { "@nestjs/platform-fastify": { diff --git a/ui/package-lock.json b/ui/package-lock.json index 2897aad1a..9e11748ce 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -10,25 +10,25 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/compiler": "20.0.2", - "@angular/core": "20.0.2", - "@angular/forms": "20.0.2", - "@angular/localize": "20.0.2", - "@angular/platform-browser": "20.0.2", - "@angular/platform-browser-dynamic": "20.0.2", - "@angular/router": "20.0.2", + "@angular/animations": "20.0.4", + "@angular/common": "20.0.4", + "@angular/compiler": "20.0.4", + "@angular/core": "20.0.4", + "@angular/forms": "20.0.4", + "@angular/localize": "20.0.4", + "@angular/platform-browser": "20.0.4", + "@angular/platform-browser-dynamic": "20.0.4", + "@angular/router": "20.0.4", "@auth0/angular-jwt": "5.2.0", - "@homebridge/hap-client": "2.2.0", + "@homebridge/hap-client": "3.1.0", "@ng-bootstrap/ng-bootstrap": "18.0.0", "@ng-formworks/bootstrap5": "19.5.8", "@ng-formworks/core": "19.5.8", "@ngx-translate/core": "16.0.4", - "ajv-keywords": "^5.1.0", - "angular-gridster2": "19.0.0", - "bootstrap": "5.3.6", - "chart.js": "4.4.9", + "ajv-keywords": "5.1.0", + "angular-gridster2": "20.0.0", + "bootstrap": "5.3.7", + "chart.js": "4.5.0", "dayjs": "1.11.13", "emoji-js": "3.8.1", "file-saver": "2.0.5", @@ -55,16 +55,16 @@ "zone.js": "0.15.1" }, "devDependencies": { - "@angular/build": "^20.0.1", - "@angular/cli": "^20.0.1", - "@angular/compiler-cli": "^20.0.1", - "@angular/language-service": "^20.0.1", + "@angular/build": "^20.0.3", + "@angular/cli": "^20.0.3", + "@angular/compiler-cli": "^20.0.4", + "@angular/language-service": "^20.0.4", "@fortawesome/fontawesome-free": "^6.7.2", "@homebridge/plugin-ui-utils": "^2.1.0", "@types/emoji-js": "^3.5.2", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.15.30", + "@types/node": "^24.0.3", "@types/qrcode": "^1.5.5", "@types/semver": "^7.7.0", "he": "^1.2.0", @@ -87,13 +87,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.2000.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2000.1.tgz", - "integrity": "sha512-EcOGU1xEhARYpDF391VaeUg/+YRym9OxzJMcc0rSHl3YLK8/m+24ap2YAQY5N7n9+mmEqHVu/q31ldFpOoMCTw==", + "version": "0.2000.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.2000.3.tgz", + "integrity": "sha512-37S4dzlwB3C8gnBlwxjjvNUqwSeKnDe2j1XWg7sj94kbg/jLJV0Db/Dvb7zJjKher6Ed1Bnj3pMOM206ALJW2A==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.0.1", + "@angular-devkit/core": "20.0.3", "rxjs": "7.8.2" }, "engines": { @@ -103,9 +103,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.0.1.tgz", - "integrity": "sha512-Ilafyj8JVwq3NZsaiGw5UDkP4EAkGKiEvZ4TC3WVidZbM4EpKt9/Jd7ZpsTRGDLG429U+fGhay+ZQeCFGqy5rA==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-20.0.3.tgz", + "integrity": "sha512-XgEIbIky0pMtJSomHRaf16BT1jzJNQCm2geNZ642n3cj8fYLm4jHJX/r738kIfbHWoWXT/hlTmVgIH9TdQPicA==", "dev": true, "license": "MIT", "dependencies": { @@ -131,13 +131,13 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.0.1.tgz", - "integrity": "sha512-bSr/5YIdjtwKYqylkYrlOVP+tuFz+tfOldmLfWHAsDGnJUznb5t4ckx6yyROp+iDQfu2Aez09p+l4KfUBq+H9A==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-20.0.3.tgz", + "integrity": "sha512-T679AQXenG6e4fdC/HXrps0Dqy1EYKb4pFNLQqZHR9mfyeq/vxFWs3ga/yMiqvqMPUK5W5FucEpFZJQQmc7M+w==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.0.1", + "@angular-devkit/core": "20.0.3", "jsonc-parser": "3.3.1", "magic-string": "0.30.17", "ora": "8.2.0", @@ -150,9 +150,9 @@ } }, "node_modules/@angular/animations": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.0.2.tgz", - "integrity": "sha512-p9TqZdVOFWMF75lfxk++5GZOBGO3K7qVdAXiQw89VLac8yqsu9iXFlcq34x256McHxONTjrrKBeP5oU1T8rxCw==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-20.0.4.tgz", + "integrity": "sha512-s0kRcEply2A1ThvFmb0+o+hEpAbPn08lpK8xjWZryM4cMrwjgsUE0OZHZPBANP4I1xT7Z82l+fmQbH+vX48EyA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -161,19 +161,19 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/core": "20.0.2" + "@angular/common": "20.0.4", + "@angular/core": "20.0.4" } }, "node_modules/@angular/build": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.0.1.tgz", - "integrity": "sha512-m/0jtXIeOaoU/WXtMLRuvq7UaGRxNHpoRKVVoJrifvZuNBYGM4e2lzxlIlo8kiQhPpZQc0zcAMoosbmzKKdkUQ==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-20.0.3.tgz", + "integrity": "sha512-xA5eTGop85SI/+hfiOSJR/xI1w1NK3qylpEZ277YRaw8Ikh7r1DKPJOMGBfXNd8QsZYBSWGHA8SXvCmOh/hvLQ==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.2000.1", + "@angular-devkit/architect": "0.2000.3", "@babel/core": "7.27.1", "@babel/helper-annotate-as-pure": "7.27.1", "@babel/helper-split-export-declaration": "7.24.7", @@ -215,7 +215,7 @@ "@angular/platform-browser": "^20.0.0", "@angular/platform-server": "^20.0.0", "@angular/service-worker": "^20.0.0", - "@angular/ssr": "^20.0.1", + "@angular/ssr": "^20.0.3", "karma": "^6.4.0", "less": "^4.2.0", "ng-packagr": "^20.0.0", @@ -265,9 +265,9 @@ } }, "node_modules/@angular/cdk": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.2.tgz", - "integrity": "sha512-gRQcpTNhnwBxXSmpnrljODUHQmB2Hnxc6L2Ad6mSMV+c3opd9KIFxL5eG2WOOPHGAaPrV4gNFw+t1i01U4grTg==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-20.0.3.tgz", + "integrity": "sha512-70KG8GpK4aV9j5hUkpDZJQ6oMgCuaCRY6JX1axPxkNtQaiK6PAmTfQLiGqF2cYhbQneeq3uGvTorAjRfvp8NPQ==", "license": "MIT", "peer": true, "dependencies": { @@ -281,18 +281,18 @@ } }, "node_modules/@angular/cli": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.0.1.tgz", - "integrity": "sha512-OU91byvG/WsDDUVmXIJr3/sU89U6g8G8IXrqgVRVPgjXKEQMnUNBlmygD2rMUR5C02g2lGc6s2j0hnOJ/dDNOw==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-20.0.3.tgz", + "integrity": "sha512-tDYcUrxq8Y9wK6EqwJ6Gn+4IF+VpPVikmpuqzqrUtYzqvRTqYtkyhJsAu3Ec6d6941mL2U3ZnMm3sjOxPPNkjA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.2000.1", - "@angular-devkit/core": "20.0.1", - "@angular-devkit/schematics": "20.0.1", + "@angular-devkit/architect": "0.2000.3", + "@angular-devkit/core": "20.0.3", + "@angular-devkit/schematics": "20.0.3", "@inquirer/prompts": "7.5.1", "@listr2/prompt-adapter-inquirer": "2.0.22", - "@schematics/angular": "20.0.1", + "@schematics/angular": "20.0.3", "@yarnpkg/lockfile": "1.1.0", "ini": "5.0.0", "jsonc-parser": "3.3.1", @@ -314,9 +314,9 @@ } }, "node_modules/@angular/common": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.0.2.tgz", - "integrity": "sha512-dqzKFL2MgPpQiaY9ZyDhGZYWEXblsqofW6czH/+HkmlNgSmDCBaY/UhNQShxNQ0KQbR1o08OWuQr29zxkY1CMA==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-20.0.4.tgz", + "integrity": "sha512-fWgxe2rgSKgI36ummBYnBN4YUrmp4CHbfEG3RMeJho/vhHKguk2/o6BgL9zvnKybvbWmuaqbkHogi+y0LeJ8Ww==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -325,14 +325,14 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/core": "20.0.2", + "@angular/core": "20.0.4", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.2.tgz", - "integrity": "sha512-BJYXGUZaY9awYvgt0w9TDq73A1+m8W5eMRn/krWeQcfWakwTgs27BSxmhfJhD45KrMrky5yxAvGgqSfMKrLeng==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-20.0.4.tgz", + "integrity": "sha512-1bP3P8Ll/KUYMPiE6TDjkMXkqCDVgSUAUsVCgzAxz4mcMuc9PnlbhQazpWHCkCDIjGFZ5XIAsS49V7tfaTbLDw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -342,9 +342,9 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.0.2.tgz", - "integrity": "sha512-kVKHS5ZRadTR+rRuBl3Dsccsv/jiHXdJJYlDQwQW87afd4RtAu75P3RsSd8jaUj+7P9O4Ve4vwCZVtgOh0yxbw==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-20.0.4.tgz", + "integrity": "sha512-2FP1WMRexAMcDPNE3YO3zB++sCgND9O/qJC5rgKbAebpbmOrCDMUBRlftkwiLT+UhTM9PjhTtAGtK7C+2iwx1g==", "license": "MIT", "dependencies": { "@babel/core": "7.27.4", @@ -364,7 +364,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.0.2", + "@angular/compiler": "20.0.4", "typescript": ">=5.8 <5.9" }, "peerDependenciesMeta": { @@ -476,9 +476,9 @@ } }, "node_modules/@angular/core": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.0.2.tgz", - "integrity": "sha512-z9L8WPrHTkfupHtpO6aW4KqcqigIhxcQwCaEMgXWc5WJkoiMJSfo/dk+cyiGjCfTkc5Y6DO6f6ERi0IWYWWbPA==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-20.0.4.tgz", + "integrity": "sha512-JhSl3B6CrJ9kegLffgWVFGF4D4bWLV/9r8R0+h78vU+ppdPFPWDha7WnirF31cPIg3pBzy6wn103Kcy9Ri5M5w==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -487,7 +487,7 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.0.2", + "@angular/compiler": "20.0.4", "rxjs": "^6.5.3 || ^7.4.0", "zone.js": "~0.15.0" }, @@ -501,9 +501,9 @@ } }, "node_modules/@angular/forms": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.0.2.tgz", - "integrity": "sha512-RrQKwzFZsEDXsvesNXS4XxndEKZHC+VexIdRr1vlxx7isfvpl4htOxceW0D+Gvku1mnaS99eB/AWS50HxW3B3Q==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-20.0.4.tgz", + "integrity": "sha512-bFTMgJSHiLr80ELymRykZW6o5QroDlk+g5AFFiY9yxM8I0DV5YpCNBefv8GiuWubE+Lw6LkQ/HMYeXYJMTue3A==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -512,16 +512,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/core": "20.0.2", - "@angular/platform-browser": "20.0.2", + "@angular/common": "20.0.4", + "@angular/core": "20.0.4", + "@angular/platform-browser": "20.0.4", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.0.2.tgz", - "integrity": "sha512-CUkKyuMUvRqJR5BeSDQ4gGX8z5vxRkQ0mqIq4uMXrFs/rMn7cYqfzr3rjxp0S69wsOKF4G/6pgN5xpUhnqhdgw==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-20.0.4.tgz", + "integrity": "sha512-DVia9XvaX/VgSfAKcjJNLcoQvYCDw4XY00VXb8X90XYTr9GE472seQ3I/qXf3JpAyNlLJ7iPGWIHsrLvLFcDNA==", "dev": true, "license": "MIT", "engines": { @@ -529,9 +529,9 @@ } }, "node_modules/@angular/localize": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.0.2.tgz", - "integrity": "sha512-k872tsni1WhrxZNEreCrPatcs35le1LZiLYXg6iGvDmwr8K125DiI2cC6l0dSoD6b3qwP2g+BtRT5lR8V6ROrg==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-20.0.4.tgz", + "integrity": "sha512-UDOUb8I4fmTpbFwQ9fSP+UhABoXstby6bqmyfuGmjSBPfliKcv6QKK9CS0vO8cPaNRmwPPqVPyYsLpTthRFdag==", "license": "MIT", "dependencies": { "@babel/core": "7.27.4", @@ -548,8 +548,8 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/compiler": "20.0.2", - "@angular/compiler-cli": "20.0.2" + "@angular/compiler": "20.0.4", + "@angular/compiler-cli": "20.0.4" } }, "node_modules/@angular/localize/node_modules/@babel/core": { @@ -655,9 +655,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.0.2.tgz", - "integrity": "sha512-4adMQSVlwxjY9z/LEk3Q5hr4/qbM9UD9FcqbyZOt3+BL+F2GwGdKzwg6Dj4Dv0Tv8/dudNSVgHc8lIdQ4C7K1w==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-20.0.4.tgz", + "integrity": "sha512-hMJYvtZlNPh4Tt6JrnK+vmBmHWok04EkuJwyPcPhlle1u6/LihuCj4suELLqCanX9EzyNgvyKnws0i6JE/qh8Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -666,9 +666,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/core": "20.0.2" + "@angular/animations": "20.0.4", + "@angular/common": "20.0.4", + "@angular/core": "20.0.4" }, "peerDependenciesMeta": { "@angular/animations": { @@ -677,9 +677,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.0.2.tgz", - "integrity": "sha512-8MDGsgcxUxSldcX6HRGB5dj+xOCQ8qmx8Vog9unEBNkuPH0vqvOepqn3prdV6dM31jYfJ9JAEKeEfNZFjuWSkA==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.0.4.tgz", + "integrity": "sha512-MTjnSd/nuurpBT5FosgPSGsuH5xF9czmZOSvjBRPKDwAKBCBxISYx/Qb7ktqxI8Fp2ER2wbyxrypwcZHpDyysg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -688,16 +688,16 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/compiler": "20.0.2", - "@angular/core": "20.0.2", - "@angular/platform-browser": "20.0.2" + "@angular/common": "20.0.4", + "@angular/compiler": "20.0.4", + "@angular/core": "20.0.4", + "@angular/platform-browser": "20.0.4" } }, "node_modules/@angular/router": { - "version": "20.0.2", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.0.2.tgz", - "integrity": "sha512-UyuTeoXkkZw1eFFNwrTfb1JXow6HKVdLNb3n9MhqDz+3ekdiqDH8EBaKhxYZxlcpNoa6cNbECZJYtaHy1lw38g==", + "version": "20.0.4", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-20.0.4.tgz", + "integrity": "sha512-t02ukwKh+YDZutR09ZYJVLaC+OPyDxu6ll7A2MFK0BNLPpD9oQc0lDwJZSrqfAhlXU0arWUjmwkNvFdh21/Z5Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -706,9 +706,9 @@ "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "@angular/common": "20.0.2", - "@angular/core": "20.0.2", - "@angular/platform-browser": "20.0.2", + "@angular/common": "20.0.4", + "@angular/core": "20.0.4", + "@angular/platform-browser": "20.0.4", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -1449,12 +1449,12 @@ } }, "node_modules/@homebridge/hap-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-2.2.0.tgz", - "integrity": "sha512-ko50uTJosoogBotV2Wf1eGKjgMe9Iy0wg6WEPSlorQnIu3Li+dcnm2SlOpE/8ijMexyMPqTVFoeU1Bo+nm4+6Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@homebridge/hap-client/-/hap-client-3.1.0.tgz", + "integrity": "sha512-8w2ciWvtNqBspFN/WVpkGEOqCEg1w3XPC/haU7pJbE/GIh4g/Nt8+2t5nOivunpsE+9TY44Ily3MBEsfxFru2A==", "license": "MIT", "dependencies": { - "axios": "1.9.0", + "axios": "1.10.0", "bonjour-service": "1.3.0", "decamelize": "5.0.1", "inflection": "3.0.2", @@ -3322,14 +3322,14 @@ ] }, "node_modules/@schematics/angular": { - "version": "20.0.1", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.0.1.tgz", - "integrity": "sha512-29T9vUAjZnbXM+vImIQcdqG/ibdcfj5+pybo5cbiMSwVPVyerXgnD0HKC4dyZ34V2RFZa8cmyCLe/5bYoPQ+0g==", + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-20.0.3.tgz", + "integrity": "sha512-oWj5UU1gR12KDxQwOUpxweaaF8PPF7t5ymTa/px/nl4YYWd9s5e1skoDNcGHHl0MPHklJzNLxP7O89BORie5vQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "20.0.1", - "@angular-devkit/schematics": "20.0.1", + "@angular-devkit/core": "20.0.3", + "@angular-devkit/schematics": "20.0.3", "jsonc-parser": "3.3.1" }, "engines": { @@ -3362,9 +3362,9 @@ } }, "node_modules/@sigstore/protobuf-specs": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.4.2.tgz", - "integrity": "sha512-F2ye+n1INNhqT0MW+LfUEvTUPc/nS70vICJcxorKl7/gV9CO39+EDCw+qHNKEqvsDWk++yGVKCbzK1qLPvmC8g==", + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.4.3.tgz", + "integrity": "sha512-fk2zjD9117RL9BjqEwF7fwv7Q/P9yGsMV4MUJZ/DocaQJ6+3pKr+syBq1owU5Q5qGw5CUbXzm+4yJ2JVRDQeSA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3546,9 +3546,9 @@ "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.17.tgz", - "integrity": "sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==", + "version": "4.17.18", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.18.tgz", + "integrity": "sha512-KJ65INaxqxmU6EoCiJmRPZC9H9RVWCRd349tXM2M3O5NA7cY6YL7c0bHAHQ93NOfTObEQ004kd2QVHs/r0+m4g==", "dev": true, "license": "MIT" }, @@ -3563,13 +3563,13 @@ } }, "node_modules/@types/node": { - "version": "22.15.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.30.tgz", - "integrity": "sha512-6Q7lr06bEHdlfplU6YRbgG1SFBdlsfNC4/lX+SkhiTs0cpJkOElmWls8PxDFv4yY/xKb8Y6SO0OmSX4wgqTZbA==", + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz", + "integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/qrcode": { @@ -3620,9 +3620,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -3702,16 +3702,16 @@ } }, "node_modules/angular-gridster2": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/angular-gridster2/-/angular-gridster2-19.0.0.tgz", - "integrity": "sha512-82SHZzwOmGRvR77VtbpV5Eh7CoTtxLslwOVzTYB3qNQIGGFaOsS8nRAuYpZOlZpVc+n6fBz1HU0yP0icnQ9ppg==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/angular-gridster2/-/angular-gridster2-20.0.0.tgz", + "integrity": "sha512-c2YL0AeOV3Ca4xwmjjGl7UqL/HZBmOdj+Z7k3aAXbtarhQbWsEhu8Nh6IQIsoHeOcmrhPK0ilFlXh08xart43w==", "license": "MIT", "dependencies": { "tslib": "^2.4.0" }, "peerDependencies": { - "@angular/common": "^19.0.0", - "@angular/core": "^19.0.0", + "@angular/common": "^20.0.0", + "@angular/core": "^20.0.0", "rxjs": "^7.0.0" } }, @@ -3786,9 +3786,9 @@ "peer": true }, "node_modules/axios": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", - "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", @@ -3841,9 +3841,9 @@ "license": "ISC" }, "node_modules/bootstrap": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.6.tgz", - "integrity": "sha512-jX0GAcRzvdwISuvArXn3m7KZscWWFAf1MKBcnzaN02qWMb3jpMoUX4/qgeiGzqyIb4ojulRzs89UCUmGcFSzTA==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.7.tgz", + "integrity": "sha512-7KgiD8UHjfcPBHEpDNg+zGz8L3LqR3GVwqZiBRFX04a1BCArZOz1r2kjly2HQ0WokqTO0v1nF+QAt8dsW4lKlw==", "funding": [ { "type": "github", @@ -3860,9 +3860,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4064,9 +4064,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001721.tgz", - "integrity": "sha512-cOuvmUVtKrtEaoKiO0rSc29jcjwMwX5tOHDy4MgVFEWiUXj4uBMJkwI8MDySkgXidpMiHUcviogAvFi4pA2hDQ==", + "version": "1.0.30001723", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001723.tgz", + "integrity": "sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==", "funding": [ { "type": "opencollective", @@ -4104,9 +4104,9 @@ "license": "MIT" }, "node_modules/chart.js": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.9.tgz", - "integrity": "sha512-EyZ9wWKgpAU0fLJ43YAEIF8sr5F2W3LqbS40ZJyHIner2lY14ufqv2VMp69MAiZ2rpwxEUxEhIH/0U3xyRynxg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz", + "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==", "license": "MIT", "dependencies": { "@kurkle/color": "^0.3.0" @@ -4662,9 +4662,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.165", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.165.tgz", - "integrity": "sha512-naiMx1Z6Nb2TxPU6fiFrUrDTjyPMLdTtaOd2oLmG8zVSg2hCWGkhPyxwk+qRmZ1ytwVqUv0u7ZcDA5+ALhaUtw==", + "version": "1.5.170", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.170.tgz", + "integrity": "sha512-GP+M7aeluQo9uAyiTCxgIj/j+PrWhMlY7LFVj8prlsPljd0Fdg9AprlfUi+OCSFWy9Y5/2D/Jrj9HS8Z4rpKWA==", "license": "ISC" }, "node_modules/emoji-datasource": { @@ -4942,9 +4942,9 @@ "license": "BSD-3-Clause" }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -5346,9 +5346,9 @@ } }, "node_modules/htmlparser2/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -5420,9 +5420,9 @@ } }, "node_modules/immutable": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.2.tgz", - "integrity": "sha512-qHKXW1q6liAk1Oys6umoaZbDRqjcjgSrbnrifHsfsttza7zcvRAsL7mMV6xWcyhwQy7Xj5v4hhbr6b+iDYwlmQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz", + "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==", "dev": true, "license": "MIT" }, @@ -7021,9 +7021,9 @@ } }, "node_modules/parse5-html-rewriting-stream/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -7047,9 +7047,9 @@ } }, "node_modules/parse5/node_modules/entities": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz", - "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -7223,9 +7223,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, "funding": [ { @@ -7538,9 +7538,9 @@ } }, "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -7851,9 +7851,9 @@ } }, "node_modules/socks": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", - "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.5.tgz", + "integrity": "sha512-iF+tNDQla22geJdTyJB1wM/qrX9DMRwWrciEPwWLPRWAUEM8sQiyxgckLxWT1f7+9VabJS0jTGGr4QgBuvi6Ww==", "dev": true, "license": "MIT", "dependencies": { @@ -8368,9 +8368,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true, "license": "MIT" }, diff --git a/ui/package.json b/ui/package.json index 253a3f135..c844c8943 100644 --- a/ui/package.json +++ b/ui/package.json @@ -12,25 +12,25 @@ "postinstall": "patch-package" }, "dependencies": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/compiler": "20.0.2", - "@angular/core": "20.0.2", - "@angular/forms": "20.0.2", - "@angular/localize": "20.0.2", - "@angular/platform-browser": "20.0.2", - "@angular/platform-browser-dynamic": "20.0.2", - "@angular/router": "20.0.2", + "@angular/animations": "20.0.4", + "@angular/common": "20.0.4", + "@angular/compiler": "20.0.4", + "@angular/core": "20.0.4", + "@angular/forms": "20.0.4", + "@angular/localize": "20.0.4", + "@angular/platform-browser": "20.0.4", + "@angular/platform-browser-dynamic": "20.0.4", + "@angular/router": "20.0.4", "@auth0/angular-jwt": "5.2.0", - "@homebridge/hap-client": "2.2.0", + "@homebridge/hap-client": "3.1.0", "@ng-bootstrap/ng-bootstrap": "18.0.0", "@ng-formworks/bootstrap5": "19.5.8", "@ng-formworks/core": "19.5.8", "@ngx-translate/core": "16.0.4", - "ajv-keywords": "^5.1.0", - "angular-gridster2": "19.0.0", - "bootstrap": "5.3.6", - "chart.js": "4.4.9", + "ajv-keywords": "5.1.0", + "angular-gridster2": "20.0.0", + "bootstrap": "5.3.7", + "chart.js": "4.5.0", "dayjs": "1.11.13", "emoji-js": "3.8.1", "file-saver": "2.0.5", @@ -57,16 +57,16 @@ "zone.js": "0.15.1" }, "devDependencies": { - "@angular/build": "^20.0.1", - "@angular/cli": "^20.0.1", - "@angular/compiler-cli": "^20.0.1", - "@angular/language-service": "^20.0.1", + "@angular/build": "^20.0.3", + "@angular/cli": "^20.0.3", + "@angular/compiler-cli": "^20.0.4", + "@angular/language-service": "^20.0.4", "@fortawesome/fontawesome-free": "^6.7.2", "@homebridge/plugin-ui-utils": "^2.1.0", "@types/emoji-js": "^3.5.2", "@types/file-saver": "^2.0.7", "@types/lodash-es": "^4.17.12", - "@types/node": "^22.15.30", + "@types/node": "^24.0.3", "@types/qrcode": "^1.5.5", "@types/semver": "^7.7.0", "he": "^1.2.0", @@ -75,10 +75,10 @@ "typescript": "^5.8.3" }, "overrides": { - "@angular/animations": "20.0.2", - "@angular/common": "20.0.2", - "@angular/core": "20.0.2", - "@angular/forms": "20.0.2", - "@angular/localize": "20.0.2" + "@angular/animations": "20.0.4", + "@angular/common": "20.0.4", + "@angular/core": "20.0.4", + "@angular/forms": "20.0.4", + "@angular/localize": "20.0.4" } } From 43e4442cdb02f2d5c80e85cc3fe49b531d58c446 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:10:24 +0100 Subject: [PATCH 14/22] retire use of `pnpm` and code references --- CHANGELOG.md | 28 ++-- src/bin/hb-service.ts | 10 +- src/bin/platforms/darwin.ts | 67 +++----- src/bin/platforms/linux.ts | 61 +++----- src/core/config/config.service.ts | 2 - src/modules/plugins/plugins.service.ts | 78 ++-------- src/self-check.ts | 15 +- ui/src/app/core/settings.service.ts | 1 - ui/src/app/modules/status/status.module.ts | 2 - .../hb-v2-modal/hb-v2-modal.component.ts | 6 +- .../ui-v5-modal/ui-v5-modal.component.html | 145 ------------------ .../ui-v5-modal/ui-v5-modal.component.ts | 28 ---- .../update-info-widget.component.html | 19 +-- .../update-info-widget.component.ts | 18 +-- 14 files changed, 90 insertions(+), 390 deletions(-) delete mode 100644 ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html delete mode 100644 ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5ccae0a..45d18bd09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,17 +2,27 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. This project tries to adhere to [Semantic Versioning](http://semver.org/). -## v4.77.0 (Unreleased) +## v5.0.0 (Unreleased) + +### ⚠️ Breaking Changes + +- This version of the Homebridge UI: + - Is compatible with Homebridge `v1` and `v2-beta` + - Drops support for Node.js `v18` and earlier, so please update to `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js) + - Drops support for Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware + - Drops support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) + +### Other Changes + +- retire use of `pnpm` and code references -### ⚠️ Upcoming Deprecations: +### Homebridge Dependencies + +- `@homebridge/hap-client` @ `v2.2.0` +- `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` +- `@homebridge/plugin-ui-utils` @ `v2.1.0` -- A new version of Homebridge UI (v5) will be released around mid-June 2025. This will be compatible with both Homebridge v1 and v2 (in beta). -- Initially, there will be no significant differences between Homebridge UI v4 and v5. The major version increment primarily reflects the removal of support for outdated technologies and hardware. UI v5 will: - - Be compatible with Homebridge `v1` and `v2` - - Drop support for Node.js `v18` and earlier, so please update to `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js) - - Drop support for Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware - - Drop support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) -- Note that these are not requirements for UI `v4.77.0` +## v4.77.0 (Unreleased) ### UI Changes diff --git a/src/bin/hb-service.ts b/src/bin/hb-service.ts index 4dc4f8c9e..b1dd23352 100644 --- a/src/bin/hb-service.ts +++ b/src/bin/hb-service.ts @@ -1328,7 +1328,7 @@ export class HomebridgeServiceHelper { } /** - * Install / Remove a plugin using pnpm (supported platforms only) + * Install / Remove a plugin (supported platforms only) */ private async npmPluginManagement(args: any[]) { if (!this.enableHbServicePluginManagement) { @@ -1360,13 +1360,7 @@ export class HomebridgeServiceHelper { this.logger(`Path does not exist: ${cwd}.`, 'fail') } - let cmd: string - - if (process.env.UIX_USE_PNPM === '1') { - cmd = `pnpm -C "${cwd}" ${action} ${target.name}` - } else { - cmd = `npm --prefix "${cwd}" ${action} ${target.name}` - } + let cmd: string = `npm --prefix "${cwd}" ${action} ${target.name}` if (action === 'add') { cmd += `@${target.version}` diff --git a/src/bin/platforms/darwin.ts b/src/bin/platforms/darwin.ts index 8d02b4a99..562f10d5f 100644 --- a/src/bin/platforms/darwin.ts +++ b/src/bin/platforms/darwin.ts @@ -112,50 +112,33 @@ export class DarwinInstaller extends BasePlatform { const targetNodeVersion = execSync('node -v').toString('utf8').trim() - if (this.isPackage() && process.env.UIX_USE_PNPM === '1' && process.env.UIX_CUSTOM_PLUGIN_PATH) { - // PNPM+package mode - const cwd = dirname(process.env.UIX_CUSTOM_PLUGIN_PATH) - - if (!await pathExists(cwd)) { - this.hbService.logger(`Path does not exist: "${cwd}"`, 'fail') - process.exit(1) - } - - execSync(`pnpm -C "${cwd}" rebuild`, { - cwd, - stdio: 'inherit', - }) - this.hbService.logger(`Rebuilt plugins in ${process.env.UIX_CUSTOM_PLUGIN_PATH} for Node.js ${targetNodeVersion}.`, 'succeed') - } else { - // Normal global npm setups - const npmGlobalPath = execSync('/bin/echo -n "$(npm -g prefix)/lib/node_modules"', { - env: Object.assign({ - npm_config_loglevel: 'silent', - npm_update_notifier: 'false', - }, process.env), - }).toString('utf8') - - execSync('npm rebuild --unsafe-perm', { - cwd: process.env.UIX_BASE_PATH, - stdio: 'inherit', - }) - this.hbService.logger(`Rebuilt homebridge-config-ui-x for Node.js ${targetNodeVersion}.`, 'succeed') - - if (all === true) { - // Rebuild all modules - try { - execSync('npm rebuild --unsafe-perm', { - cwd: npmGlobalPath, - stdio: 'inherit', - }) - this.hbService.logger(`Rebuilt plugins in ${npmGlobalPath} for Node.js ${targetNodeVersion}.`, 'succeed') - } catch (e) { - this.hbService.logger('Could not rebuild all modules - check Homebridge logs.', 'warn') - } + const npmGlobalPath = execSync('/bin/echo -n "$(npm -g prefix)/lib/node_modules"', { + env: Object.assign({ + npm_config_loglevel: 'silent', + npm_update_notifier: 'false', + }, process.env), + }).toString('utf8') + + execSync('npm rebuild --unsafe-perm', { + cwd: process.env.UIX_BASE_PATH, + stdio: 'inherit', + }) + this.hbService.logger(`Rebuilt homebridge-config-ui-x for Node.js ${targetNodeVersion}.`, 'succeed') + + if (all === true) { + // Rebuild all modules + try { + execSync('npm rebuild --unsafe-perm', { + cwd: npmGlobalPath, + stdio: 'inherit', + }) + this.hbService.logger(`Rebuilt plugins in ${npmGlobalPath} for Node.js ${targetNodeVersion}.`, 'succeed') + } catch (e) { + this.hbService.logger('Could not rebuild all modules - check Homebridge logs.', 'warn') } - - await this.setNpmPermissions(npmGlobalPath) } + + await this.setNpmPermissions(npmGlobalPath) } catch (e) { console.error(e.toString()) this.hbService.logger('ERROR: Failed Operation', 'fail') diff --git a/src/bin/platforms/linux.ts b/src/bin/platforms/linux.ts index 0d2307b4c..342fe7efa 100644 --- a/src/bin/platforms/linux.ts +++ b/src/bin/platforms/linux.ts @@ -199,46 +199,29 @@ export class LinuxInstaller extends BasePlatform { const targetNodeVersion = execSync('node -v').toString('utf8').trim() - if (this.isPackage() && process.env.UIX_USE_PNPM === '1' && process.env.UIX_CUSTOM_PLUGIN_PATH) { - // PNPM+package mode - const cwd = dirname(process.env.UIX_CUSTOM_PLUGIN_PATH) - - if (!await pathExists(cwd)) { - this.hbService.logger(`Path does not exist: "${cwd}"`, 'fail') - process.exit(1) - } + const npmGlobalPath = execSync('/bin/echo -n "$(npm -g prefix)/lib/node_modules"', { + env: Object.assign({ + npm_config_loglevel: 'silent', + npm_update_notifier: 'false', + }, process.env), + }).toString('utf8') + + execSync('npm rebuild --unsafe-perm', { + cwd: process.env.UIX_BASE_PATH, + stdio: 'inherit', + }) + this.hbService.logger(`Rebuilt homebridge-config-ui-x for Node.js ${targetNodeVersion}.`, 'succeed') - execSync(`pnpm -C "${cwd}" rebuild`, { - cwd, - stdio: 'inherit', - }) - this.hbService.logger(`Rebuilt plugins in ${process.env.UIX_CUSTOM_PLUGIN_PATH} for Node.js ${targetNodeVersion}.`, 'succeed') - } else { - // Normal global npm setups - const npmGlobalPath = execSync('/bin/echo -n "$(npm -g prefix)/lib/node_modules"', { - env: Object.assign({ - npm_config_loglevel: 'silent', - npm_update_notifier: 'false', - }, process.env), - }).toString('utf8') - - execSync('npm rebuild --unsafe-perm', { - cwd: process.env.UIX_BASE_PATH, - stdio: 'inherit', - }) - this.hbService.logger(`Rebuilt homebridge-config-ui-x for Node.js ${targetNodeVersion}.`, 'succeed') - - if (all === true) { - // Rebuild all global node_modules - try { - execSync('npm rebuild --unsafe-perm', { - cwd: npmGlobalPath, - stdio: 'inherit', - }) - this.hbService.logger(`Rebuilt plugins in ${npmGlobalPath} for Node.js ${targetNodeVersion}.`, 'succeed') - } catch (e) { - this.hbService.logger('Could not rebuild all plugins - check logs.', 'warn') - } + if (all === true) { + // Rebuild all global node_modules + try { + execSync('npm rebuild --unsafe-perm', { + cwd: npmGlobalPath, + stdio: 'inherit', + }) + this.hbService.logger(`Rebuilt plugins in ${npmGlobalPath} for Node.js ${targetNodeVersion}.`, 'succeed') + } catch (e) { + this.hbService.logger('Could not rebuild all plugins - check logs.', 'warn') } } } catch (e) { diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index dbe9e73a2..7bf298442 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -51,7 +51,6 @@ export class ConfigService { || Boolean(process.env.HOMEBRIDGE_CONFIG_UI_TERMINAL === '1') // Plugin management - public usePnpm = (process.env.UIX_USE_PNPM === '1') public usePluginBundles = (process.env.UIX_USE_PLUGIN_BUNDLES === '1') // Recommend child bridges on platforms with > 2GB ram @@ -241,7 +240,6 @@ export class ConfigService { runningOnRaspberryPi: this.runningOnRaspberryPi, temperatureUnits: this.ui.tempUnits || 'c', temp: this.ui.temp, - usePnpm: this.usePnpm, log: { maxSize: this.ui.log?.maxSize, truncateSize: this.ui.log?.truncateSize, diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index 3058d5e44..9e9eb69b1 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -492,29 +492,6 @@ export class PluginsService { const userPlatform = platform() - // Guard rails for v5 upgrade - if (+pluginAction.version.split('.')[0] > 4) { - // 1. Disallow if the node version is less than 20 - if (!satisfies(process.version, '>=20')) { - throw new Error('Homebridge UI v5 requires Node.js v20 or above.') - } - - // 2. Disallow if not running in service mode - if (!this.configService.serviceMode) { - throw new Error('Homebridge UI v5 requires using service mode.') - } - - // 3. Disallow if using pnpm package manager - if (this.configService.usePnpm) { - throw new Error('Homebridge UI v5 is not compatible with the pnpm package manager.') - } - - // 4. Disallow updates on linux armv6l (raspberry pi 1 / zero, for example) - if (userPlatform === 'linux' && execSync('uname -m').toString().trim() === 'armv6l') { - throw new Error('Homebridge UI v5 is not compatible with your armv6l device.') - } - } - // Set the default install path let installPath = this.configService.customPluginPath ? this.configService.customPluginPath @@ -553,10 +530,7 @@ export class PluginsService { const installOptions: Array = [] // Check to see if the custom plugin path is using a package.json file - if ( - installPath === this.configService.customPluginPath - && await pathExists(resolve(installPath, '../package.json')) - ) { + if (installPath === this.configService.customPluginPath && await pathExists(resolve(installPath, '../package.json'))) { installOptions.push('--save') } @@ -568,10 +542,8 @@ export class PluginsService { installOptions.push('-g') } - if (!this.configService.usePnpm) { - // If installing, set --omit=dev to prevent installing devDependencies - installOptions.push('--omit=dev') - } + // If installing, set --omit=dev to prevent installing devDependencies + installOptions.push('--omit=dev') const npmPluginLabel = `${pluginAction.name}@${pluginAction.version}` // Clean up the npm cache before any installation @@ -642,11 +614,7 @@ export class PluginsService { let npmPluginLabel = pluginAction.name // Check to see if the custom plugin path is using a package.json file - if ( - installPath === this.configService.customPluginPath - && !(action === 'uninstall' && this.configService.usePnpm) - && await pathExists(resolve(installPath, '../package.json')) - ) { + if (installPath === this.configService.customPluginPath && await pathExists(resolve(installPath, '../package.json'))) { installOptions.push('--save') } @@ -659,10 +627,8 @@ export class PluginsService { } if (action === 'install') { - if (!this.configService.usePnpm) { - // If installing, set --omit=dev to prevent installing devDependencies - installOptions.push('--omit=dev') - } + // If installing, set --omit=dev to prevent installing devDependencies + installOptions.push('--omit=dev') npmPluginLabel = `${pluginAction.name}@${pluginAction.version}` } @@ -758,9 +724,7 @@ export class PluginsService { // Prepare flags for npm command const installOptions: Array = [] - if (!this.configService.usePnpm) { - installOptions.push('--omit=dev') - } + installOptions.push('--omit=dev') // Check to see if the custom plugin path is using a package.json file if (installPath === this.configService.customPluginPath && await pathExists(resolve(installPath, '../package.json'))) { @@ -788,18 +752,9 @@ export class PluginsService { /** * Gets the Homebridge UI package details */ - public async getHomebridgeUiPackage(): Promise { + public async getHomebridgeUiPackage(): Promise { const plugins = await this.getInstalledPlugins() - const plugin = plugins.find((x: HomebridgePlugin) => x.name === this.configService.name) - return { - ...plugin, - readyForV5: { - node: satisfies(process.version, '>=20'), - pnpm: !this.configService.usePnpm, - arch: platform() !== 'linux' || execSync('uname -m').toString().trim() !== 'armv6l', - service: this.configService.serviceMode, - }, - } + return plugins.find((x: HomebridgePlugin) => x.name === this.configService.name) } /** @@ -981,9 +936,7 @@ export class PluginsService { configSchema.schema.properties.port.default = this.configService.ui.port // Filter some options from the UI config when using service mode - if (this.configService.serviceMode) { - configSchema.layout = configSchema.layout.filter((section: any) => section.ref !== 'log' && section.ref !== 'homebridge') - } + configSchema.layout = configSchema.layout.filter((section: any) => section.ref !== 'log' && section.ref !== 'homebridge') } // Modify homebridge-alexa to set the default pin @@ -1368,8 +1321,8 @@ export class PluginsService { this.logger.error('npm install -g npm') } } - // Linux and macOS don't require the full path to npm / pnpm - return this.configService.usePnpm ? ['pnpm'] : ['npm'] + // Linux and macOS don't require the full path to npm + return ['npm'] } /** @@ -1603,14 +1556,9 @@ export class PluginsService { npm_config_update_notifier: 'false', npm_config_prefer_online: 'true', npm_config_foreground_scripts: 'true', + npm_config_loglevel: 'error', }) - if (!this.configService.usePnpm) { - Object.assign(env, { - npm_config_loglevel: 'error', - }) - } - // Set global prefix for unix based systems if (command.includes('-g') && basename(cwd) === 'lib') { cwd = dirname(cwd) diff --git a/src/self-check.ts b/src/self-check.ts index 758ccc2fb..2855c771d 100644 --- a/src/self-check.ts +++ b/src/self-check.ts @@ -13,17 +13,10 @@ function tryRebuildNodePtyModule() { logger.warn('[node-pty] Trying to rebuild automatically...') logger.warn(`[node-pty] Path: ${modulePath}.`) try { - if (process.env.UIX_USE_PNPM === '1' && process.env.UIX_CUSTOM_PLUGIN_PATH) { - execSync('pnpm rebuild @homebridge/node-pty-prebuilt-multiarch', { - cwd: process.env.UIX_CUSTOM_PLUGIN_PATH, - stdio: 'ignore', - }) - } else { - execSync('npm run install --unsafe-perm', { - cwd: modulePath, - stdio: 'ignore', - }) - } + execSync('npm run install --unsafe-perm', { + cwd: modulePath, + stdio: 'ignore', + }) } catch (e) { if (platform() !== 'win32') { execSync('sudo -E -n run install --unsafe-perm', { diff --git a/ui/src/app/core/settings.service.ts b/ui/src/app/core/settings.service.ts index d51fb4d67..07efac628 100644 --- a/ui/src/app/core/settings.service.ts +++ b/ui/src/app/core/settings.service.ts @@ -35,7 +35,6 @@ interface EnvInterface { customWallpaperHash: string setupWizardComplete: boolean recommendChildBridges: boolean - usePnpm: boolean scheduledBackupDisable: boolean scheduledBackupPath: string log?: { diff --git a/ui/src/app/modules/status/status.module.ts b/ui/src/app/modules/status/status.module.ts index 0b833e5f4..837f71b38 100644 --- a/ui/src/app/modules/status/status.module.ts +++ b/ui/src/app/modules/status/status.module.ts @@ -25,7 +25,6 @@ import { NetworkWidgetComponent } from '@/app/modules/status/widgets/network-wid import { SystemInfoWidgetComponent } from '@/app/modules/status/widgets/system-info-widget/system-info-widget.component' import { TerminalWidgetComponent } from '@/app/modules/status/widgets/terminal-widget/terminal-widget.component' import { HbV2ModalComponent } from '@/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component' -import { UiV5ModalComponent } from '@/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component' import { UpdateInfoWidgetComponent } from '@/app/modules/status/widgets/update-info-widget/update-info-widget.component' import { UptimeWidgetComponent } from '@/app/modules/status/widgets/uptime-widget/uptime-widget.component' import { WeatherWidgetComponent } from '@/app/modules/status/widgets/weather-widget/weather-widget.component' @@ -63,7 +62,6 @@ import { WidgetsComponent } from '@/app/modules/status/widgets/widgets.component BridgesWidgetComponent, CreditsComponent, HbV2ModalComponent, - UiV5ModalComponent, ], providers: [ provideCharts(withDefaultRegisterables()), diff --git a/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts index 17063bd86..4fa0de594 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component.ts @@ -4,6 +4,7 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { firstValueFrom } from 'rxjs' +import { satisfies } from 'semver' import { ApiService } from '@/app/core/api.service' import { SettingsService } from '@/app/core/settings.service' @@ -30,7 +31,6 @@ export class HbV2ModalComponent implements OnInit { public loading = true public installedPlugins: any = [] public allPluginsSupported = true - public homebridgeUiPkg = {} as any public nodeReady = false private io: IoNamespace @@ -48,8 +48,8 @@ export class HbV2ModalComponent implements OnInit { async checkHomebridgeUiVersion() { try { - this.homebridgeUiPkg = await firstValueFrom(this.io.request('homebridge-ui-version-check')) - this.nodeReady = this.homebridgeUiPkg.readyForV5.node + const { nodeVersion } = await firstValueFrom(this.io.request('get-homebridge-server-info')) + this.nodeReady = satisfies(nodeVersion, '>=20') } catch (error) { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) diff --git a/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html b/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html deleted file mode 100644 index e80365cc1..000000000 --- a/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.html +++ /dev/null @@ -1,145 +0,0 @@ - diff --git a/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.ts deleted file mode 100644 index 0f3026876..000000000 --- a/ui/src/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { NgOptimizedImage } from '@angular/common' -import { Component, inject, Input } from '@angular/core' -import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' -import { TranslatePipe } from '@ngx-translate/core' - -import { SettingsService } from '@/app/core/settings.service' - -@Component({ - templateUrl: './ui-v5-modal.component.html', - standalone: true, - imports: [ - TranslatePipe, - NgOptimizedImage, - ], -}) -export class UiV5ModalComponent { - $activeModal = inject(NgbActiveModal) - $settings = inject(SettingsService) - - @Input() readyForV5: { - node: boolean - pnpm: boolean - service: boolean - arch: boolean - } - - constructor() {} -} diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html index 9e70bd154..d6609d730 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.html @@ -80,24 +80,7 @@ class="card-link card-link-title" >Homebridge UI - @if (!isRunningUiV5) { - - - - } } @if (!homebridgeUiPkg.installedVersion) { + } @if (!homebridgeUiPkg.installedVersion) { Homebridge UI }
    diff --git a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts index 482855d28..1ac7561ef 100644 --- a/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts +++ b/ui/src/app/modules/status/widgets/update-info-widget/update-info-widget.component.ts @@ -1,7 +1,7 @@ import { NgClass } from '@angular/common' import { Component, inject, Input, OnInit } from '@angular/core' import { RouterLink } from '@angular/router' -import { NgbModal, NgbTooltip } from '@ng-bootstrap/ng-bootstrap' +import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { TranslatePipe, TranslateService } from '@ngx-translate/core' import { ToastrService } from 'ngx-toastr' import { firstValueFrom } from 'rxjs' @@ -12,7 +12,6 @@ import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.s import { SettingsService } from '@/app/core/settings.service' import { IoNamespace, WsService } from '@/app/core/ws.service' import { HbV2ModalComponent } from '@/app/modules/status/widgets/update-info-widget/hb-v2-modal/hb-v2-modal.component' -import { UiV5ModalComponent } from '@/app/modules/status/widgets/update-info-widget/ui-v5-modal/ui-v5-modal.component' @Component({ templateUrl: './update-info-widget.component.html', @@ -22,7 +21,6 @@ import { UiV5ModalComponent } from '@/app/modules/status/widgets/update-info-wid NgClass, TranslatePipe, RouterLink, - NgbTooltip, ], }) export class UpdateInfoWidgetComponent implements OnInit { @@ -45,7 +43,6 @@ export class UpdateInfoWidgetComponent implements OnInit { public serverInfo: any public isRunningHbV2 = false - public isRunningUiV5 = false public isHbV2Ready = false public isUiV5Ready = false @@ -119,11 +116,6 @@ export class UpdateInfoWidgetComponent implements OnInit { const response = await firstValueFrom(this.io.request('homebridge-ui-version-check')) this.homebridgeUiPkg = response this.$settings.env.homebridgeUiVersion = response.installedVersion - this.isRunningUiV5 = response.installedVersion.startsWith('5.') - this.isUiV5Ready = this.homebridgeUiPkg.readyForV5.node - && this.homebridgeUiPkg.readyForV5.service - && this.homebridgeUiPkg.readyForV5.pnpm - && this.homebridgeUiPkg.readyForV5.arch } catch (error) { console.error(error) this.$toastr.error(error.message, this.$translate.instant('toast.title_error')) @@ -179,12 +171,4 @@ export class UpdateInfoWidgetComponent implements OnInit { }) ref.componentInstance.isUpdating = false } - - readyForV5Modal() { - const ref = this.$modal.open(UiV5ModalComponent, { - size: 'lg', - backdrop: 'static', - }) - ref.componentInstance.readyForV5 = this.homebridgeUiPkg.readyForV5 - } } From 2fb8c4e086191529bd2762c3287e0a28aeca62fc Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 26 Oct 2024 11:38:11 +0100 Subject: [PATCH 15/22] bump the default node version from 20 to 22 --- .github/workflows/validate.yml | 2 +- CHANGELOG.md | 1 + src/modules/status/status.service.ts | 26 ++++++++++++-------------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 32d82c7f5..1ea3e25a6 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -39,7 +39,7 @@ jobs: matrix: os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] - node-version: [18.x, 20.x, 22.x] + node-version: [20.x, 22.x] runs-on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 45d18bd09..3a57e3a0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. ### Other Changes - retire use of `pnpm` and code references +- bump the default node version from 20 to 22 ### Homebridge Dependencies diff --git a/src/modules/status/status.service.ts b/src/modules/status/status.service.ts index 94d8103c4..bc478c314 100644 --- a/src/modules/status/status.service.ts +++ b/src/modules/status/status.service.ts @@ -471,7 +471,6 @@ export class StatusService { // Get the newest v18 and v20 in the list const latest18 = versionList.filter((x: { version: string }) => x.version.startsWith('v18'))[0] - const latest20 = versionList.filter((x: { version: string }) => x.version.startsWith('v20'))[0] const latest22 = versionList.filter((x: { version: string }) => x.version.startsWith('v22'))[0] let updateAvailable = false @@ -484,25 +483,26 @@ export class StatusService { * * 18 2.28 * 20 2.31 + * 22 2.31 (assumption - the code below assumes this) */ // Behaviour depends on the installed version of node switch (process.version.split('.')[0]) { case 'v18': { - // Currently using v18, but v20 is available + // Currently using v18, but v22 is available // If the user is running linux, then check their glibc version - // If they are running glibc 2.31 or higher, then show the option to update to v20 + // If they are running glibc 2.31 or higher, then show the option to update to v22 // Otherwise we would still want to see if there is a minor/patch update available for v18 - // Otherwise, already show the option for updating to node 20 + // Otherwise, already show the option for updating to node 22 if (platform() === 'linux') { const glibcVersion = this.getGlibcVersion() if (glibcVersion) { if (Number.parseFloat(glibcVersion) >= 2.31) { - // Glibc version is high enough to support v20 + // Glibc version is high enough to support v22 updateAvailable = true - latestVersion = latest20.version + latestVersion = latest22.version } else { - // Glibc version is too low to support v20 + // Glibc version is too low to support v22 // Check if there is a new minor/patch version available if (gt(latest18.version, process.version)) { updateAvailable = true @@ -516,19 +516,17 @@ export class StatusService { } } } else { - // Not running linux, so show the option for updating to node 20 + // Not running linux, so show the option for updating to node 22 updateAvailable = true - latestVersion = latest20.version + latestVersion = latest22.version } break } case 'v20': { // Currently using v20 - // Check if there is a new minor/patch version available - if (gt(latest20.version, process.version)) { - updateAvailable = true - latestVersion = latest20.version - } + // Show the option for updating to node 22 + updateAvailable = true + latestVersion = latest22.version break } case 'v22': { From fa13ccc906b71070a60fc37fbee9a9e5fcdd5f21 Mon Sep 17 00:00:00 2001 From: Donavan Becker Date: Mon, 28 Oct 2024 20:30:46 -0500 Subject: [PATCH 16/22] Update Default Dashboard Layout --- CHANGELOG.md | 4 + .../status/default-dashboard-layout.json | 109 ++++++++++-------- 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a57e3a0a..4d4fd1916 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,10 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - Drops support for Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware - Drops support for instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt) +### UI Changes + +- update default dashboard layout + ### Other Changes - retire use of `pnpm` and code references diff --git a/ui/src/app/modules/status/default-dashboard-layout.json b/ui/src/app/modules/status/default-dashboard-layout.json index 99a335e15..834d68a33 100644 --- a/ui/src/app/modules/status/default-dashboard-layout.json +++ b/ui/src/app/modules/status/default-dashboard-layout.json @@ -2,82 +2,99 @@ { "component": "UpdateInfoWidgetComponent", "x": 0, - "y": 0, - "cols": 5, - "rows": 7, + "y": 6, + "cols": 4, + "rows": 6, "mobileOrder": 10, - "hideOnMobile": false + "hidePort": true, + "hideOnMobile": false, + "draggable": true }, { "component": "BridgesWidgetComponent", - "x": 0, - "y": 7, - "cols": 5, - "rows": 7, - "mobileOrder": 35, - "hideOnMobile": false - }, - { - "component": "HomebridgeLogsWidgetComponent", - "x": 5, - "y": 0, - "cols": 10, - "rows": 8, - "mobileOrder": 1000, - "hideOnMobile": true - }, - { - "component": "SystemInfoWidgetComponent", "x": 15, "y": 0, "cols": 5, - "rows": 9, - "mobileOrder": 70, - "hideOnMobile": false - }, - { - "component": "HapQrcodeWidgetComponent", - "x": 15, - "y": 9, - "cols": 5, - "rows": 5, - "mobileOrder": 100, - "hideOnMobile": false + "rows": 12, + "mobileOrder": 35, + "hideOnMobile": false, + "draggable": true }, { "component": "CpuWidgetComponent", - "x": 5, - "y": 8, + "x": 4, + "y": 0, "cols": 5, "rows": 3, "mobileOrder": 40, - "hideOnMobile": false + "hideOnMobile": false, + "draggable": true, + "refreshInterval": 10, + "historyItems": 60 }, { "component": "MemoryWidgetComponent", - "x": 5, - "y": 11, + "x": 4, + "y": 3, "cols": 5, "rows": 3, "mobileOrder": 50, - "hideOnMobile": false + "hideOnMobile": false, + "draggable": true, + "refreshInterval": 10, + "historyItems": 60 }, { "component": "NetworkWidgetComponent", - "x": 10, - "y": 11, + "x": 4, + "y": 6, "cols": 5, "rows": 3, "mobileOrder": 55, - "hideOnMobile": false + "hideOnMobile": false, + "draggable": true, + "refreshInterval": 10, + "historyItems": 60, + "networkInterface": "en0" }, { "component": "UptimeWidgetComponent", - "x": 10, - "y": 8, + "x": 4, + "y": 9, "cols": 5, "rows": 3, "mobileOrder": 60, - "hideOnMobile": false + "hideOnMobile": false, + "draggable": true + }, + { + "component": "SystemInfoWidgetComponent", + "x": 9, + "y": 0, + "cols": 6, + "rows": 12, + "mobileOrder": 70, + "hideOnMobile": false, + "draggable": true + }, + { + "component": "HapQrcodeWidgetComponent", + "x": 0, + "y": 0, + "cols": 4, + "rows": 6, + "mobileOrder": 100, + "hideOnMobile": false, + "draggable": true + }, + { + "component": "HomebridgeLogsWidgetComponent", + "x": 0, + "y": 12, + "cols": 20, + "rows": 7, + "mobileOrder": 1000, + "hideOnMobile": true, + "draggable": true } ] From ad40ce91841016ad87411da993c31ff7b0b4848b Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Fri, 22 Nov 2024 09:44:23 +0000 Subject: [PATCH 17/22] make terminal enabled by default on new macOS hb-service installs --- CHANGELOG.md | 1 + src/bin/platforms/darwin.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d4fd1916..dfd3e308a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - retire use of `pnpm` and code references - bump the default node version from 20 to 22 +- make terminal enabled by default on new macOS hb-service installs ### Homebridge Dependencies diff --git a/src/bin/platforms/darwin.ts b/src/bin/platforms/darwin.ts index 562f10d5f..f3dcb35c9 100644 --- a/src/bin/platforms/darwin.ts +++ b/src/bin/platforms/darwin.ts @@ -385,6 +385,8 @@ export class DarwinInstaller extends BasePlatform { ` ${this.getUserHomeDir()}`, ' UIX_STORAGE_PATH', ` ${this.hbService.storagePath}`, + ' HOMEBRIDGE_CONFIG_UI_TERMINAL', + ' 1', ' ', '', '', From 91ad2fcb33b05fa163e24bba47ea16ca6ce2a1e9 Mon Sep 17 00:00:00 2001 From: l1500s Date: Mon, 25 Nov 2024 11:18:46 +0200 Subject: [PATCH 18/22] updates to the `fi.json` language file (#2253) --- CHANGELOG.md | 1 + ui/src/i18n/fi.json | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfd3e308a..3f68fbf6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. ### UI Changes +- updates to the `fi.json` language file (#2253) (@l1500s) - update default dashboard layout ### Other Changes diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 31c524d8e..62af8e471 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -28,7 +28,7 @@ "accessories.control.current": "Current", "accessories.control.default_room": "Oletus huone", "accessories.control.dehumidify": "Dehumidify", - "accessories.control.detected": "Detected", + "accessories.control.detected": "Havaittu", "accessories.control.drag_here": "Raaha tähän", "accessories.control.heat": "Lämmitys", "accessories.control.home": "Koti", @@ -42,7 +42,7 @@ "accessories.control.mode": "Mode", "accessories.control.mute": "Vaimennus", "accessories.control.night": "Yö", - "accessories.control.not_detected": "Not Detected", + "accessories.control.not_detected": "Ei havaittu", "accessories.control.not_mute": "Päällä", "accessories.control.off": "Pois", "accessories.control.on": "Päällä", @@ -171,9 +171,9 @@ "form.button_unpair": "Pura pariliitos", "form.label.changes_kept": "Note that existing selections/changes are preserved when switching between items.", "form.label_continue": "Jatka", - "form.label_invalid": "Config validation failed - you can still save your changes.", - "form.label_invalid_strict": "Config validation failed - please review the form before saving.", - "form.label_valid": "Config validation passed.", + "form.label_invalid": "Asetuksia ei hyväksytty - voit siitä huolimatta tallentaa muutokset.", + "form.label_invalid_strict": "Asetuksia ei hyväksytty - ole hyvä ja tarkista tiedot ennen tallentamista.", + "form.label_valid": "Asetukset hyväksytty.", "form.select.auto": "Automattinen (Käytä selaimen asetuksia)", "login.invalid_code": "The code entered is incorrect or has expired", "login.invalid_credentials": "Väärä käyttäjätunnus tai salasana", @@ -204,7 +204,7 @@ "menu.linux.label_shutdown_server": "Sulje järjestelmä", "menu.linux.label_terminal": "Pääte", "menu.reload": "Reload", - "menu.restart.title": "Käynnistys optiot", + "menu.restart.title": "Käynnistys valinnat", "menu.settings.title": "Asetukset", "menu.tooltip_logout": "Kirjaudu ulos", "menu.tooltip_restart": "Uudelleenkäynnistä", @@ -277,12 +277,12 @@ "plugins.manage.more_info": "More information about scoped {{ scopedLink }} and verified {{ verifiedLink }} plugins.", "plugins.manage.online_updates": "Online päivitykset eivät toimi Windowsissa. Sinun on tehtävä päivitys käsin Homebridge palvelun pysäyttämisen jälkeen.", "plugins.manage.plugin_logs": "Laajennusten lokitiedot", - "plugins.manage.scoped.error": "An error occurred. You can download the logs below.", + "plugins.manage.scoped.error": "Virhe havaittu. Alapuolelta voit ladata lokitiedot.", "plugins.manage.scoped.info_1": "Homebridge scoped plugins have names beginning with {{ prefix }}.", "plugins.manage.scoped.info_2": "For more information about scoped plugins and why to switch, see the wiki page {{ link }}.", - "plugins.manage.scoped.process": "This process will not affect your Homebridge/HomeKit accessories. You will not be able to cancel the process once it has started. It will:", + "plugins.manage.scoped.process": "Tämä prosessi ei vaikuta Homebridge/HomeKit lisälaitteisiin. Prosessia ei voi peruuttaa enää käynnistyksen jälkeen. Se:", "plugins.manage.scoped.switch": "Switch To Scoped Plugin", - "plugins.manage.scoped.windows": "Online updates are not supported on Windows. You will need to install the new plugin and uninstall the old plugin manually. You should not restart Homebridge until both steps are complete.", + "plugins.manage.scoped.windows": "Online-päivityksiä ei tueta Windowsissa. Sinun on asennettava uusi laajennus ja poistettava vanha laajennus käsin.", "plugins.manage.scoped_message": "Scoped plugins improve long-term reliability and ensure consistent maintenance by combining centralized oversight from the Homebridge team with continued involvement from the original maintainer.", "plugins.manage.scoped_subtitle": "This plugin is scoped and verified.", "plugins.manage.select_version": "Valitse asennettava versio", @@ -532,11 +532,11 @@ "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Nykyinen käyttöjärjestelmäsi versio ei tue Node.js:n uudempia versioita. Jotta voit ratkaista tämän ja pystyä asentamaan päivitetyt versiot Node.js:stä tulevaisuudessa, sinun on päivitettävä käyttöjärjestelmäsi uudempaan versioon.", "status.widget.info.glibc_title": "Käyttöjärjestelmän Päivitys", - "status.widget.info.hostname": "Hostname", + "status.widget.info.hostname": "Isäntänimi", "status.widget.info.ipv4": "IPv4", "status.widget.info.ipv6": "IPv6", "status.widget.info.no": "Ei", - "status.widget.info.node_unsupp": "Unsupported", + "status.widget.info.node_unsupp": "Ei tuettu", "status.widget.info.node_unsupp_message": "Käytät Node.js-versiota, jota Homebridge ei tue virallisesti. Sinun tulisi harkita vaihtamista tuettuun versioon.", "status.widget.info.node_unsupp_title": "Ei tuettu Node versio", "status.widget.info.node_update_message": "Homebridge vaatii toimiakseen Node.js:n, joka on asennettu järjestelmään. Sinun on aika ajoin päivitettävä Node.js, jotta voit ottaa käyttöön tuen uusille ominaisuuksille. Homebridge (ja vahvistetut laajennukset) tukevat kaikkia Node.js:n nykyisiä Active- ja Maintenance LTS -julkaisuja.", @@ -561,7 +561,7 @@ "status.widget.network.seconds": "sekuntia", "status.widget.qr_paired": "Paritettu", "status.widget.qr_unpaired": "Ei paritettu", - "status.widget.show_hide": "Show/Hide Widgets", + "status.widget.show_hide": "Näytä/Piilota sovelmat", "status.widget.title_manage_widget": "Hallitse sovelmaa", "status.widget.uptime.label_process": "Prosessi", "status.widget.uptime.label_server": "Palvelin", From d5dfbd65a604e12586e43c8d5ce86903a291f171 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sun, 26 Jan 2025 11:58:19 +0000 Subject: [PATCH 19/22] set service mode as default, remove standalone --- CHANGELOG.md | 1 + config.schema.json | 136 +----------------- src/core/config/config.service.ts | 14 +- src/index.ts | 58 +------- src/modules/backup/backup.service.ts | 90 +----------- .../child-bridges/child-bridges.service.ts | 11 +- .../hb-service/hb-service.controller.ts | 2 +- src/modules/plugins/plugins.service.ts | 3 - src/modules/server/server.controller.ts | 10 -- src/modules/server/server.service.ts | 37 +---- src/modules/status/status.controller.ts | 1 - src/modules/status/status.service.ts | 50 ++----- .../e2e/platform-tools-hb-service.e2e-spec.ts | 2 - test/e2e/plugins.e2e-spec.ts | 2 +- test/e2e/server.e2e-spec.ts | 34 +---- test/e2e/status.e2e-spec.ts | 43 ++---- .../custom-plugins.component.ts | 4 +- .../manage-plugin.component.html | 4 - .../manage-plugin/manage-plugin.component.ts | 3 - .../manual-config/manual-config.component.ts | 4 +- .../plugin-bridge.component.html | 5 +- .../plugin-bridge/plugin-bridge.component.ts | 14 +- .../plugin-config/plugin-config.component.ts | 4 +- .../switch-to-scoped.component.html | 15 +- .../uninstall-plugin.component.html | 2 +- .../uninstall-plugin.component.ts | 2 +- ui/src/app/core/settings.service.ts | 1 - .../plugin-card/plugin-card.component.html | 2 - .../app/modules/plugins/plugins.component.ts | 1 - .../modules/settings/settings.component.html | 21 +-- .../modules/settings/settings.component.ts | 30 ++-- .../widget-visibility.component.ts | 2 +- .../system-info-widget.component.html | 10 -- .../system-info-widget.component.ts | 12 -- ui/src/i18n/bg.json | 5 - ui/src/i18n/ca.json | 5 - ui/src/i18n/cs.json | 5 - ui/src/i18n/de.json | 5 - ui/src/i18n/en.json | 5 - ui/src/i18n/es.json | 5 - ui/src/i18n/fi.json | 5 - ui/src/i18n/fr.json | 5 - ui/src/i18n/he.json | 5 - ui/src/i18n/hu.json | 5 - ui/src/i18n/id.json | 5 - ui/src/i18n/it.json | 5 - ui/src/i18n/ja.json | 5 - ui/src/i18n/ko.json | 5 - ui/src/i18n/mk.json | 5 - ui/src/i18n/nl.json | 5 - ui/src/i18n/no.json | 5 - ui/src/i18n/pl.json | 5 - ui/src/i18n/pt-BR.json | 5 - ui/src/i18n/pt.json | 5 - ui/src/i18n/ru.json | 5 - ui/src/i18n/sl.json | 5 - ui/src/i18n/sv.json | 5 - ui/src/i18n/th.json | 5 - ui/src/i18n/tr.json | 5 - ui/src/i18n/uk.json | 5 - ui/src/i18n/zh-CN.json | 5 - ui/src/i18n/zh-TW.json | 5 - 62 files changed, 72 insertions(+), 698 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f68fbf6d..e6203e05d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - retire use of `pnpm` and code references - bump the default node version from 20 to 22 - make terminal enabled by default on new macOS hb-service installs +- set service mode as default, remove standalone ### Homebridge Dependencies diff --git a/config.schema.json b/config.schema.json index da6edc5ce..47de56968 100644 --- a/config.schema.json +++ b/config.schema.json @@ -176,12 +176,6 @@ } ] }, - "restart": { - "title": "Custom Restart Command", - "type": "string", - "description": "If no restart command is set the process will terminate with a non-zero exit code.", - "placeholder": "eg. sudo systemctl restart homebridge" - }, "temp": { "title": "OS Temp File Path", "type": "string", @@ -398,22 +392,12 @@ "type": "string", "placeholder": "eg. /home/pi/mywallpaper.jpg" }, - "sudo": { - "title": "Use Sudo", - "type": "boolean", - "description": "If you are running Homebridge as root, you may need to enable this option." - }, "homebridgePackagePath": { "title": "Path To Homebridge Module", "type": "string", "description": "If you have multiple versions of Homebridge installed, you can specify the path to the version you want to use here.", "placeholder": "eg. /usr/local/lib/node_modules/homebridge" }, - "noFork": { - "title": "Do not run the UI server in a separate process/thread", - "type": "boolean", - "description": "If you are running Homebridge in a container, you may need to enable this option." - }, "host": { "title": "Host IP Address", "type": "string", @@ -421,16 +405,6 @@ "description": "The host IP address to listen on. In most cases this will be '::' or '0.0.0.0'.", "placeholder": "eg. 0.0.0.0" }, - "debug": { - "title": "Enable Debug Logging", - "type": "boolean", - "description": "If enabled, the Homebridge UI will log debug level messages to the console." - }, - "standalone": { - "title": "Tell Homebridge the plugin is operating in standalone mode", - "type": "boolean", - "description": "If you are running Homebridge in a container, you may need to enable this option." - }, "sessionTimeout": { "title": "Session Timeout (Seconds)", "type": "integer", @@ -447,79 +421,6 @@ "title": "Log Settings", "description": "The log settings for the Homebridge UI.", "properties": { - "method": { - "title": "Log Method", - "type": "string", - "default": "", - "description": "The method used to read the Homebridge log file.", - "oneOf": [ - { - "title": "Default", - "enum": [ - "" - ] - }, - { - "title": "From File", - "enum": [ - "file" - ] - }, - { - "title": "Systemd", - "enum": [ - "systemd" - ] - }, - { - "title": "Custom Command", - "enum": [ - "custom" - ] - } - ] - }, - "path": { - "title": "Log File Path", - "type": "string", - "description": "Enter the full file path to your log file.", - "placeholder": "/var/log/homebridge.log", - "condition": { - "functionBody": "return (model.log && model.log.method==='file')" - } - }, - "service": { - "title": "Systemd Service", - "type": "string", - "description": "Enter the systemd service name. Defaults to 'homebridge'.", - "placeholder": "homebridge", - "condition": { - "functionBody": "return (model.log && model.log.method==='systemd')" - } - }, - "command": { - "title": "Custom Command", - "description": "This command should stream the logs to stdout.", - "type": "string", - "placeholder": "journalctl -f -n 100 -u homebridge", - "condition": { - "functionBody": "return (model.log && model.log.method==='custom')" - } - }, - "tail": { - "type": "string", - "description": "Deprecated.", - "condition": { - "functionBody": "return (model.log && (model.log.method==='custom' || model.log.method==='systemd' || model.log.method==='file'))" - } - }, - "systemd": { - "type": "string", - "description": "Deprecated.", - "condition": { - "functionBody": "return (model.log && (model.log.method==='custom' || model.log.method==='systemd' || model.log.method==='file'))" - } - }, "maxSize": { "type": "integer", "description": "The max log size (bytes). Set to -1 to disable log truncation.", @@ -653,40 +554,5 @@ } } }, - "layout": [ - { - "ref": "log", - "type": "fieldset", - "expandable": true, - "title": "Log Settings", - "items": [ - "log.method", - "log.path", - "log.service", - "log.command", - "log.tail", - "log.systemd" - ] - }, - { - "ref": "homebridge", - "type": "fieldset", - "expandable": true, - "title": "Homebridge Settings", - "items": [ - "sudo", - "restart" - ] - }, - { - "ref": "container", - "type": "fieldset", - "expandable": true, - "title": "Container Settings", - "items": [ - "standalone", - "noFork" - ] - } - ] + "layout": [] } diff --git a/src/core/config/config.service.ts b/src/core/config/config.service.ts index 7bf298442..01b992396 100644 --- a/src/core/config/config.service.ts +++ b/src/core/config/config.service.ts @@ -37,8 +37,7 @@ export class ConfigService { public homebridgeVersion: string // Server env - public minimumNodeVersion = '14.15.0' - public serviceMode = (process.env.UIX_SERVICE_MODE === '1') + public minimumNodeVersion = '20.18.0' public runningInDocker = Boolean(process.env.HOMEBRIDGE_CONFIG_UI === '1') public runningInSynologyPackage = Boolean(process.env.HOMEBRIDGE_SYNOLOGY_PACKAGE === '1') public runningInPackageMode = Boolean(process.env.HOMEBRIDGE_APT_PACKAGE === '1') @@ -112,12 +111,10 @@ export class ConfigService { temp?: string tempUnits?: string wallpaper?: string - noFork?: boolean linux?: { shutdown?: string restart?: string } - standalone?: boolean debug?: boolean proxyHost?: string sessionTimeout?: number @@ -166,9 +163,7 @@ export class ConfigService { this.setConfigForDocker() } - if (this.serviceMode) { - this.setConfigForServiceMode() - } + this.setConfig() if (!this.ui.port) { this.ui.port = 8080 @@ -209,7 +204,6 @@ export class ConfigService { packageVersion: this.package.version, platform: platform(), port: this.ui.port, - serviceMode: this.serviceMode, setupWizardComplete: this.setupWizardComplete, }, formAuth: Boolean(this.ui.auth !== 'none'), @@ -332,9 +326,9 @@ export class ConfigService { } /** - * Populate the required config when running in "Service Mode" + * Populate the required config */ - private setConfigForServiceMode() { + private setConfig() { this.homebridgeInsecureMode = Boolean(process.env.UIX_INSECURE_MODE === '1') this.ui.restart = undefined this.ui.sudo = (platform() === 'linux' && !this.runningInDocker && !this.runningInSynologyPackage && !this.runningInPackageMode) || platform() === 'freebsd' diff --git a/src/index.ts b/src/index.ts index 7f25f8f28..71edc3a52 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,8 +2,6 @@ * Homebridge Entry Point */ -import { fork } from 'node:child_process' -import { resolve } from 'node:path' import process from 'node:process' import { Command } from 'commander' @@ -35,57 +33,6 @@ class HomebridgeUi { log.error(msg) log.warn(msg) } - - if (process.env.UIX_SERVICE_MODE === '1' && process.connected) { - this.log('Running in service mode.') - } else if (config.standalone || process.env.UIX_SERVICE_MODE === '1' - || (process.env.HOMEBRIDGE_CONFIG_UI === '1' && satisfies(process.env.CONFIG_UI_VERSION, '>=3.5.5', { includePrerelease: true }))) { - this.log.warn('*********** Homebridge Standalone Mode Is Deprecated **********') - this.log.warn('* Please swap to service mode using the hb-service command. *') - this.log.warn('* See https://homebridge.io/w/JUvQr for instructions on how to migrate. *') - this.log('Running in standalone mode.') - } else if (config.noFork) { - this.noFork() - } else { - this.fork() - } - } - - /** - * Run plugin as a separate node.js process - */ - fork() { - const ui = fork(resolve(__dirname, 'bin/fork'), null, { - env: process.env, - }) - - this.log('Spawning Homebridge UI with PID', ui.pid) - - ui.on('close', () => { - process.kill(process.pid, 'SIGTERM') - }) - - ui.on('error', () => { - // Do nothing - }) - } - - /** - * Run plugin in the main homebridge process - */ - async noFork() { - await import('./main') - } - - /** - * Set up the service mode process helper - * This ensures the Homebridge process is killed when hb-service - * is killed with SIGTERM to prevent stale processes. - */ - static serviceMode() { - process.on('disconnect', () => { - process.exit() - }) } accessories(callback) { @@ -98,8 +45,5 @@ class HomebridgeUi { export = (api) => { homebridge = api homebridge.registerPlatform('homebridge-config-ui-x', 'config', HomebridgeUi) - - if (process.env.UIX_SERVICE_MODE === '1' && process.connected) { - HomebridgeUi.serviceMode() - } + process.on('disconnect', () => process.exit()) } diff --git a/src/modules/backup/backup.service.ts b/src/modules/backup/backup.service.ts index 6f3177899..f1ac80376 100644 --- a/src/modules/backup/backup.service.ts +++ b/src/modules/backup/backup.service.ts @@ -3,7 +3,6 @@ import type { FastifyReply } from 'fastify' import type { HomebridgePlugin } from '../plugins/types' -import { exec, execSync } from 'node:child_process' import { EventEmitter } from 'node:events' import { platform, tmpdir } from 'node:os' import { basename, join, resolve } from 'node:path' @@ -558,13 +557,6 @@ export class BackupService { if (uiConfigBlock) { uiConfigBlock.port = this.configService.ui.port - - // Delete unnecessary config in service mode / docker - if (this.configService.serviceMode || this.configService.runningInDocker) { - delete uiConfigBlock.restart - delete uiConfigBlock.sudo - delete uiConfigBlock.log - } } else { restoredConfig.platforms.push({ name: 'Config', @@ -756,85 +748,13 @@ export class BackupService { */ postBackupRestoreRestart() { setTimeout(() => { - // If running in service mode - if (this.configService.serviceMode) { - // Kill homebridge - this.homebridgeIpcService.killHomebridge() - - // Kill self - setTimeout(() => { - process.kill(process.pid, 'SIGKILL') - }, 500) - - return - } - - // If running in docker - if (this.configService.runningInDocker) { - try { - return execSync('killall -9 homebridge; kill -9 $(pidof homebridge-config-ui-x);') - } catch (e) { - this.logger.error(`Failed to restart Homebridge as ${e.message}.`) - this.logger.error(e) - } - } + // Kill homebridge + this.homebridgeIpcService.killHomebridge() - // If running as a fork, kill the parent homebridge process - if (process.connected) { - process.kill(process.ppid, 'SIGKILL') + // Kill self + setTimeout(() => { process.kill(process.pid, 'SIGKILL') - } - - // If running with noFork - if (this.configService.ui.noFork) { - return process.kill(process.pid, 'SIGKILL') - } - - // If running in standalone mode, need to find the pid of homebridge and kill it - if (platform() === 'linux' && this.configService.ui.standalone) { - try { - // Try to get pid by port - const getPidByPort = (port: number): number => { - try { - return Number.parseInt(execSync( - `fuser ${port}/tcp 2>/dev/null`, - ).toString('utf8').trim(), 10) - } catch (e) { - return null - } - } - - // Try to get pid by name - const getPidByName = (): number => { - try { - return Number.parseInt(execSync('pidof homebridge').toString('utf8').trim(), 10) - } catch (e) { - return null - } - } - - const homebridgePid = getPidByPort(this.configService.homebridgeConfig.bridge.port) || getPidByName() - - if (homebridgePid) { - process.kill(homebridgePid, 'SIGKILL') - return process.kill(process.pid, 'SIGKILL') - } - } catch (e) { - // Just proceed to the users restart command - } - } - - // Try the users restart command - if (this.configService.ui.restart) { - return exec(this.configService.ui.restart, (err) => { - if (err) { - this.logger.log('Restart command exited with an error, failed to restart Homebridge.') - } - }) - } - - // If all else fails just kill the current process - return process.kill(process.pid, 'SIGKILL') + }, 500) }, 500) return { status: 0 } diff --git a/src/modules/child-bridges/child-bridges.service.ts b/src/modules/child-bridges/child-bridges.service.ts index f4cf1e122..22f4c2c54 100644 --- a/src/modules/child-bridges/child-bridges.service.ts +++ b/src/modules/child-bridges/child-bridges.service.ts @@ -1,4 +1,4 @@ -import { BadRequestException, Injectable } from '@nestjs/common' +import { Injectable } from '@nestjs/common' import { ConfigService } from '../../core/config/config.service' import { HomebridgeIpcService } from '../../core/homebridge-ipc/homebridge-ipc.service' @@ -18,10 +18,6 @@ export class ChildBridgesService { * Return an array of child bridges */ public async getChildBridges() { - if (!this.configService.serviceMode) { - throw new BadRequestException('This command is only available in service mode.') - } - try { return await this.homebridgeIpcService.requestResponse('childBridgeMetadataRequest', 'childBridgeMetadataResponse') } catch (e) { @@ -63,11 +59,6 @@ export class ChildBridgesService { * @returns ok when done */ public stopStartRestartChildBridge(event: 'startChildBridge' | 'stopChildBridge' | 'restartChildBridge', deviceId: string) { - if (!this.configService.serviceMode) { - this.logger.error('The restart child bridge command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - if (deviceId.length === 12) { deviceId = deviceId.match(/.{1,2}/g).join(':') } diff --git a/src/modules/platform-tools/hb-service/hb-service.controller.ts b/src/modules/platform-tools/hb-service/hb-service.controller.ts index 17d0e68c4..f31cc5d2b 100644 --- a/src/modules/platform-tools/hb-service/hb-service.controller.ts +++ b/src/modules/platform-tools/hb-service/hb-service.controller.ts @@ -40,7 +40,7 @@ export class HbServiceController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Request the UI does a full restart next time a restart for Homebridge is sent.', - description: 'When running under hb-service the UI will only restart if it detects it needs to.', + description: 'The UI will only restart if it detects it needs to.', }) @Put('set-full-service-restart-flag') setFullServiceRestartFlag() { diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index 9e9eb69b1..30e233caf 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -934,9 +934,6 @@ export class PluginsService { // Modify this plugins schema to set the default port number if (pluginName === this.configService.name) { configSchema.schema.properties.port.default = this.configService.ui.port - - // Filter some options from the UI config when using service mode - configSchema.layout = configSchema.layout.filter((section: any) => section.ref !== 'log' && section.ref !== 'homebridge') } // Modify homebridge-alexa to set the default pin diff --git a/src/modules/server/server.controller.ts b/src/modules/server/server.controller.ts index 52105428a..00ff5c095 100644 --- a/src/modules/server/server.controller.ts +++ b/src/modules/server/server.controller.ts @@ -44,7 +44,6 @@ export class ServerController { @Put('/restart/:deviceId') @ApiOperation({ summary: 'Restart a child bridge instance.', - description: 'This method is only supported on setups running `hb-service`.', }) restartChildBridge(@Param('deviceId') deviceId: string) { return this.childBridgesService.restartChildBridge(deviceId) @@ -54,7 +53,6 @@ export class ServerController { @Put('/stop/:deviceId') @ApiOperation({ summary: 'Stop a child bridge instance.', - description: 'This method is only supported on setups running `hb-service`.', }) stopChildBridge(@Param('deviceId') deviceId: string) { return this.childBridgesService.stopChildBridge(deviceId) @@ -64,7 +62,6 @@ export class ServerController { @Put('/start/:deviceId') @ApiOperation({ summary: 'Start a child bridge instance.', - description: 'This method is only supported on setups running `hb-service`.', }) startChildBridge(@Param('deviceId') deviceId: string) { return this.childBridgesService.startChildBridge(deviceId) @@ -86,7 +83,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove Homebridge cached accessories.', - description: 'This method is only supported on setups running `hb-service`.', }) @Put('/reset-cached-accessories') deleteAllCachedAccessories() { @@ -103,7 +99,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove a single Homebridge cached accessory.', - description: 'This method is only supported on setups running `hb-service`.', }) @ApiParam({ name: 'uuid' }) @ApiQuery({ name: 'cacheFile' }) @@ -116,7 +111,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove multiple Homebridge cached accessories.', - description: 'This method is only supported on setups running `hb-service`.', }) @ApiBody({ description: 'Array of accessories (uuid and cacheFile) to remove from the cache', type: 'json', isArray: true }) @Delete('/cached-accessories') @@ -142,7 +136,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove a single paired bridge.', - description: 'This method is only supported on setups running `hb-service`.', }) @ApiParam({ name: 'deviceId' }) @ApiQuery({ name: 'resetPairingInfo', type: Boolean }) @@ -156,7 +149,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove multiple paired bridges.', - description: 'This method is only supported on setups running `hb-service`.', }) @ApiBody({ description: 'Array of paired bridges (id and resetPairingInfo) to remove from the cache', type: 'json', isArray: true }) @Delete('/pairings') @@ -168,7 +160,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove a paired bridge\'s cached accessories.', - description: 'This method is only supported on setups running `hb-service`.', }) @ApiParam({ name: 'deviceId' }) @Delete('/pairings/:deviceId/accessories') @@ -180,7 +171,6 @@ export class ServerController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Remove multiple paired bridges\'s cached accessories.', - description: 'This method is only supported on setups running `hb-service`.', }) @ApiBody({ description: 'Array of bridges (id) for which to remove accessories.', type: 'json', isArray: true }) @Delete('/pairings/accessories') diff --git a/src/modules/server/server.service.ts b/src/modules/server/server.service.ts index 49356c60c..168ec996f 100644 --- a/src/modules/server/server.service.ts +++ b/src/modules/server/server.service.ts @@ -132,7 +132,7 @@ export class ServerService { public async restartServer() { this.logger.log('Homebridge restart request received.') - if (this.configService.serviceMode && !(await this.configService.uiRestartRequired() || await this.nodeVersionChanged())) { + if (!await this.configService.uiRestartRequired() && !await this.nodeVersionChanged()) { this.logger.log('UI/Bridge settings have not changed - only restarting Homebridge process.') // Restart homebridge by killing child process this.homebridgeIpcService.restartHomebridge() @@ -255,11 +255,6 @@ export class ServerService { * Remove a device pairing */ public async deleteDevicePairing(id: string, resetPairingInfo: boolean) { - if (!this.configService.serviceMode) { - this.logger.error('The reset paired bridge command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - this.logger.warn(`Shutting down Homebridge before resetting paired bridge ${id}...`) // Wait for homebridge to stop @@ -275,11 +270,6 @@ export class ServerService { * Remove multiple device pairings */ public async deleteDevicesPairing(bridges: { id: string, resetPairingInfo: boolean }[]) { - if (!this.configService.serviceMode) { - this.logger.error('The reset multiple paired bridges command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - this.logger.warn(`Shutting down Homebridge before resetting paired bridges ${bridges.map(x => x.id).join(', ')}...`) // Wait for homebridge to stop @@ -301,11 +291,6 @@ export class ServerService { * Remove a device's accessories */ public async deleteDeviceAccessories(id: string) { - if (!this.configService.serviceMode) { - this.logger.error('The remove bridge\'s accessories command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - this.logger.warn(`Shutting down Homebridge before removing accessories for paired bridge ${id}...`) // Wait for homebridge to stop. @@ -320,11 +305,6 @@ export class ServerService { * Remove multiple devices' accessories */ public async deleteDevicesAccessories(bridges: { id: string }[]) { - if (!this.configService.serviceMode) { - this.logger.error('The remove bridges\' accessories command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - this.logger.warn(`Shutting down Homebridge before removing accessories for paired bridges ${bridges.map(x => x.id).join(', ')}...`) // Wait for homebridge to stop. @@ -367,11 +347,6 @@ export class ServerService { * Remove a single cached accessory */ public async deleteCachedAccessory(uuid: string, cacheFile: string) { - if (!this.configService.serviceMode) { - this.logger.error('The remove cached accessory command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - cacheFile = cacheFile || 'cachedAccessories' const cachedAccessoriesPath = resolve(this.configService.storagePath, 'accessories', cacheFile) @@ -400,11 +375,6 @@ export class ServerService { * Remove multiple cached accessories */ public async deleteCachedAccessories(accessories: { uuid: string, cacheFile: string }[]) { - if (!this.configService.serviceMode) { - this.logger.error('The remove cached accessories command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - this.logger.warn(`Shutting down Homebridge before removing cached accessories ${accessories.map(x => x.uuid).join(', ')}.`) // Wait for homebridge to stop. @@ -448,11 +418,6 @@ export class ServerService { * Clears the Homebridge Accessory Cache */ public async deleteAllCachedAccessories() { - if (!this.configService.serviceMode) { - this.logger.error('The remove all cached accessories command is only available in service mode.') - throw new BadRequestException('This command is only available in service mode.') - } - const cachedAccessoriesDir = join(this.configService.storagePath, 'accessories') const cachedAccessoryPaths = (await readdir(cachedAccessoriesDir)) .filter(x => x.match(/cachedAccessories\.([A-F,0-9]+)/) || x === 'cachedAccessories' || x === '.cachedAccessories.bak') diff --git a/src/modules/status/status.controller.ts b/src/modules/status/status.controller.ts index db8298219..fa800bbf3 100644 --- a/src/modules/status/status.controller.ts +++ b/src/modules/status/status.controller.ts @@ -52,7 +52,6 @@ export class StatusController { @ApiOperation({ summary: 'Return an array of the active child bridges and their status.', - description: 'This method is only available when running `hb-service`.', }) @Get('/homebridge/child-bridges') async getChildBridges() { diff --git a/src/modules/status/status.service.ts b/src/modules/status/status.service.ts index bc478c314..738566385 100644 --- a/src/modules/status/status.service.ts +++ b/src/modules/status/status.service.ts @@ -94,18 +94,16 @@ export class StatusService { this.logger.warn('Server metrics monitoring disabled.') } - if (this.configService.serviceMode) { - this.homebridgeIpcService.on('serverStatusUpdate', (data: HomebridgeStatusUpdate) => { - this.homebridgeStatus = data.status === HomebridgeStatus.OK ? HomebridgeStatus.UP : data.status + this.homebridgeIpcService.on('serverStatusUpdate', (data: HomebridgeStatusUpdate) => { + this.homebridgeStatus = data.status === HomebridgeStatus.OK ? HomebridgeStatus.UP : data.status - if (data?.setupUri) { - this.serverService.setupCode = data.setupUri - this.serverService.paired = data.paired - } + if (data?.setupUri) { + this.serverService.setupCode = data.setupUri + this.serverService.paired = data.paired + } - this.homebridgeStatusChange.next(this.homebridgeStatus) - }) - } + this.homebridgeStatusChange.next(this.homebridgeStatus) + }) } /** @@ -298,21 +296,13 @@ export class StatusService { * @param client */ public async watchStats(client: any) { - let homebridgeStatusChangeSub: Subscription let homebridgeStatusInterval: NodeJS.Timeout client.emit('homebridge-status', await this.getHomebridgeStats()) - // IPC status events are only available when running in service mode - if (this.configService.serviceMode) { - homebridgeStatusChangeSub = this.homebridgeStatusChange.subscribe(async () => { - client.emit('homebridge-status', await this.getHomebridgeStats()) - }) - } else { - homebridgeStatusInterval = setInterval(async () => { - client.emit('homebridge-status', await this.getHomebridgeStats()) - }, 10000) - } + const homebridgeStatusChangeSub: Subscription = this.homebridgeStatusChange.subscribe(async () => { + client.emit('homebridge-status', await this.getHomebridgeStats()) + }) // Cleanup on disconnect const onEnd = () => { @@ -323,9 +313,7 @@ export class StatusService { clearInterval(homebridgeStatusInterval) } - if (homebridgeStatusChangeSub) { - homebridgeStatusChangeSub.unsubscribe() - } + homebridgeStatusChangeSub.unsubscribe() } client.on('end', onEnd.bind(this)) @@ -351,19 +339,6 @@ export class StatusService { * Check if homebridge is running on the local system */ public async checkHomebridgeStatus() { - if (this.configService.serviceMode) { - return this.homebridgeStatus - } - - try { - await firstValueFrom(this.httpService.get(`http://localhost:${this.configService.homebridgeConfig.bridge.port}`, { - validateStatus: () => true, - })) - this.homebridgeStatus = HomebridgeStatus.UP - } catch (e) { - this.homebridgeStatus = HomebridgeStatus.DOWN - } - return this.homebridgeStatus } @@ -440,7 +415,6 @@ export class StatusService { homebridgeRunningInDocker: this.configService.runningInDocker, homebridgeRunningInSynologyPackage: this.configService.runningInSynologyPackage, homebridgeRunningInPackageMode: this.configService.runningInPackageMode, - homebridgeServiceMode: this.configService.serviceMode, nodeVersion: process.version, os: await this.getOsInfo(), glibcVersion: this.getGlibcVersion(), diff --git a/test/e2e/platform-tools-hb-service.e2e-spec.ts b/test/e2e/platform-tools-hb-service.e2e-spec.ts index ce8309e14..0a666094c 100644 --- a/test/e2e/platform-tools-hb-service.e2e-spec.ts +++ b/test/e2e/platform-tools-hb-service.e2e-spec.ts @@ -65,8 +65,6 @@ describe('PlatformToolsHbService (e2e)', () => { // Ensure restart required flag is cleared configService.hbServiceUiRestartRequired = false - // Enable service mode - configService.serviceMode = true configService.ui.log = { method: 'file', path: logFilePath, diff --git a/test/e2e/plugins.e2e-spec.ts b/test/e2e/plugins.e2e-spec.ts index 4f50c83a2..5100f1d16 100644 --- a/test/e2e/plugins.e2e-spec.ts +++ b/test/e2e/plugins.e2e-spec.ts @@ -176,7 +176,7 @@ describe('PluginController (e2e)', () => { expect(res.json().filter(x => x.name === 'homebridge-config-ui-rdp')).toHaveLength(0) }) - it('GET /plugins/search/:query (blacklisted - search query', async () => { + it('GET /plugins/search/:query (blacklisted - search query)', async () => { const res = await app.inject({ method: 'GET', path: `/plugins/search/${encodeURIComponent('ui')}`, diff --git a/test/e2e/server.e2e-spec.ts b/test/e2e/server.e2e-spec.ts index 321050683..1e013b24c 100644 --- a/test/e2e/server.e2e-spec.ts +++ b/test/e2e/server.e2e-spec.ts @@ -77,8 +77,6 @@ describe('ServerController (e2e)', () => { }) beforeEach(async () => { - configService.serviceMode = false - // Get auth token before each test authorization = `bearer ${(await app.inject({ method: 'POST', @@ -164,10 +162,7 @@ describe('ServerController (e2e)', () => { expect(await pathExists(accessoriesPath)).toBe(false) }) - it('PUT /server/reset-cached-accessories (service mode enabled)', async () => { - // Enable service mode - configService.serviceMode = true - + it('PUT /server/reset-cached-accessories', async () => { const res = await app.inject({ method: 'PUT', path: '/server/reset-cached-accessories', @@ -179,25 +174,7 @@ describe('ServerController (e2e)', () => { expect(res.statusCode).toBe(200) }) - it('PUT /server/reset-cached-accessories (service mode disabled)', async () => { - // Enable service mode - configService.serviceMode = false - - const res = await app.inject({ - method: 'PUT', - path: '/server/reset-cached-accessories', - headers: { - authorization, - }, - }) - - expect(res.statusCode).toBe(400) - }) - it('GET /server/cached-accessories', async () => { - // Enable service mode - configService.serviceMode = true - const res = await app.inject({ method: 'GET', path: '/server/cached-accessories', @@ -211,9 +188,6 @@ describe('ServerController (e2e)', () => { }) it('DELETE /server/cached-accessories/:uuid (valid uuid)', async () => { - // Enable service mode - configService.serviceMode = true - // Sanity check to ensure one cached accessory is preset let cachedAccessories = await readJson(resolve(accessoriesPath, 'cachedAccessories')) expect(cachedAccessories).toHaveLength(1) @@ -234,9 +208,6 @@ describe('ServerController (e2e)', () => { }) it('DELETE /server/cached-accessories/:uuid (invalid uuid)', async () => { - // Enable service mode - configService.serviceMode = true - // Sanity check to ensure one cached accessory is preset let cachedAccessories = await readJson(resolve(accessoriesPath, 'cachedAccessories')) expect(cachedAccessories).toHaveLength(1) @@ -285,9 +256,6 @@ describe('ServerController (e2e)', () => { }) it('DELETE /server/pairings/:deviceId', async () => { - // Enable service mode - configService.serviceMode = true - const res = await app.inject({ method: 'DELETE', path: '/server/pairings/67E41F0EA05D', diff --git a/test/e2e/status.e2e-spec.ts b/test/e2e/status.e2e-spec.ts index cc4467113..80f2f5ec5 100644 --- a/test/e2e/status.e2e-spec.ts +++ b/test/e2e/status.e2e-spec.ts @@ -8,17 +8,19 @@ import { HttpService } from '@nestjs/axios' import { ValidationPipe } from '@nestjs/common' import { FastifyAdapter } from '@nestjs/platform-fastify' import { Test } from '@nestjs/testing' -import { AxiosError, AxiosResponse, InternalAxiosRequestConfig } from 'axios' +import { AxiosResponse, InternalAxiosRequestConfig } from 'axios' import { copy } from 'fs-extra' -import { of, throwError } from 'rxjs' +import { of } from 'rxjs' import { afterAll, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' import { AuthModule } from '../../src/core/auth/auth.module' +import { HomebridgeIpcService } from '../../src/core/homebridge-ipc/homebridge-ipc.service' import { StatusModule } from '../../src/modules/status/status.module' describe('StatusController (e2e)', () => { let app: NestFastifyApplication let httpService: HttpService + let ipcService: HomebridgeIpcService let authFilePath: string let secretsFilePath: string @@ -55,6 +57,8 @@ describe('StatusController (e2e)', () => { await app.init() await app.getHttpAdapter().getInstance().ready() + + ipcService = app.get(HomebridgeIpcService) }) beforeEach(async () => { @@ -128,17 +132,7 @@ describe('StatusController (e2e)', () => { expect(res.json()).toHaveProperty('processUptime') }) - it('GET /status/homebridge (homebridge up)', async () => { - const response: AxiosResponse = { - data: {}, - headers: {}, - config: { url: 'http://localhost:51826' } as InternalAxiosRequestConfig, - status: 404, - statusText: 'Not Found', - } - - vi.spyOn(httpService, 'get').mockImplementationOnce(() => of(response) as any) - + it('GET /status/homebridge (homebridge down)', async () => { const res = await app.inject({ method: 'GET', path: '/status/homebridge', @@ -147,25 +141,14 @@ describe('StatusController (e2e)', () => { }, }) + // Default status is down expect(res.statusCode).toBe(200) - expect(res.json()).toEqual({ status: 'up' }) + expect(res.json()).toEqual({ status: 'down' }) }) - it('GET /status/homebridge (homebridge down)', async () => { - const response: AxiosError = { - name: 'Connection Error', - message: 'Connection Error', - toJSON: () => { - return {} - }, - isAxiosError: true, - code: null, - response: null, - config: { url: 'http://localhost:51826' } as InternalAxiosRequestConfig, - } - - vi.spyOn(httpService, 'get') - .mockImplementationOnce(() => throwError(response)) + it('GET /status/homebridge (homebridge up)', async () => { + // Set homebridge status to up + ipcService.emit('serverStatusUpdate', { status: 'up' }) const res = await app.inject({ method: 'GET', @@ -176,7 +159,7 @@ describe('StatusController (e2e)', () => { }) expect(res.statusCode).toBe(200) - expect(res.json()).toEqual({ status: 'down' }) + expect(res.json()).toEqual({ status: 'up' }) }) it('GET /status/server-information', async () => { diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts index 6c9448869..fb5eab012 100644 --- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts +++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts @@ -455,14 +455,14 @@ export class CustomPluginsComponent implements OnInit, OnDestroy { if (exit) { // Possible child bridge setup recommendation if the plugin is not Homebridge UI // If it is the first time configuring the plugin, then offer to set up a child bridge straight away - if (this.isFirstSave && this.$settings.env.recommendChildBridges && this.$settings.env.serviceMode && newConfig[0]?.platform) { + if (this.isFirstSave && this.$settings.env.recommendChildBridges && newConfig[0]?.platform) { // Close the modal and open the child bridge setup modal this.$activeModal.close() this.$plugin.bridgeSettings(this.plugin, true) return } - if (!['homebridge', 'homebridge-config-ui-x'].includes(this.plugin.name) && this.$settings.env.serviceMode) { + if (!['homebridge', 'homebridge-config-ui-x'].includes(this.plugin.name)) { await this.getChildBridges() if (this.childBridges.length > 0) { this.$activeModal.close() diff --git a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html index a571de6da..cf657f34a 100644 --- a/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html +++ b/ui/src/app/core/manage-plugins/manage-plugin/manage-plugin.component.html @@ -50,17 +50,13 @@
    • {{ 'plugins.manage.online_updates' | translate }}
    • - @if ($settings.env.serviceMode) {
    • {{ 'plugins.manage.manual_update_command' | translate }}
    • - }
    - @if ($settings.env.serviceMode) {
     hb-service stop
     npm install -g {{ pluginName }}@{{targetVersion}}
     hb-service start
    - } } @if (showReleaseNotes && !actionComplete && onlineUpdateOk) { - @if ($settings.env.serviceMode) {
  • @@ -239,7 +238,7 @@ />
  • - } } } + } } @if (configBlocks[selectedBlock]._bridge?.username && deviceInfo[configBlocks[selectedBlock]._bridge?.username] === false) { @@ -247,7 +246,7 @@
    {{ 'child_bridge.restart_homebridge' | translate }}
    {{ 'child_bridge.return_to_pair' | translate }} - } } @if (deleteBridges.length && $settings.env.serviceMode) { + } } @if (deleteBridges.length) {

    {{ 'child_bridge.confirm_delete_1' | translate }} @if (deletingPairedBridge) { {{ diff --git a/ui/src/app/core/manage-plugins/plugin-bridge/plugin-bridge.component.ts b/ui/src/app/core/manage-plugins/plugin-bridge/plugin-bridge.component.ts index 85b75ba3c..e04522e64 100644 --- a/ui/src/app/core/manage-plugins/plugin-bridge/plugin-bridge.component.ts +++ b/ui/src/app/core/manage-plugins/plugin-bridge/plugin-bridge.component.ts @@ -269,14 +269,12 @@ export class PluginBridgeComponent implements OnInit { await firstValueFrom(this.$api.post(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`, this.configBlocks)) // Delete unused bridges, so no bridges are orphaned - if (this.$settings.env.serviceMode) { - for (const bridge of this.deleteBridges) { - try { - await firstValueFrom(this.$api.delete(`/server/pairings/${bridge.id.replace(/:/g, '')}`)) - } catch (error) { - console.error(error) - this.$toastr.error(this.$translate.instant('settings.reset_bridge.error'), this.$translate.instant('toast.title_error')) - } + for (const bridge of this.deleteBridges) { + try { + await firstValueFrom(this.$api.delete(`/server/pairings/${bridge.id.replace(/:/g, '')}`)) + } catch (error) { + console.error(error) + this.$toastr.error(this.$translate.instant('settings.reset_bridge.error'), this.$translate.instant('toast.title_error')) } } diff --git a/ui/src/app/core/manage-plugins/plugin-config/plugin-config.component.ts b/ui/src/app/core/manage-plugins/plugin-config/plugin-config.component.ts index a8ce4b73c..a61a64e9f 100644 --- a/ui/src/app/core/manage-plugins/plugin-config/plugin-config.component.ts +++ b/ui/src/app/core/manage-plugins/plugin-config/plugin-config.component.ts @@ -144,7 +144,7 @@ export class PluginConfigComponent implements OnInit { } else { // Possible child bridge setup recommendation if the plugin is not Homebridge UI // If it is the first time configuring the plugin, then offer to set up a child bridge straight away - if (this.isFirstSave && this.$settings.env.recommendChildBridges && this.$settings.env.serviceMode && newConfig[0]?.platform) { + if (this.isFirstSave && this.$settings.env.recommendChildBridges && newConfig[0]?.platform) { // Close the modal and open the child bridge setup modal this.$activeModal.close() this.$plugin.bridgeSettings(this.plugin, true) @@ -152,7 +152,7 @@ export class PluginConfigComponent implements OnInit { } } - if (!['homebridge', 'homebridge-config-ui-x'].includes(this.plugin.name) && this.$settings.env.serviceMode) { + if (!['homebridge', 'homebridge-config-ui-x'].includes(this.plugin.name)) { await this.getChildBridges() if (this.childBridges.length > 0) { this.$activeModal.close() diff --git a/ui/src/app/core/manage-plugins/switch-to-scoped/switch-to-scoped.component.html b/ui/src/app/core/manage-plugins/switch-to-scoped/switch-to-scoped.component.html index 39df81637..160542915 100644 --- a/ui/src/app/core/manage-plugins/switch-to-scoped/switch-to-scoped.component.html +++ b/ui/src/app/core/manage-plugins/switch-to-scoped/switch-to-scoped.component.html @@ -22,26 +22,17 @@

  • {{ 'plugins.manage.scoped.process' | translate }}
  • } @if (!onlineUpdateOk) {
  • - @if ($settings.env.serviceMode) {
  • {{ 'plugins.manage.manual_update_command' | translate }}
  • - } } + } - @if (!onlineUpdateOk) { @if ($settings.env.serviceMode) { + @if (!onlineUpdateOk) {
     hb-service stop
     npm install -g {{ plugin.newHbScope.to }}@{{ plugin.newHbScope.switch }}
     npm uninstall -g {{ plugin.newHbScope.from }}
     hb-service start
    - } @if (!$settings.env.serviceMode) { -
      -
    • {{ 'plugins.manage.install' | translate }} {{ plugin.newHbScope.to }}
    • -
    • - {{ 'plugins.manage.uninstall' | translate }} {{ plugin.newHbScope.from }} -
    • -
    • {{ 'menu.hbrestart.title' | translate }}
    • -
    - } } @if (onlineUpdateOk) { + } @if (onlineUpdateOk) {
    • diff --git a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html index d9b80955c..a928e61ca 100644 --- a/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html +++ b/ui/src/app/core/manage-plugins/uninstall-plugin/uninstall-plugin.component.html @@ -27,7 +27,7 @@ {{ 'plugins.uninstall_remove_plugin_config' | translate }} - @if ($settings.env.serviceMode && hasChildBridges) { + @if (hasChildBridges) {
    -
  • - {{ 'menu.label_settings_advanced' | translate }} - -
  • {{ 'backup.title_backup' | translate }}
  • - }
  • {{ 'reset.bridge_all.title' | translate | titlecase }}
    diff --git a/ui/src/app/modules/settings/settings.component.ts b/ui/src/app/modules/settings/settings.component.ts index bfce9f273..1df7c763b 100644 --- a/ui/src/app/modules/settings/settings.component.ts +++ b/ui/src/app/modules/settings/settings.component.ts @@ -10,7 +10,6 @@ import { firstValueFrom } from 'rxjs' import { debounceTime } from 'rxjs/operators' import { ApiService } from '@/app/core/api.service' -import { ManagePluginsService } from '@/app/core/manage-plugins/manage-plugins.service' import { SettingsService } from '@/app/core/settings.service' import { AccessoryControlListsComponent } from '@/app/modules/settings/accessory-control-lists/accessory-control-lists.component' import { BackupComponent } from '@/app/modules/settings/backup/backup.component' @@ -81,7 +80,6 @@ interface NetworkAdapterSelected { export class SettingsComponent implements OnInit { private $api = inject(ApiService) private $modal = inject(NgbModal) - private $plugin = inject(ManagePluginsService) private $router = inject(Router) $settings = inject(SettingsService) private $toastr = inject(ToastrService) @@ -220,10 +218,7 @@ export class SettingsComponent implements OnInit { this.isHbV2 = this.$settings.env.homebridgeVersion.startsWith('2') await this.initNetworkingOptions() - - if (this.$settings.env.serviceMode) { - await this.initServiceModeForm() - } + await this.initStartupSettings() this.hbNameFormControl.patchValue(this.$settings.env.homebridgeInstanceName) this.hbNameFormControl.valueChanges @@ -348,31 +343,31 @@ export class SettingsComponent implements OnInit { .subscribe((value: string) => this.hbLinuxRestartSave(value)) } - async initServiceModeForm() { + async initStartupSettings() { try { - const serviceModeData = await firstValueFrom(this.$api.get('/platform-tools/hb-service/homebridge-startup-settings')) + const startupSettingsData = await firstValueFrom(this.$api.get('/platform-tools/hb-service/homebridge-startup-settings')) - this.hbDebugFormControl.patchValue(serviceModeData.HOMEBRIDGE_DEBUG) + this.hbDebugFormControl.patchValue(startupSettingsData.HOMEBRIDGE_DEBUG) this.hbDebugFormControl.valueChanges .pipe(debounceTime(750)) .subscribe((value: boolean) => this.hbDebugSave(value)) - this.hbInsecureFormControl.patchValue(serviceModeData.HOMEBRIDGE_INSECURE) + this.hbInsecureFormControl.patchValue(startupSettingsData.HOMEBRIDGE_INSECURE) this.hbInsecureFormControl.valueChanges .pipe(debounceTime(750)) .subscribe((value: boolean) => this.hbInsecureSave(value)) - this.hbKeepFormControl.patchValue(serviceModeData.HOMEBRIDGE_KEEP_ORPHANS) + this.hbKeepFormControl.patchValue(startupSettingsData.HOMEBRIDGE_KEEP_ORPHANS) this.hbKeepFormControl.valueChanges .pipe(debounceTime(750)) .subscribe((value: boolean) => this.hbKeepSave(value)) - this.hbEnvDebugFormControl.patchValue(serviceModeData.ENV_DEBUG) + this.hbEnvDebugFormControl.patchValue(startupSettingsData.ENV_DEBUG) this.hbEnvDebugFormControl.valueChanges .pipe(debounceTime(1500)) .subscribe((value: string) => this.hbEnvDebugSave(value)) - this.hbEnvNodeFormControl.patchValue(serviceModeData.ENV_NODE_OPTIONS) + this.hbEnvNodeFormControl.patchValue(startupSettingsData.ENV_NODE_OPTIONS) this.hbEnvNodeFormControl.valueChanges .pipe(debounceTime(1500)) .subscribe((value: string) => this.hbEnvNodeSave(value)) @@ -1096,15 +1091,6 @@ export class SettingsComponent implements OnInit { } } - openUiSettings() { - this.$plugin.settings({ - name: 'homebridge-config-ui-x', - displayName: 'Homebridge UI', - settingsSchema: true, - links: {}, - }) - } - openBackupModal() { this.$modal.open(BackupComponent, { size: 'lg', diff --git a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts index a6313d4ba..a3b105a06 100644 --- a/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts +++ b/ui/src/app/modules/status/widget-visibility/widget-visibility.component.ts @@ -58,7 +58,7 @@ export class WidgetVisibilityComponent implements OnInit { { name: this.$translate.instant('child_bridge.bridges'), component: 'BridgesWidgetComponent', - hidden: !this.$settings.env.serviceMode, + hidden: false, cols: 5, rows: 9, mobileOrder: 35, diff --git a/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.html b/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.html index 6f1861bd4..9d3a8c4ca 100644 --- a/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.html +++ b/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.html @@ -81,16 +81,6 @@ {{ 'status.widget.info.synology_package' | translate }} {{ 'status.widget.info.yes' | translate }} - } @if (!serverInfo.homebridgeServiceMode) { - - {{ 'status.widget.info.service_mode' | translate }} - - - - - {{ 'status.widget.info.disabled' | translate }} - - } diff --git a/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.ts b/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.ts index 5ca1ce101..9b1a8c435 100644 --- a/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.ts +++ b/ui/src/app/modules/status/widgets/system-info-widget/system-info-widget.component.ts @@ -62,16 +62,4 @@ export class SystemInfoWidgetComponent implements OnInit { ref.componentInstance.faIconClass = 'fab fa-fw fa-node-js primary-text' ref.componentInstance.ctaButtonLink = 'https://github.com/homebridge/homebridge-config-ui-x/wiki/Troubleshooting/#error---update-node---your-version-of-linux-does-not-meet-the-glibc-version' } - - serviceModeModal() { - const ref = this.$modal.open(InformationComponent, { - size: 'lg', - backdrop: 'static', - }) - ref.componentInstance.title = this.$translate.instant('status.widget.info.servicemode_title') - ref.componentInstance.message = this.$translate.instant('status.widget.info.servicemode_message') - ref.componentInstance.ctaButtonLabel = this.$translate.instant('form.button_more_info') - ref.componentInstance.faIconClass = 'fas fa-fw fa-circle-exclamation primary-text' - ref.componentInstance.ctaButtonLink = 'https://github.com/homebridge/homebridge-config-ui-x/wiki/How-To-Swap-From-Standalone-Mode-to-Service-Mode' - } } diff --git a/ui/src/i18n/bg.json b/ui/src/i18n/bg.json index 1ef2b17eb..dcf25761c 100644 --- a/ui/src/i18n/bg.json +++ b/ui/src/i18n/bg.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Аксесоари", "menu.label_plugins": "Добавки", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Статус", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Рестартирай Сървъра", @@ -528,7 +527,6 @@ "status.widget.info": "System Information", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config Path", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin Path", - "status.widget.info.service_mode": "Service Mode", "status.widget.info.service_user": "User", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Storage Path", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Time Zone", diff --git a/ui/src/i18n/ca.json b/ui/src/i18n/ca.json index 56ba30ed5..946e229ff 100644 --- a/ui/src/i18n/ca.json +++ b/ui/src/i18n/ca.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Accessoris", "menu.label_plugins": "Plugins", "menu.label_settings": "Ajustos", - "menu.label_settings_advanced": "Ajustos Avançats de la IU", "menu.label_status": "Estat", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Reiniciar Servidor", @@ -528,7 +527,6 @@ "status.widget.info": "Informació del sistema", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Ruta de configuració", - "status.widget.info.disabled": "No", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "Actualització del OS", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "Sistema operatiu", "status.widget.info.plugin_path": "Ruta plugins", - "status.widget.info.service_mode": "Mode de Servei", "status.widget.info.service_user": "Usuari", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Ruta d'emmagatzematge", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Zona horària", diff --git a/ui/src/i18n/cs.json b/ui/src/i18n/cs.json index 21e95b6b7..5f005d50c 100644 --- a/ui/src/i18n/cs.json +++ b/ui/src/i18n/cs.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Příslušenství", "menu.label_plugins": "Pluginy", "menu.label_settings": "Nastavení", - "menu.label_settings_advanced": "Pokročilá nastavení UI", "menu.label_status": "Stav", "menu.linux.label_logs": "Protokoly", "menu.linux.label_restart_server": "Restart serveru", @@ -528,7 +527,6 @@ "status.widget.info": "Systémové informace", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Cesta ke konfiguraci", - "status.widget.info.disabled": "Zakázáno", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Tento systém nepodporuje novější verze Node.js. Pro jejich instalaci a používání v budoucnu budete muset aktualizovat svůj operační systém na novější verzi.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Cesta k Node.js", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Cesta k pluginu", - "status.widget.info.service_mode": "Servisní režim", "status.widget.info.service_user": "Uživatel", - "status.widget.info.servicemode_message": "Samostatný režim již není doporučen. Nastavení Homebridge a Homebridge UI pomocí hb-service nabízí stejné výhody jako samostatný režim, ale je mnohem jednodušší na konfiguraci a údržbu.", - "status.widget.info.servicemode_title": "Servisní mód", "status.widget.info.storage_path": "Cesta k programu", "status.widget.info.synology_package": "Synology Balíček", "status.widget.info.timezone": "Časová zóna", diff --git a/ui/src/i18n/de.json b/ui/src/i18n/de.json index e130ab965..b319e0ad9 100644 --- a/ui/src/i18n/de.json +++ b/ui/src/i18n/de.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Geräte", "menu.label_plugins": "Plugins", "menu.label_settings": "Einstellungen", - "menu.label_settings_advanced": "UI Erweiterte Einstellungen", "menu.label_status": "Status", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Server neustarten", @@ -528,7 +527,6 @@ "status.widget.info": "System Informationen", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Konfigurationspfad", - "status.widget.info.disabled": "Deaktiviert", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Diese Meldung zeigt an, dass Ihr Betriebssystem keine neueren Versionen von Node.js unterstützt. Um dieses Problem zu beheben und in Zukunft aktualisierte Versionen von Node.js installieren zu können, müssen Sie Ihr Betriebssystem auf eine neuere Version aktualisieren.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Pfad", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Pluginpfad", - "status.widget.info.service_mode": "Service-Modus", "status.widget.info.service_user": "Benutzer", - "status.widget.info.servicemode_message": "Der Standalone-Modus wird nicht mehr empfohlen. Die Einrichtung von Homebridge und Homebridge UI mit hb-service bietet dieselben Vorteile wie der Standalone-Modus, ist aber viel einfacher einzurichten und zu warten.", - "status.widget.info.servicemode_title": "Service-Modus", "status.widget.info.storage_path": "Speicherpfad", "status.widget.info.synology_package": "Synology-Paket", "status.widget.info.timezone": "Zeitzone", diff --git a/ui/src/i18n/en.json b/ui/src/i18n/en.json index a4bc46b32..ceb4f7034 100644 --- a/ui/src/i18n/en.json +++ b/ui/src/i18n/en.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Accessories", "menu.label_plugins": "Plugins", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Status", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Restart OS", @@ -528,7 +527,6 @@ "status.widget.info": "System Information", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config Path", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin Path", - "status.widget.info.service_mode": "Service Mode", "status.widget.info.service_user": "User", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Storage Path", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Time Zone", diff --git a/ui/src/i18n/es.json b/ui/src/i18n/es.json index 545a8bcff..74155b898 100644 --- a/ui/src/i18n/es.json +++ b/ui/src/i18n/es.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Accesorios", "menu.label_plugins": "Plugins", "menu.label_settings": "Configuración", - "menu.label_settings_advanced": "Ajustes Avanzados de la Interfaz", "menu.label_status": "Estado", "menu.linux.label_logs": "Registros", "menu.linux.label_restart_server": "Reiniciar Servidor", @@ -528,7 +527,6 @@ "status.widget.info": "Información del Sistema", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Ruta de Configuración", - "status.widget.info.disabled": "No", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Este mensaje indica que tu sistema operativo no es compatible con versiones más nuevas de Node.js. Para solucionar esto y poder instalar actualizaciones futuras de Node.js, deberás actualizar tu sistema operativo a una versión más reciente.", "status.widget.info.glibc_title": "Actualización del SO", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Ruta de Node.js", "status.widget.info.os": "Sistema Operativo", "status.widget.info.plugin_path": "Ruta de Plugins", - "status.widget.info.service_mode": "Modo de Servicio", "status.widget.info.service_user": "Usuario", - "status.widget.info.servicemode_message": "El modo independiente ya no se recomienda. Configurar Homebridge y Homebridge UI con hb-service ofrece las mismas ventajas que el modo independiente, pero es mucho más fácil de instalar y mantener.", - "status.widget.info.servicemode_title": "Modo de Servicio", "status.widget.info.storage_path": "Ruta de Almacenamiento", "status.widget.info.synology_package": "Paquete de Synology", "status.widget.info.timezone": "Zona Horaria", diff --git a/ui/src/i18n/fi.json b/ui/src/i18n/fi.json index 62af8e471..787bcf942 100644 --- a/ui/src/i18n/fi.json +++ b/ui/src/i18n/fi.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Laitteet", "menu.label_plugins": "Laajennukset", "menu.label_settings": "Asetukset", - "menu.label_settings_advanced": "UI kehittyneet asetukset", "menu.label_status": "Tila", "menu.linux.label_logs": "Lokitiedot", "menu.linux.label_restart_server": "Uudellenkäynnistä järjestelmä", @@ -528,7 +527,6 @@ "status.widget.info": "Tietoja järjestelmästä", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "asetusten Polku", - "status.widget.info.disabled": "Poistettu käytöstä", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Nykyinen käyttöjärjestelmäsi versio ei tue Node.js:n uudempia versioita. Jotta voit ratkaista tämän ja pystyä asentamaan päivitetyt versiot Node.js:stä tulevaisuudessa, sinun on päivitettävä käyttöjärjestelmäsi uudempaan versioon.", "status.widget.info.glibc_title": "Käyttöjärjestelmän Päivitys", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js polku", "status.widget.info.os": "Käyttöjärjestelmä", "status.widget.info.plugin_path": "Laajennusten polku", - "status.widget.info.service_mode": "Palvelun tila", "status.widget.info.service_user": "Käyttäjä", - "status.widget.info.servicemode_message": "Itsenäistä tilaa ei enää suositella. Homebridgen ja Homebridge-UI:n määrittäminen hb-palvelun kanssa tarjoaa samat edut kuin itsenäisessä tilassa, mutta se on paljon helpompi asentaa ja ylläpitää.", - "status.widget.info.servicemode_title": "Palvelun tila", "status.widget.info.storage_path": "Tallennuskansio", "status.widget.info.synology_package": "Synology ohjelmisto", "status.widget.info.timezone": "Aikavyöhyke", diff --git a/ui/src/i18n/fr.json b/ui/src/i18n/fr.json index 3a4b499fb..9baf88c19 100644 --- a/ui/src/i18n/fr.json +++ b/ui/src/i18n/fr.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Accessoires", "menu.label_plugins": "Plugins", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Statut", "menu.linux.label_logs": "Journaux", "menu.linux.label_restart_server": "Redémarrer le Serveur", @@ -528,7 +527,6 @@ "status.widget.info": "Informations Système", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Répertoire de la Config", - "status.widget.info.disabled": "Désactivé", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Ce message indique que votre système d'exploitation ne supporte pas les versions récentes de Node.js. Pour résoudre cela et pouvoir installer des versions plus récentes de Node.js dans le futur, vous devrez mettre à jour votre système d'exploitation pour une versions plus récente.", "status.widget.info.glibc_title": "Mise à jour de l'OS", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Répertoire de Node.js", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Répertoire des plugins", - "status.widget.info.service_mode": "Exécuter en tant que Service", "status.widget.info.service_user": "Utilisateur", - "status.widget.info.servicemode_message": "Le mode Standalone n'est plus recommandé. La configuration de Homebridge et de Homebridge UI avec hb-service présente les mêmes avantages que le mode Standalone mais est beaucoup plus facile à mettre en place et à maintenir.", - "status.widget.info.servicemode_title": "Mode de service", "status.widget.info.storage_path": "Répertoire de stockage", "status.widget.info.synology_package": "Paquet Synology", "status.widget.info.timezone": "Fuseau Horaire", diff --git a/ui/src/i18n/he.json b/ui/src/i18n/he.json index df650eb64..25df9a1bd 100644 --- a/ui/src/i18n/he.json +++ b/ui/src/i18n/he.json @@ -197,7 +197,6 @@ "menu.label_accessories": "אביזרים", "menu.label_plugins": "תוספים", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "סטאטוס", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "אתחל מחדש שרת", @@ -528,7 +527,6 @@ "status.widget.info": "מידע מערכת", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "שביל קונפיגורציה", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "מערכת הפעלה", "status.widget.info.plugin_path": "נתיב לתוסף", - "status.widget.info.service_mode": "מצב שירות", "status.widget.info.service_user": "משתמש", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "שביל אחסון", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "אזור זמן", diff --git a/ui/src/i18n/hu.json b/ui/src/i18n/hu.json index aea7587eb..311d2aceb 100644 --- a/ui/src/i18n/hu.json +++ b/ui/src/i18n/hu.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Kiegészítők", "menu.label_plugins": "Pluginek", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Státusz", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Szerver újraindítása", @@ -528,7 +527,6 @@ "status.widget.info": "System Information", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config Path", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin Path", - "status.widget.info.service_mode": "Service Mode", "status.widget.info.service_user": "User", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Storage Path", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Time Zone", diff --git a/ui/src/i18n/id.json b/ui/src/i18n/id.json index 97bce998c..cf1dfa69e 100644 --- a/ui/src/i18n/id.json +++ b/ui/src/i18n/id.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Aksesoris", "menu.label_plugins": "Plugin", "menu.label_settings": "Pengaturan", - "menu.label_settings_advanced": "Pengaturan Lanjutan UI", "menu.label_status": "Status", "menu.linux.label_logs": "Log", "menu.linux.label_restart_server": "Memulai Kembali Server", @@ -528,7 +527,6 @@ "status.widget.info": "Informasi Sistem", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Path Konfigurasi", - "status.widget.info.disabled": "Dinonaktifkan", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Pesan ini menunjukkan bahwa sistem operasi Anda tidak mendukung versi yang lebih baru dari Node.js.Untuk menyelesaikan ini dan dapat menginstal versi yang diperbarui dari Node.js di masa mendatang, Anda perlu memperbarui sistem operasi Anda ke versi yang lebih baru.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Jalur Node.js", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Path Plugin", - "status.widget.info.service_mode": "Mode Servis", "status.widget.info.service_user": "Pengguna", - "status.widget.info.servicemode_message": "Mode mandiri tidak lagi direkomendasikan.Menyiapkan Homebridge dan Homebridge UI dengan HB-Service memiliki manfaat yang sama dari mode mandiri tetapi jauh lebih mudah untuk diatur dan dirawat.", - "status.widget.info.servicemode_title": "Mode Service", "status.widget.info.storage_path": "Path Penyimpanan", "status.widget.info.synology_package": "Paket Synology", "status.widget.info.timezone": "Zona Waktu", diff --git a/ui/src/i18n/it.json b/ui/src/i18n/it.json index 154c2709c..15e882c6d 100644 --- a/ui/src/i18n/it.json +++ b/ui/src/i18n/it.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Accessori", "menu.label_plugins": "Plugin", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Stato", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Riavvia sistema", @@ -528,7 +527,6 @@ "status.widget.info": "Informazioni di sistema", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Percorso configurazione", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "Sistema operativo", "status.widget.info.plugin_path": "Percorso plugin", - "status.widget.info.service_mode": "Modalità servizio", "status.widget.info.service_user": "Utente", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Percorso salvataggio", "status.widget.info.synology_package": "Pacchetto Synology", "status.widget.info.timezone": "Fuso orario", diff --git a/ui/src/i18n/ja.json b/ui/src/i18n/ja.json index ba3470e1f..e5056350d 100644 --- a/ui/src/i18n/ja.json +++ b/ui/src/i18n/ja.json @@ -197,7 +197,6 @@ "menu.label_accessories": "アクセサリ", "menu.label_plugins": "プラグイン", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "状態", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "サーバーを再起動", @@ -528,7 +527,6 @@ "status.widget.info": "システム情報", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "コンフィグの場所", - "status.widget.info.disabled": "無効", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "このメッセージは、お使いのオペレーティングシステムがNode.jsの新しいバージョンをサポートしていないことを示しています。この問題を解決し、将来Node.jsの更新バージョンをインストールできるようにするには、オペレーティングシステムをより新しいバージョンに更新する必要があります。", "status.widget.info.glibc_title": "OSアップデート", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "プラグインの場所", - "status.widget.info.service_mode": "サービスモード", "status.widget.info.service_user": "ユーザ", - "status.widget.info.servicemode_message": "スタンドアロンモードは推奨されません。hb-serviceでHomebridgeとHomebridge UIをセットアップすると、スタンドアロンモードと同じ利点がありますが、セットアップとメンテナンスがより簡単になります。", - "status.widget.info.servicemode_title": "サービスモード", "status.widget.info.storage_path": "ストレージの場所", "status.widget.info.synology_package": "Synologyパッケージ", "status.widget.info.timezone": "タイムゾーン", diff --git a/ui/src/i18n/ko.json b/ui/src/i18n/ko.json index 3d815e345..686e81ccf 100644 --- a/ui/src/i18n/ko.json +++ b/ui/src/i18n/ko.json @@ -197,7 +197,6 @@ "menu.label_accessories": "액세서리", "menu.label_plugins": "플러그인", "menu.label_settings": "설정", - "menu.label_settings_advanced": "고급 UI 설정", "menu.label_status": "상태", "menu.linux.label_logs": "로그", "menu.linux.label_restart_server": "서버 재시작", @@ -528,7 +527,6 @@ "status.widget.info": "시스템 정보", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config 경로", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "이 메시지는 사용 중인 운영체제가 새로운 버전의 Node.js를 지원하지 않는다는 것을 나타냅니다. 이 문제를 해결하고 향후 Node.js의 최신 버전을 설치하기 위해서는 운영체제를 더 최신 버전으로 업데이트해야 합니다.", "status.widget.info.glibc_title": "OS 업데이트", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js 경로", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "플러그인 경로", - "status.widget.info.service_mode": "서비스 모드", "status.widget.info.service_user": "사용자", - "status.widget.info.servicemode_message": "독립 실행 모드는 더 이상 권장되지 않습니다. hb-service를 통해 Homebridge와 Homebridge UI를 설정하는 것이 독립 실행 모드와 동일한 이점을 제공하면서도 설정과 유지 관리가 훨씬 더 쉽습니다.", - "status.widget.info.servicemode_title": "서비스 모드", "status.widget.info.storage_path": "저장소 경로", "status.widget.info.synology_package": "Synology 패키지", "status.widget.info.timezone": "시간대", diff --git a/ui/src/i18n/mk.json b/ui/src/i18n/mk.json index 419a284c8..348996380 100644 --- a/ui/src/i18n/mk.json +++ b/ui/src/i18n/mk.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Уреди", "menu.label_plugins": "Плагини", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Статус", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Рестартирај сервер", @@ -528,7 +527,6 @@ "status.widget.info": "Информации за системот", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Патека за конфигурацијата", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Патека за плагинот", - "status.widget.info.service_mode": "Мод на сервисот", "status.widget.info.service_user": "Корисник", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Патека за storage", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Временска зона", diff --git a/ui/src/i18n/nl.json b/ui/src/i18n/nl.json index 1b0ec2e3c..bcc9c6885 100644 --- a/ui/src/i18n/nl.json +++ b/ui/src/i18n/nl.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Accessoires", "menu.label_plugins": "Plugins", "menu.label_settings": "Instellingen", - "menu.label_settings_advanced": "UI Geavanceerde Instellingen", "menu.label_status": "Status", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Herstart Server", @@ -528,7 +527,6 @@ "status.widget.info": "Systeem Informatie", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config Pad", - "status.widget.info.disabled": "Inactief", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Deze melding geeft aan dat Uw operating systeem nieuwere versies van Node.js ondersteunt. Om dit op te lossen en om nieuwere versies van Node.js in de toekomst te kunnen installeren, moet U het operating systeem bijwerken met een recentere versie.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Pad", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin Pad", - "status.widget.info.service_mode": "Service Modus", "status.widget.info.service_user": "Gebruiker", - "status.widget.info.servicemode_message": "Standalone modus wordt niet langer aanbevolen. Installatie van Homebridge en Homebridge UI met hb-service heeft dezelfde voordelen als standalone modus maar is veel eenvoudiger in te stellen en te onderhouden.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Opslag Pad", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Tijdzone", diff --git a/ui/src/i18n/no.json b/ui/src/i18n/no.json index 6a75d5c4b..2ecfb1303 100644 --- a/ui/src/i18n/no.json +++ b/ui/src/i18n/no.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Tilbehør", "menu.label_plugins": "Plugins", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Status", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Restart serveren", @@ -528,7 +527,6 @@ "status.widget.info": "System Information", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config Path", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin Path", - "status.widget.info.service_mode": "Service Mode", "status.widget.info.service_user": "User", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Storage Path", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Time Zone", diff --git a/ui/src/i18n/pl.json b/ui/src/i18n/pl.json index 2f8f9a1bf..ab6ad1364 100644 --- a/ui/src/i18n/pl.json +++ b/ui/src/i18n/pl.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Akcesoria", "menu.label_plugins": "Wtyczki", "menu.label_settings": "Ustawienia", - "menu.label_settings_advanced": "Zaawansowane", "menu.label_status": "Status", "menu.linux.label_logs": "Log", "menu.linux.label_restart_server": "Zrestartuj serwer", @@ -528,7 +527,6 @@ "status.widget.info": "Informacje o systemie", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Ścieżka konfiguracji", - "status.widget.info.disabled": "Wyłączony", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Ten komunikat wskazuje, że twój system operacyjny nie obsługuje nowszych wersji Node.js. Aby rozwiązać ten problem i móc zainstalować zaktualizowane wersje Node.js w przyszłości, trzeba zaktualizować system do nowszej wersji.", "status.widget.info.glibc_title": "Aktualizacja OS", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Ścieżka Node.js", "status.widget.info.os": "System", "status.widget.info.plugin_path": "Ścieżka wtyczki", - "status.widget.info.service_mode": "Tryb serwisowy", "status.widget.info.service_user": "Użytkownik", - "status.widget.info.servicemode_message": "Tryb autonomiczny nie jest już zalecany. Konfiguracja Homebridge i Homebridge UI z hb-service ma te same zalety co tryb autonomiczny, ale jest znacznie łatwiejsza w konfiguracji i utrzymaniu.", - "status.widget.info.servicemode_title": "Tryb serwisowy", "status.widget.info.storage_path": "Ścieżka zapisu", "status.widget.info.synology_package": "Paczka Synology", "status.widget.info.timezone": "Strefa czasowa", diff --git a/ui/src/i18n/pt-BR.json b/ui/src/i18n/pt-BR.json index 02b7c7784..02c3a3d37 100644 --- a/ui/src/i18n/pt-BR.json +++ b/ui/src/i18n/pt-BR.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Acessórios", "menu.label_plugins": "Plugins", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Status", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Reiniciar o Servidor", @@ -528,7 +527,6 @@ "status.widget.info": "Informações do Sistema", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Local das Configurações", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "Sistema Operacional", "status.widget.info.plugin_path": "Local do Plugin", - "status.widget.info.service_mode": "Rodando como Serviço", "status.widget.info.service_user": "Usuário", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Local do Armazenamento", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Fuso Horário", diff --git a/ui/src/i18n/pt.json b/ui/src/i18n/pt.json index 4c2122d72..1cf750c73 100644 --- a/ui/src/i18n/pt.json +++ b/ui/src/i18n/pt.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Acessórios", "menu.label_plugins": "Plugins", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Estado", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Reiniciar o Servidor", @@ -528,7 +527,6 @@ "status.widget.info": "Informações do Sistema", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Caminho das Configurações", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "Sistema Operativo", "status.widget.info.plugin_path": "Caminho do Plugin", - "status.widget.info.service_mode": "Executado como Serviço", "status.widget.info.service_user": "Utilizador", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Caminho do Armazenamento", "status.widget.info.synology_package": "Pacote Synology", "status.widget.info.timezone": "Fuso Horário", diff --git a/ui/src/i18n/ru.json b/ui/src/i18n/ru.json index ae46eb9e9..04c3641bd 100644 --- a/ui/src/i18n/ru.json +++ b/ui/src/i18n/ru.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Аксессуары", "menu.label_plugins": "Плагины", "menu.label_settings": "Настройки", - "menu.label_settings_advanced": "Расширенные настройки UI", "menu.label_status": "Статус", "menu.linux.label_logs": "Журналы", "menu.linux.label_restart_server": "Перезагрузить ОС", @@ -528,7 +527,6 @@ "status.widget.info": "Информация о системе", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Путь к конфигурации", - "status.widget.info.disabled": "Отключено", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Это сообщение означает, что ваша операционная система не поддерживает более новые версии Node.js. Чтобы решить эту проблему и иметь возможность устанавливать обновлённые версии Node.js в будущем, обновите операционную систему до более новой версии.", "status.widget.info.glibc_title": "Обновление ОС", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Путь к Node.js", "status.widget.info.os": "Операционная система", "status.widget.info.plugin_path": "Путь к плагинам", - "status.widget.info.service_mode": "Режим сервиса", "status.widget.info.service_user": "Пользователь", - "status.widget.info.servicemode_message": "Режим Standalone больше не рекомендуется. Настройка Homebridge и Homebridge UI с помощью hb-service имеет те же преимущества, но проще в установке и сопровождении.", - "status.widget.info.servicemode_title": "Режим сервиса", "status.widget.info.storage_path": "Путь к хранилищу", "status.widget.info.synology_package": "Пакет Synology", "status.widget.info.timezone": "Часовой пояс", diff --git a/ui/src/i18n/sl.json b/ui/src/i18n/sl.json index dfcd88e65..1513ebf69 100644 --- a/ui/src/i18n/sl.json +++ b/ui/src/i18n/sl.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Dodatki", "menu.label_plugins": "Vtičniki", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Stanje", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Znova zaženite strežnik", @@ -528,7 +527,6 @@ "status.widget.info": "Sistemske informacije", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Konfiguriraj pot", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Pot vtičnika", - "status.widget.info.service_mode": "Način storitve", "status.widget.info.service_user": "Uporabnik", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Shranjevalna pot", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Časovni pas", diff --git a/ui/src/i18n/sv.json b/ui/src/i18n/sv.json index 622095e24..4bd51cc24 100644 --- a/ui/src/i18n/sv.json +++ b/ui/src/i18n/sv.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Tillbehör", "menu.label_plugins": "Plugins", "menu.label_settings": "Inställningar", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Status", "menu.linux.label_logs": "Logg", "menu.linux.label_restart_server": "Starta om servern", @@ -528,7 +527,6 @@ "status.widget.info": "Systeminformation", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Konfig sökväg", - "status.widget.info.disabled": "Inaktiverad", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Detta meddelande tyder på att ditt operativsystem inte stödjer nyare versioner av Node.js. För att lösa detta och kunna installera uppdaterade versioner av Node.js i framtiden måste du uppdatera ditt operativsystem till en nyare version.", "status.widget.info.glibc_title": "OS-uppdatering", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js sökväg", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin sökväg", - "status.widget.info.service_mode": "Serviceläge", "status.widget.info.service_user": "Användare", - "status.widget.info.servicemode_message": "Standalone-läge rekommenderas inte längre. Installation av Homebridge och Homebridge UI med hb-service har samma fördelar som standalone-läge, men är mycket lättare att konfigurera och underhålla.", - "status.widget.info.servicemode_title": "Serviceläge", "status.widget.info.storage_path": "Lagring sökväg", "status.widget.info.synology_package": "Synology-paket", "status.widget.info.timezone": "Tidszon", diff --git a/ui/src/i18n/th.json b/ui/src/i18n/th.json index f839fd4ab..bad51fc65 100644 --- a/ui/src/i18n/th.json +++ b/ui/src/i18n/th.json @@ -197,7 +197,6 @@ "menu.label_accessories": "อุปกรณ์เสริม", "menu.label_plugins": "ปลั๊กอิน", "menu.label_settings": "การตั้งค่า", - "menu.label_settings_advanced": "การตั้งค่า UI ขั้นสูง", "menu.label_status": "สถานะ", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "รีสตาร์ทเซิร์ฟเวอร์", @@ -528,7 +527,6 @@ "status.widget.info": "ข้อมูลระบบ", "status.widget.info.arch": "โค้ง", "status.widget.info.config_path": "เส้นทางกำหนดค่า", - "status.widget.info.disabled": "ปิดการใช้", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "ข้อความนี้ระบุว่าระบบปฏิบัติการของคุณไม่รองรับ Node.js เวอร์ชันใหม่กว่า เพื่อแก้ไขปัญหานี้และสามารถติดตั้ง Node.js เวอร์ชันอัปเดตได้ในอนาคต คุณจะต้องอัปเดตระบบปฏิบัติการเป็นเวอร์ชันล่าสุด", "status.widget.info.glibc_title": "อัพเดตระบบปฏิบัติการ", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "พาธของ Node.js", "status.widget.info.os": "ระบบปฏิบัติการ", "status.widget.info.plugin_path": "เส้นทางปลั๊กอิน", - "status.widget.info.service_mode": "โหมดบริการ", "status.widget.info.service_user": "ผู้ใช้", - "status.widget.info.servicemode_message": "ไม่แนะนำให้ใช้โหมดสแตนด์อโลนอีกต่อไป การตั้งค่า Homebridge และ Homebridge UI ด้วย hb-service มีข้อดีเหมือนกับโหมดสแตนด์อโลน แต่การตั้งค่าและบำรุงรักษาได้ง่ายกว่ามาก", - "status.widget.info.servicemode_title": "โหมดบริการ", "status.widget.info.storage_path": "เส้นทางการจัดเก็บ", "status.widget.info.synology_package": "แพ็คเกจ Synology", "status.widget.info.timezone": "เขตเวลา", diff --git a/ui/src/i18n/tr.json b/ui/src/i18n/tr.json index 1c60b01c2..600e12c71 100644 --- a/ui/src/i18n/tr.json +++ b/ui/src/i18n/tr.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Aksesuarlar", "menu.label_plugins": "Eklentiler", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "Durum", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "Sunucuyu Yeniden Başlat", @@ -528,7 +527,6 @@ "status.widget.info": "Sistem Bilgisi", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Yapılandırma Konumu", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "İS", "status.widget.info.plugin_path": "Eklentiler Konumu", - "status.widget.info.service_mode": "Servis Modu", "status.widget.info.service_user": "Kullanıcı", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "Depolama Konumu", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "Saat Dilimi", diff --git a/ui/src/i18n/uk.json b/ui/src/i18n/uk.json index 27e5e2229..93ee5fcc3 100644 --- a/ui/src/i18n/uk.json +++ b/ui/src/i18n/uk.json @@ -197,7 +197,6 @@ "menu.label_accessories": "Аксесуари", "menu.label_plugins": "Плагіни", "menu.label_settings": "Налаштування", - "menu.label_settings_advanced": "Розширені налаштування UI", "menu.label_status": "Статус", "menu.linux.label_logs": "Журнали", "menu.linux.label_restart_server": "Перезавантажити сервер", @@ -528,7 +527,6 @@ "status.widget.info": "Інформація про систему", "status.widget.info.arch": "Арх.", "status.widget.info.config_path": "Файл конфігурації", - "status.widget.info.disabled": "Вимкнено", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "Це повідомлення означає, що Ваша операційна система не підтримує нові версії Node.js. Щоб вирішити цю проблему та мати можливість інсталювати оновлені версії Node.js у майбутньому, Вам потрібно оновити операційну систему до новішої версії.", "status.widget.info.glibc_title": "OS Оновлена", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Шлях Node.js", "status.widget.info.os": "ОС", "status.widget.info.plugin_path": "Директорія плагінів", - "status.widget.info.service_mode": "Сервісний режим", "status.widget.info.service_user": "Користувач", - "status.widget.info.servicemode_message": "Автономний режим більше не рекомендується. Налаштування Homebridge і Homebridge UI за допомогою hb-service має ті самі переваги, що й автономний режим, але його набагато легше налаштовувати та підтримувати.", - "status.widget.info.servicemode_title": "Сервісний режим", "status.widget.info.storage_path": "Директорія зберігання", "status.widget.info.synology_package": "Пакет Synology", "status.widget.info.timezone": "Часовий пояс", diff --git a/ui/src/i18n/zh-CN.json b/ui/src/i18n/zh-CN.json index 14d7b0163..edeec9ab6 100644 --- a/ui/src/i18n/zh-CN.json +++ b/ui/src/i18n/zh-CN.json @@ -197,7 +197,6 @@ "menu.label_accessories": "配件", "menu.label_plugins": "插件", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "状态", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "重启服务器", @@ -528,7 +527,6 @@ "status.widget.info": "系统信息", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config 路径", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "操作系统", "status.widget.info.plugin_path": "插件路径", - "status.widget.info.service_mode": "服务模式", "status.widget.info.service_user": "用户", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "存储路径", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "时区", diff --git a/ui/src/i18n/zh-TW.json b/ui/src/i18n/zh-TW.json index fb6d148e7..9c7f697ab 100644 --- a/ui/src/i18n/zh-TW.json +++ b/ui/src/i18n/zh-TW.json @@ -197,7 +197,6 @@ "menu.label_accessories": "配件", "menu.label_plugins": "Plugins", "menu.label_settings": "Settings", - "menu.label_settings_advanced": "UI Advanced Settings", "menu.label_status": "狀態", "menu.linux.label_logs": "Logs", "menu.linux.label_restart_server": "重新啟動 Homebridge", @@ -528,7 +527,6 @@ "status.widget.info": "系統資訊", "status.widget.info.arch": "Arch.", "status.widget.info.config_path": "Config 路徑", - "status.widget.info.disabled": "Disabled", "status.widget.info.docker": "Docker", "status.widget.info.glibc_message": "This message indicates that your operating system does not support newer versions of Node.js. To resolve this and be able to install updated versions of Node.js in the future, you will need to update your operating system to a more recent version.", "status.widget.info.glibc_title": "OS Update", @@ -545,10 +543,7 @@ "status.widget.info.nodejs_path": "Node.js Path", "status.widget.info.os": "OS", "status.widget.info.plugin_path": "Plugin 路徑", - "status.widget.info.service_mode": "服務模式", "status.widget.info.service_user": "使用者", - "status.widget.info.servicemode_message": "Standalone mode is no longer recommended. Setting up Homebridge and Homebridge UI with hb-service has the same benefits of standalone mode but it is much easier to setup and maintain.", - "status.widget.info.servicemode_title": "Service Mode", "status.widget.info.storage_path": "儲存路徑", "status.widget.info.synology_package": "Synology Package", "status.widget.info.timezone": "時區", From 8feb467bd59bb4bfea60b4333d022dd396b2a206 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Sat, 7 Jun 2025 13:14:27 +0100 Subject: [PATCH 20/22] add support for dark mode switching with custom plugin uis Co-Authored-By: Northern Man <19808920+NorthernMan54@users.noreply.github.com> --- CHANGELOG.md | 1 + .../custom-plugins.component.ts | 4 +- ui/src/app/core/settings.service.ts | 37 ++++++++++++++++++- .../plugin-card/plugin-card.component.ts | 2 +- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6203e05d..502b8a040 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - updates to the `fi.json` language file (#2253) (@l1500s) - update default dashboard layout +- add support for dark mode switching with custom plugin uis (@NorthernMan54) ### Other Changes diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts index fb5eab012..0968bbada 100644 --- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts +++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts @@ -288,6 +288,7 @@ export class CustomPluginsComponent implements OnInit, OnDestroy { // Set body class event.source.postMessage({ action: 'body-class', class: currentTheme }, event.origin) + event.source.postMessage({ action: 'body-class', class: 'modal-content' }, event.origin) if (darkMode) { event.source.postMessage({ action: 'body-class', class: 'dark-mode' }, event.origin) } @@ -312,9 +313,6 @@ export class CustomPluginsComponent implements OnInit, OnDestroy { const customStyles = ` body { height: unset !important; - background-color: ${darkMode ? '#242424' : '#FFFFFF'} !important; - color: ${darkMode ? '#FFFFFF' : '#000000'}; - padding: 5px !important; } ` event.source.postMessage({ action: 'inline-style', style: customStyles }, event.origin) diff --git a/ui/src/app/core/settings.service.ts b/ui/src/app/core/settings.service.ts index 568b837b5..162934328 100644 --- a/ui/src/app/core/settings.service.ts +++ b/ui/src/app/core/settings.service.ts @@ -169,7 +169,7 @@ export class SettingsService { // Save the new property to the config file firstValueFrom(this.$api.put('/config-editor/ui', { key: 'theme', value: theme })) - .catch(error => console.error(error)) + .catch(error => console.error('Error saving setTheme:', error)) } // Grab the body element @@ -192,6 +192,41 @@ export class SettingsService { bodySelector.classList.remove('dark-mode') } } + + // Update same-origin iframes + const iframes = window.document.querySelectorAll('iframe') + iframes.forEach((iframe, index) => { + try { + const iframeDoc = iframe.contentDocument + if (iframeDoc) { + const iframeBody = iframeDoc.body + + iframeBody.classList.remove(`config-ui-x-${this.theme}`) + iframeBody.classList.remove(`config-ui-x-dark-mode-${this.theme}`) + if (this.actualLightingMode === 'dark') { + iframeBody.classList.add(`config-ui-x-dark-mode-${this.theme}`) + + if (!iframeBody.classList.contains('dark-mode')) { + iframeBody.classList.add('dark-mode') + } + } else { + iframeBody.classList.add(`config-ui-x-${this.theme}`) + + if (iframeBody.classList.contains('dark-mode')) { + iframeBody.classList.remove('dark-mode') + } + } + + // Notify iframe Angular app + iframe.contentWindow.postMessage( + { type: 'theme-update', isDark: this.actualLightingMode === 'dark', theme }, + window.location.origin, + ) + } + } catch (e) { + console.warn(`Iframe ${index}: Access denied (cross-origin?)`, { error: e, src: iframe.src }) + } + }) } setMenuMode(value: 'default' | 'freeze') { diff --git a/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts b/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts index 19b170dd7..cb39eed8c 100644 --- a/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts +++ b/ui/src/app/modules/plugins/plugin-card/plugin-card.component.ts @@ -78,7 +78,7 @@ export class PluginCardComponent implements OnInit { this.setChildBridges = childBridges - const homebridgeVersion = this.$settings.env.homebridgeVersion.split('.')[0] + const homebridgeVersion = this.$settings.env.homebridgeVersion?.split('.')[0] const hbEngines = this.plugin.engines?.homebridge?.split('||').map((x: string) => x.trim()) || [] this.hb2Status = homebridgeVersion === '2' ? 'hide' : hbEngines.some((x: string) => (x.startsWith('^2') || x.startsWith('>=2'))) ? 'supported' : this.hb2Status } From 9f7fe93d186ce05e183397b046c1200467ad3b00 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:18:53 +0100 Subject: [PATCH 21/22] Initial support for NodeJS 24 in preparation for LTS in Fall of 2025 (#2451) Co-Authored-By: Northern Man <19808920+NorthernMan54@users.noreply.github.com> --- .github/workflows/beta-release.yml | 2 +- .github/workflows/validate.yml | 6 +++--- CHANGELOG.md | 1 + package-lock.json | 2 +- package.json | 2 +- src/bin/hb-service.ts | 6 +++--- src/modules/status/status.service.ts | 11 +++++++++++ 7 files changed, 21 insertions(+), 9 deletions(-) diff --git a/.github/workflows/beta-release.yml b/.github/workflows/beta-release.yml index e4f04eca3..6d84cdb50 100644 --- a/.github/workflows/beta-release.yml +++ b/.github/workflows/beta-release.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] + os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022] uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 1ea3e25a6..f8db46546 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] + os: [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022] uses: homebridge/.github/.github/workflows/nodejs-build-and-test.yml@latest with: @@ -38,8 +38,8 @@ jobs: fail-fast: false matrix: os: - [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022, windows-2019] - node-version: [20.x, 22.x] + [ubuntu-latest, ubuntu-24.04, ubuntu-22.04, macos-latest, macos-15, macos-14, macos-13, windows-latest, windows-2022] + node-version: [20.x, 22.x, 24.x] runs-on: ${{ matrix.os }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 502b8a040..45d9978be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - bump the default node version from 20 to 22 - make terminal enabled by default on new macOS hb-service installs - set service mode as default, remove standalone +- Initial support for NodeJS 24 in preparation for LTS in Fall of 2025 (#2451) (@NorthernMan54) ### Homebridge Dependencies diff --git a/package-lock.json b/package-lock.json index afe446660..5b8df8ba7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,7 +91,7 @@ }, "engines": { "homebridge": "^1.8.0 || ^2.0.0-beta.0", - "node": "^18 || ^20 || ^22" + "node": "^20 || ^22 || ^24" } }, "node_modules/@ampproject/remapping": { diff --git a/package.json b/package.json index b10b5ee8e..0b7932006 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "hb-service": "dist/bin/hb-service.js" }, "engines": { - "node": "^18 || ^20 || ^22", + "node": "^20 || ^22 || ^24", "homebridge": "^1.8.0 || ^2.0.0-beta.0" }, "scripts": { diff --git a/src/bin/hb-service.ts b/src/bin/hb-service.ts index b1dd23352..796d4e98f 100644 --- a/src/bin/hb-service.ts +++ b/src/bin/hb-service.ts @@ -1182,9 +1182,9 @@ export class HomebridgeServiceHelper { if (requestedVersion) { const wantedVersion = versionList.find(x => x.version.startsWith(`v${requestedVersion}`)) if (wantedVersion) { - // Check the requested version is greater than v16.18.2 - if (!gte(wantedVersion.version, '16.18.2')) { - this.logger('Refusing to install Node.js version lower than v16.18.2.', 'fail') + // Check the requested version is greater than v20.18.0 + if (!gte(wantedVersion.version, '20.18.0')) { + this.logger('Refusing to install Node.js version lower than v20.18.0.', 'fail') return { update: false } } this.logger(`Installing Node.js ${wantedVersion.version} over ${process.version}...`, 'info') diff --git a/src/modules/status/status.service.ts b/src/modules/status/status.service.ts index 738566385..cb41f220c 100644 --- a/src/modules/status/status.service.ts +++ b/src/modules/status/status.service.ts @@ -446,6 +446,7 @@ export class StatusService { // Get the newest v18 and v20 in the list const latest18 = versionList.filter((x: { version: string }) => x.version.startsWith('v18'))[0] const latest22 = versionList.filter((x: { version: string }) => x.version.startsWith('v22'))[0] + const latest24 = versionList.filter((x: { version: string }) => x.version.startsWith('v24'))[0] let updateAvailable = false let latestVersion = process.version @@ -458,6 +459,7 @@ export class StatusService { * 18 2.28 * 20 2.31 * 22 2.31 (assumption - the code below assumes this) + * 24 ???? */ // Behaviour depends on the installed version of node @@ -512,6 +514,15 @@ export class StatusService { } break } + case 'v24': { + // Currently using v24 + // Check if there is a new minor/patch version available + if (gt(latest24.version, process.version)) { + updateAvailable = true + latestVersion = latest24.version + } + break + } default: { // Using an unsupported version of node showNodeUnsupportedWarning = true From 8a04ab0add9e3c193bb9d3092e64c1e13f7ed3b7 Mon Sep 17 00:00:00 2001 From: Ben <43026681+bwp91@users.noreply.github.com> Date: Mon, 16 Jun 2025 22:28:27 +0100 Subject: [PATCH 22/22] update `fastify` and `nestjs` dependencies --- CHANGELOG.md | 5 +- package-lock.json | 1321 +++++++++-------- package.json | 34 +- src/index.ts | 4 +- .../accessories/accessories.controller.ts | 4 +- .../config-editor/config-editor.controller.ts | 2 +- .../hb-service/hb-service.controller.ts | 4 +- src/modules/users/users.controller.ts | 14 +- 8 files changed, 701 insertions(+), 687 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45d9978be..c56541f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,11 +25,12 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file. - make terminal enabled by default on new macOS hb-service installs - set service mode as default, remove standalone - Initial support for NodeJS 24 in preparation for LTS in Fall of 2025 (#2451) (@NorthernMan54) +- update `fastify` and `nestjs` dependencies ### Homebridge Dependencies -- `@homebridge/hap-client` @ `v2.2.0` -- `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14` +- `@homebridge/hap-client` @ `v3.0.0` +- `@homebridge/node-pty-prebuilt-multiarch` @ `v0.13.0-beta` - `@homebridge/plugin-ui-utils` @ `v2.1.0` ## v4.77.0 (Unreleased) diff --git a/package-lock.json b/package-lock.json index 5b8df8ba7..576170ffc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,27 +19,27 @@ ], "license": "MIT", "dependencies": { - "@fastify/helmet": "11.1.1", - "@fastify/multipart": "8.3.1", - "@fastify/static": "7.0.4", + "@fastify/helmet": "13.0.1", + "@fastify/multipart": "9.0.3", + "@fastify/static": "8.2.0", "@homebridge/hap-client": "3.1.0", - "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", - "@nestjs/axios": "3.1.3", - "@nestjs/common": "10.4.18", - "@nestjs/core": "10.4.18", - "@nestjs/jwt": "10.2.0", - "@nestjs/passport": "10.0.3", - "@nestjs/platform-fastify": "10.4.18", - "@nestjs/platform-socket.io": "10.4.18", - "@nestjs/swagger": "8.1.1", - "@nestjs/websockets": "10.4.18", + "@homebridge/node-pty-prebuilt-multiarch": "0.13.0-beta.4", + "@nestjs/axios": "4.0.0", + "@nestjs/common": "11.1.3", + "@nestjs/core": "11.1.3", + "@nestjs/jwt": "11.0.0", + "@nestjs/passport": "11.0.5", + "@nestjs/platform-fastify": "11.1.3", + "@nestjs/platform-socket.io": "11.1.3", + "@nestjs/swagger": "11.2.0", + "@nestjs/websockets": "11.1.3", "axios": "1.10.0", "bash-color": "0.0.4", "class-transformer": "0.5.1", "class-validator": "0.14.2", - "commander": "13.1.0", + "commander": "14.0.0", "dayjs": "1.11.13", - "fastify": "4.29.1", + "fastify": "5.4.0", "fs-extra": "11.3.0", "jsonwebtoken": "9.0.2", "lodash": "4.17.21", @@ -65,7 +65,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^4.15.0", - "@nestjs/testing": "^10.4.18", + "@nestjs/testing": "^11.1.3", "@prettier/plugin-xml": "^3.4.1", "@types/fs-extra": "^11.0.4", "@types/lodash": "^4.17.18", @@ -1087,23 +1087,40 @@ } }, "node_modules/@fastify/accept-negotiator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-1.1.0.tgz", - "integrity": "sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==", - "license": "MIT", - "engines": { - "node": ">=14" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@fastify/accept-negotiator/-/accept-negotiator-2.0.1.tgz", + "integrity": "sha512-/c/TW2bO/v9JeEgoD/g1G5GxGeCF1Hafdf79WPmUlgYiBXummY0oX3VVq4yFkKKVBKDNlaDUYoab7g38RpPqCQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" }, "node_modules/@fastify/ajv-compiler": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-3.6.0.tgz", - "integrity": "sha512-LwdXQJjmMD+GwLOkP7TVC68qa+pSSogeWWmznRJ/coyTcfe9qA05AHFSe1eZFwK6q+xVRpChnvFUkf1iYaSZsQ==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.2.tgz", + "integrity": "sha512-Rkiu/8wIjpsf46Rr+Fitd3HRP+VsxUFDDeag0hs9L0ksfnwx2g7SPQQTFL0E8Qv+rfXzQOxBJnjUB9ITUDjfWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "ajv": "^8.11.0", - "ajv-formats": "^2.1.1", - "fast-uri": "^2.0.0" + "ajv": "^8.12.0", + "ajv-formats": "^3.0.1", + "fast-uri": "^3.0.0" } }, "node_modules/@fastify/ajv-compiler/node_modules/ajv": { @@ -1122,22 +1139,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@fastify/ajv-compiler/node_modules/ajv/node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/@fastify/ajv-compiler/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -1151,13 +1152,23 @@ "license": "MIT" }, "node_modules/@fastify/cors": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-9.0.1.tgz", - "integrity": "sha512-YY9Ho3ovI+QHIL2hW+9X4XqQjXLjJqsU+sMV/xFsxZkE8p3GNnYVFpoOxF7SsP5ZL76gwvbo3V9L+FIekBGU4Q==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@fastify/cors/-/cors-11.0.1.tgz", + "integrity": "sha512-dmZaE7M1f4SM8ZZuk5RhSsDJ+ezTgI7v3HHRj8Ow9CneczsPLZV6+2j2uwdaSLn8zhTv6QV0F4ZRcqdalGx1pQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "fastify-plugin": "^4.0.0", - "mnemonist": "0.39.6" + "fastify-plugin": "^5.0.0", + "toad-cache": "^3.7.0" } }, "node_modules/@fastify/deepmerge": { @@ -1193,106 +1204,189 @@ "license": "MIT" }, "node_modules/@fastify/fast-json-stringify-compiler": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.3.0.tgz", - "integrity": "sha512-aZAXGYo6m22Fk1zZzEUKBvut/CIIQe/BapEORnxiD5Qr0kPHqqI69NtEMCme74h+at72sPhbkb4ZrLd1W3KRLA==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz", + "integrity": "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "fast-json-stringify": "^5.7.0" + "fast-json-stringify": "^6.0.0" } }, "node_modules/@fastify/formbody": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-7.4.0.tgz", - "integrity": "sha512-H3C6h1GN56/SMrZS8N2vCT2cZr7mIHzBHzOBa5OPpjfB/D6FzP9mMpE02ZzrFX0ANeh0BAJdoXKOF2e7IbV+Og==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@fastify/formbody/-/formbody-8.0.2.tgz", + "integrity": "sha512-84v5J2KrkXzjgBpYnaNRPqwgMsmY7ZDjuj0YVuMR3NXCJRCgKEZy/taSP1wUYGn0onfxJpLyRGDLa+NMaDJtnA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "fast-querystring": "^1.0.0", - "fastify-plugin": "^4.0.0" + "fast-querystring": "^1.1.2", + "fastify-plugin": "^5.0.0" } }, + "node_modules/@fastify/forwarded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.0.tgz", + "integrity": "sha512-kJExsp4JCms7ipzg7SJ3y8DwmePaELHxKYtg+tZow+k0znUTf3cb+npgyqm8+ATZOdmfgfydIebPDWM172wfyA==", + "license": "MIT" + }, "node_modules/@fastify/helmet": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/@fastify/helmet/-/helmet-11.1.1.tgz", - "integrity": "sha512-pjJxjk6SLEimITWadtYIXt6wBMfFC1I6OQyH/jYVCqSAn36sgAIFjeNiibHtifjCd+e25442pObis3Rjtame6A==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/@fastify/helmet/-/helmet-13.0.1.tgz", + "integrity": "sha512-i+ifqazG3d0HwHL3zuZdg6B/WPc9Ee6kVfGpwGho4nxm0UaK1htss0zq+1rVhOoAorZlCgTZ3/i4S58hUGkkoA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "fastify-plugin": "^4.2.1", - "helmet": "^7.0.0" + "fastify-plugin": "^5.0.0", + "helmet": "^8.0.0" } }, "node_modules/@fastify/merge-json-schemas": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.1.1.tgz", - "integrity": "sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", + "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" + "dequal": "^2.0.3" } }, "node_modules/@fastify/middie": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/@fastify/middie/-/middie-8.3.3.tgz", - "integrity": "sha512-+WHavMQr9CNTZoy2cjoDxoWp76kZ3JKjAtZj5sXNlxX5XBzHig0TeCPfPc+1+NQmliXtndT3PFwAjrQHE/6wnQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@fastify/middie/-/middie-9.0.3.tgz", + "integrity": "sha512-7OYovKXp9UKYeVMcjcFLMcSpoMkmcZmfnG+eAvtdiatN35W7c+r9y1dRfpA+pfFVNuHGGqI3W+vDTmjvcfLcMA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "@fastify/error": "^3.2.0", - "fastify-plugin": "^4.0.0", - "path-to-regexp": "^6.3.0", + "@fastify/error": "^4.0.0", + "fastify-plugin": "^5.0.0", + "path-to-regexp": "^8.1.0", "reusify": "^1.0.4" } }, - "node_modules/@fastify/middie/node_modules/@fastify/error": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", - "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", - "license": "MIT" - }, - "node_modules/@fastify/middie/node_modules/path-to-regexp": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", - "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", - "license": "MIT" - }, "node_modules/@fastify/multipart": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@fastify/multipart/-/multipart-8.3.1.tgz", - "integrity": "sha512-pncbnG28S6MIskFSVRtzTKE9dK+GrKAJl0NbaQ/CG8ded80okWFsYKzSlP9haaLNQhNRDOoHqmGQNvgbiPVpWQ==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@fastify/multipart/-/multipart-9.0.3.tgz", + "integrity": "sha512-pJogxQCrT12/6I5Fh6jr3narwcymA0pv4B0jbC7c6Bl9wnrxomEUnV0d26w6gUls7gSXmhG8JGRMmHFIPsxt1g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { "@fastify/busboy": "^3.0.0", "@fastify/deepmerge": "^2.0.0", "@fastify/error": "^4.0.0", - "fastify-plugin": "^4.0.0", - "secure-json-parse": "^2.4.0", - "stream-wormhole": "^1.1.0" + "fastify-plugin": "^5.0.0", + "secure-json-parse": "^3.0.0" + } + }, + "node_modules/@fastify/proxy-addr": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.0.0.tgz", + "integrity": "sha512-37qVVA1qZ5sgH7KpHkkC4z9SK6StIsIcOmpjvMPXNb3vx2GQxhZocogVYbr2PbbeLCQxYIPDok307xEvRZOzGA==", + "license": "MIT", + "dependencies": { + "@fastify/forwarded": "^3.0.0", + "ipaddr.js": "^2.1.0" } }, "node_modules/@fastify/send": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@fastify/send/-/send-2.1.0.tgz", - "integrity": "sha512-yNYiY6sDkexoJR0D8IDy3aRP3+L4wdqCpvx5WP+VtEU58sn7USmKynBzDQex5X42Zzvw2gNzzYgP90UfWShLFA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@fastify/send/-/send-4.1.0.tgz", + "integrity": "sha512-TMYeQLCBSy2TOFmV95hQWkiTYgC/SEx7vMdV+wnZVX4tt8VBLKzmH8vV9OzJehV0+XBfg+WxPMt5wp+JBUKsVw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "@lukeed/ms": "^2.0.1", + "@lukeed/ms": "^2.0.2", "escape-html": "~1.0.3", "fast-decode-uri-component": "^1.0.1", - "http-errors": "2.0.0", - "mime": "^3.0.0" + "http-errors": "^2.0.0", + "mime": "^3" } }, "node_modules/@fastify/static": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@fastify/static/-/static-7.0.4.tgz", - "integrity": "sha512-p2uKtaf8BMOZWLs6wu+Ihg7bWNBdjNgCwDza4MJtTqg+5ovKmcbgbR9Xs5/smZ1YISfzKOCNYmZV8LaCj+eJ1Q==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@fastify/static/-/static-8.2.0.tgz", + "integrity": "sha512-PejC/DtT7p1yo3p+W7LiUtLMsV8fEvxAK15sozHy9t8kwo5r0uLYmhV/inURmGz1SkHZFz/8CNtHLPyhKcx4SQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "@fastify/accept-negotiator": "^1.0.0", - "@fastify/send": "^2.0.0", - "content-disposition": "^0.5.3", - "fastify-plugin": "^4.0.0", - "fastq": "^1.17.0", - "glob": "^10.3.4" + "@fastify/accept-negotiator": "^2.0.0", + "@fastify/send": "^4.0.0", + "content-disposition": "^0.5.4", + "fastify-plugin": "^5.0.0", + "fastq": "^1.17.1", + "glob": "^11.0.0" } }, "node_modules/@homebridge/hap-client": { @@ -1309,14 +1403,15 @@ } }, "node_modules/@homebridge/node-pty-prebuilt-multiarch": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@homebridge/node-pty-prebuilt-multiarch/-/node-pty-prebuilt-multiarch-0.11.14.tgz", - "integrity": "sha512-fuiq5kb4i0Ao0BTf7O6kvtwUhCCCJHLhWLWaaUaLuniDGS4xmj+gxvkidJpxYVT/zTXdbcLuCY44UnoWC7xODg==", + "version": "0.13.0-beta.4", + "resolved": "https://registry.npmjs.org/@homebridge/node-pty-prebuilt-multiarch/-/node-pty-prebuilt-multiarch-0.13.0-beta.4.tgz", + "integrity": "sha512-d4fzzK6PlGrfVOqCtOblgFOOxBD6x7MMkPNGWz6A08QQS0VnY0MJ/OFowFBx+nMCPfBJVI95728bU59mPs1ZwQ==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "nan": "^2.19.0", - "prebuild-install": "^7.1.2" + "node-addon-api": "^7.1.0", + "prebuild-install": "^7.1.2", + "semver": "^7.7.2" } }, "node_modules/@humanfs/core": { @@ -1394,7 +1489,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "dev": true, "license": "MIT", "engines": { "node": "20 || >=22" @@ -1404,7 +1498,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", - "dev": true, "license": "MIT", "dependencies": { "@isaacs/balanced-match": "^4.0.1" @@ -1548,24 +1641,25 @@ "license": "MIT" }, "node_modules/@nestjs/axios": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-3.1.3.tgz", - "integrity": "sha512-RZ/63c1tMxGLqyG3iOCVt7A72oy4x1eM6QEhd4KzCYpaVWW0igq0WSREeRoEZhIxRcZfDfIIkvsOMiM7yfVGZQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-4.0.0.tgz", + "integrity": "sha512-1cB+Jyltu/uUPNQrpUimRHEQHrnQrpLzVj6dU3dgn6iDDDdahr10TgHFGTmw5VuJ9GzKZsCLDL78VSwJAs/9JQ==", "license": "MIT", "peerDependencies": { - "@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/common": "^10.0.0 || ^11.0.0", "axios": "^1.3.1", - "rxjs": "^6.0.0 || ^7.0.0" + "rxjs": "^7.0.0" } }, "node_modules/@nestjs/common": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.18.tgz", - "integrity": "sha512-9SrTth6YJJ9CjVnekw9WP8kaiwh+tSgR0KIrPYV/aWgF9D0175uDJUglzbiCfUbkPyHN8jcKXUXd3EVPDY6BNA==", + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-11.1.3.tgz", + "integrity": "sha512-ogEK+GriWodIwCw6buQ1rpcH4Kx+G7YQ9EwuPySI3rS05pSdtQ++UhucjusSI9apNidv+QURBztJkRecwwJQXg==", "license": "MIT", "dependencies": { - "file-type": "20.4.1", + "file-type": "21.0.0", "iterare": "1.2.1", + "load-esm": "1.0.2", "tslib": "2.8.1", "uid": "2.0.2" }, @@ -1574,8 +1668,8 @@ "url": "https://opencollective.com/nest" }, "peerDependencies": { - "class-transformer": "*", - "class-validator": "*", + "class-transformer": ">=0.4.1", + "class-validator": ">=0.13.2", "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, @@ -1589,28 +1683,31 @@ } }, "node_modules/@nestjs/core": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.4.18.tgz", - "integrity": "sha512-+cs96rnpHIfkn9o0DLZFKuE1RZ3FFQkpkzz+DY2U8C3Wn3VX5fQaO4YuabweLIhUKTLr9DMxPycA5qk5rAPFBw==", + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-11.1.3.tgz", + "integrity": "sha512-5lTni0TCh8x7bXETRD57pQFnKnEg1T6M+VLE7wAmyQRIecKQU+2inRGZD+A4v2DC1I04eA0WffP0GKLxjOKlzw==", "hasInstallScript": true, "license": "MIT", "dependencies": { - "@nuxtjs/opencollective": "0.3.2", + "@nuxt/opencollective": "0.4.1", "fast-safe-stringify": "2.1.1", "iterare": "1.2.1", - "path-to-regexp": "3.3.0", + "path-to-regexp": "8.2.0", "tslib": "2.8.1", "uid": "2.0.2" }, + "engines": { + "node": ">= 20" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0", - "@nestjs/websockets": "^10.0.0", + "@nestjs/common": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0", + "@nestjs/websockets": "^11.0.0", "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, @@ -1627,25 +1724,25 @@ } }, "node_modules/@nestjs/jwt": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-10.2.0.tgz", - "integrity": "sha512-x8cG90SURkEiLOehNaN2aRlotxT0KZESUliOPKKnjWiyJOcWurkF3w345WOX0P4MgFzUjGoZ1Sy0aZnxeihT0g==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-11.0.0.tgz", + "integrity": "sha512-v7YRsW3Xi8HNTsO+jeHSEEqelX37TVWgwt+BcxtkG/OfXJEOs6GZdbdza200d6KqId1pJQZ6UPj1F0M6E+mxaA==", "license": "MIT", "dependencies": { - "@types/jsonwebtoken": "9.0.5", + "@types/jsonwebtoken": "9.0.7", "jsonwebtoken": "9.0.2" }, "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0" + "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0" } }, "node_modules/@nestjs/mapped-types": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.0.6.tgz", - "integrity": "sha512-84ze+CPfp1OWdpRi1/lOu59hOhTz38eVzJvRKrg9ykRFwDz+XleKfMsG0gUqNZYFa6v53XYzeD+xItt8uDW7NQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@nestjs/mapped-types/-/mapped-types-2.1.0.tgz", + "integrity": "sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==", "license": "MIT", "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", + "@nestjs/common": "^10.0.0 || ^11.0.0", "class-transformer": "^0.4.0 || ^0.5.0", "class-validator": "^0.13.0 || ^0.14.0", "reflect-metadata": "^0.1.12 || ^0.2.0" @@ -1660,27 +1757,28 @@ } }, "node_modules/@nestjs/passport": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-10.0.3.tgz", - "integrity": "sha512-znJ9Y4S8ZDVY+j4doWAJ8EuuVO7SkQN3yOBmzxbGaXbvcSwFDAdGJ+OMCg52NdzIO4tQoN4pYKx8W6M0ArfFRQ==", + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@nestjs/passport/-/passport-11.0.5.tgz", + "integrity": "sha512-ulQX6mbjlws92PIM15Naes4F4p2JoxGnIJuUsdXQPT+Oo2sqQmENEZXM7eYuimocfHnKlcfZOuyzbA33LwUlOQ==", "license": "MIT", "peerDependencies": { - "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0", - "passport": "^0.4.0 || ^0.5.0 || ^0.6.0 || ^0.7.0" + "@nestjs/common": "^10.0.0 || ^11.0.0", + "passport": "^0.5.0 || ^0.6.0 || ^0.7.0" } }, "node_modules/@nestjs/platform-fastify": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-10.4.18.tgz", - "integrity": "sha512-2Ps17h3/snDjk9Vs4aXF+ZsEBXA2u02wPKxM+15ijM22r0aegpkqSqladP0Rv90MNubEblgHYD5NWXHKndQi1A==", - "license": "MIT", - "dependencies": { - "@fastify/cors": "9.0.1", - "@fastify/formbody": "7.4.0", - "@fastify/middie": "8.3.3", - "fastify": "4.28.1", - "light-my-request": "6.3.0", - "path-to-regexp": "3.3.0", + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/platform-fastify/-/platform-fastify-11.1.3.tgz", + "integrity": "sha512-SMIjGV6eAxQv6+/2OumIdNivVLebql6THWjXv8Uh4dR1CI6ipp3gMbpoiYbHP7AGXv8pzuGmpakli86VP9P8NQ==", + "license": "MIT", + "dependencies": { + "@fastify/cors": "11.0.1", + "@fastify/formbody": "8.0.2", + "@fastify/middie": "9.0.3", + "fast-querystring": "1.1.2", + "fastify": "5.3.3", + "light-my-request": "6.6.0", + "path-to-regexp": "8.2.0", "tslib": "2.8.1" }, "funding": { @@ -1688,10 +1786,10 @@ "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@fastify/static": "^6.0.0 || ^7.0.0", - "@fastify/view": "^7.0.0 || ^8.0.0", - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0" + "@fastify/static": "^8.0.0", + "@fastify/view": "^10.0.0 || ^11.0.0", + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0" }, "peerDependenciesMeta": { "@fastify/static": { @@ -1703,9 +1801,9 @@ } }, "node_modules/@nestjs/platform-socket.io": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-10.4.18.tgz", - "integrity": "sha512-+X/c4I5rYJU/X5ZRhrd3jJ/bL86zWWTc6FIdhNfTvVyLneYkIH9+snCyi4+7lu0auhDXqA90zNzmaUg9Iwno1Q==", + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/platform-socket.io/-/platform-socket.io-11.1.3.tgz", + "integrity": "sha512-jQ+ccprmh3kKolBp+bb97zoaS3vKaiyeNqyctGqV4CSG8P6mXSaaUObWxAsw6Jdgn5YQAVEBWJ6FhvF4s6QZbg==", "license": "MIT", "dependencies": { "socket.io": "4.8.1", @@ -1716,28 +1814,28 @@ "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/websockets": "^10.0.0", + "@nestjs/common": "^11.0.0", + "@nestjs/websockets": "^11.0.0", "rxjs": "^7.1.0" } }, "node_modules/@nestjs/swagger": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-8.1.1.tgz", - "integrity": "sha512-5Mda7H1DKnhKtlsb0C7PYshcvILv8UFyUotHzxmWh0G65Z21R3LZH/J8wmpnlzL4bmXIfr42YwbEwRxgzpJ5sQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@nestjs/swagger/-/swagger-11.2.0.tgz", + "integrity": "sha512-5wolt8GmpNcrQv34tIPUtPoV1EeFbCetm40Ij3+M0FNNnf2RJ3FyWfuQvI8SBlcJyfaounYVTKzKHreFXsUyOg==", "license": "MIT", "dependencies": { - "@microsoft/tsdoc": "^0.15.0", - "@nestjs/mapped-types": "2.0.6", + "@microsoft/tsdoc": "0.15.1", + "@nestjs/mapped-types": "2.1.0", "js-yaml": "4.1.0", "lodash": "4.17.21", - "path-to-regexp": "3.3.0", - "swagger-ui-dist": "5.18.2" + "path-to-regexp": "8.2.0", + "swagger-ui-dist": "5.21.0" }, "peerDependencies": { - "@fastify/static": "^6.0.0 || ^7.0.0", - "@nestjs/common": "^9.0.0 || ^10.0.0", - "@nestjs/core": "^9.0.0 || ^10.0.0", + "@fastify/static": "^8.0.0", + "@nestjs/common": "^11.0.1", + "@nestjs/core": "^11.0.1", "class-transformer": "*", "class-validator": "*", "reflect-metadata": "^0.1.12 || ^0.2.0" @@ -1755,9 +1853,9 @@ } }, "node_modules/@nestjs/testing": { - "version": "10.4.19", - "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-10.4.19.tgz", - "integrity": "sha512-YfzkjTmwEcoWqo8xr8YiTZMC4FjBEOg4uRTAPI2p6iGLWu+27tYau1CtAKFHY0uSAK3FzgtsAuYoxBSlfr9mWA==", + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/testing/-/testing-11.1.3.tgz", + "integrity": "sha512-CeXG6/eEqgFIkPkmU00y18Dd3DLOIDFhPItzJK1SWckKo6IhcnfoRJzGx75bmuvUMjb51j6An96S/+MJ2ty9jA==", "dev": true, "license": "MIT", "dependencies": { @@ -1768,10 +1866,10 @@ "url": "https://opencollective.com/nest" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/microservices": "^10.0.0", - "@nestjs/platform-express": "^10.0.0" + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0", + "@nestjs/microservices": "^11.0.0", + "@nestjs/platform-express": "^11.0.0" }, "peerDependenciesMeta": { "@nestjs/microservices": { @@ -1783,9 +1881,9 @@ } }, "node_modules/@nestjs/websockets": { - "version": "10.4.18", - "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-10.4.18.tgz", - "integrity": "sha512-FnwRiUGReMo8guM6fVoDotwAxOzV0Y2bLC+avz1kPfCUT7LAvivMQ0xs+rJy/nmdHb2TDxwFOK6gyQSznUdOzQ==", + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/@nestjs/websockets/-/websockets-11.1.3.tgz", + "integrity": "sha512-IjhWKfRf0D247JxYIEs8USblJJbcxUsKJpzbCPaZ7TrVy4LrpG3IRQDlSTOw599TRIYP5ixyH9C0+v5DyaI9uA==", "license": "MIT", "dependencies": { "iterare": "1.2.1", @@ -1793,9 +1891,9 @@ "tslib": "2.8.1" }, "peerDependencies": { - "@nestjs/common": "^10.0.0", - "@nestjs/core": "^10.0.0", - "@nestjs/platform-socket.io": "^10.0.0", + "@nestjs/common": "^11.0.0", + "@nestjs/core": "^11.0.0", + "@nestjs/platform-socket.io": "^11.0.0", "reflect-metadata": "^0.1.12 || ^0.2.0", "rxjs": "^7.1.0" }, @@ -1843,22 +1941,20 @@ "node": ">= 8" } }, - "node_modules/@nuxtjs/opencollective": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", - "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "node_modules/@nuxt/opencollective": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.4.1.tgz", + "integrity": "sha512-GXD3wy50qYbxCJ652bDrDzgMr3NFEkIS374+IgFQKkCvk9yiYcLvX2XDYr7UyQxf4wK0e+yqDYRubZ0DtOxnmQ==", "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "consola": "^2.15.0", - "node-fetch": "^2.6.1" + "consola": "^3.2.3" }, "bin": { "opencollective": "bin/opencollective.js" }, "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" + "node": "^14.18.0 || >=16.10.0", + "npm": ">=5.10.0" } }, "node_modules/@otplib/core": { @@ -1912,6 +2008,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, "license": "MIT", "optional": true, "engines": { @@ -2720,9 +2817,9 @@ } }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.5.tgz", - "integrity": "sha512-VRLSGzik+Unrup6BsouBeHsf4d1hOEgYWTm/7Nmw1sXoN1+tRly/Gy/po3yeahnP4jfnQWWAhQAqcNfH7ngOkA==", + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.7.tgz", + "integrity": "sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==", "license": "MIT", "dependencies": { "@types/node": "*" @@ -3646,9 +3743,9 @@ } }, "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", "dependencies": { "ajv": "^8.0.0" @@ -3678,22 +3775,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ajv-formats/node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/ajv-formats/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -3835,21 +3916,15 @@ } }, "node_modules/avvio": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-8.4.0.tgz", - "integrity": "sha512-CDSwaxINFy59iNwhYnkvALBwZiTydGkOecZyPkqBpABYR1KqGEsET0VOOYDwtleZSUIdeY36DC2bSZ24CO1igA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.1.0.tgz", + "integrity": "sha512-fYASnYi600CsH/j9EQov7lECAniYiBFiiAtBNuZYLA2leLe9qOvZzqYHFjtIj6gD2VMoMLP14834LFWvr4IfDw==", "license": "MIT", "dependencies": { - "@fastify/error": "^3.3.0", + "@fastify/error": "^4.0.0", "fastq": "^1.17.1" } }, - "node_modules/avvio/node_modules/@fastify/error": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", - "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", - "license": "MIT" - }, "node_modules/axios": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", @@ -3865,6 +3940,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -3953,6 +4029,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -4152,6 +4229,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -4439,12 +4528,12 @@ } }, "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/comment-parser": { @@ -4490,22 +4579,6 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/confbox": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", @@ -4514,10 +4587,13 @@ "license": "MIT" }, "node_modules/consola": { - "version": "2.15.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", - "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", - "license": "MIT" + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } }, "node_modules/content-disposition": { "version": "0.5.4", @@ -4751,7 +4827,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5897,12 +5972,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-content-type-parse": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-1.1.0.tgz", - "integrity": "sha512-fBHHqSTFLVnR61C+gltJuE5GkVQMV0S2nqUO8TJ+5Z3qAKG8vAx4FKai1s5jq/inV1+sREynIWSuQ6HgoSXpDQ==", - "license": "MIT" - }, "node_modules/fast-decode-uri-component": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", @@ -5961,17 +6030,26 @@ "peer": true }, "node_modules/fast-json-stringify": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-5.16.1.tgz", - "integrity": "sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-6.0.1.tgz", + "integrity": "sha512-s7SJE83QKBZwg54dIbD5rCtzOBVD43V1ReWXXYqBgwCwHLYAAT0RQc/FmrQglXqWPpz6omtryJQOau5jI4Nrvg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "@fastify/merge-json-schemas": "^0.1.0", - "ajv": "^8.10.0", + "@fastify/merge-json-schemas": "^0.2.0", + "ajv": "^8.12.0", "ajv-formats": "^3.0.1", - "fast-deep-equal": "^3.1.3", - "fast-uri": "^2.1.0", - "json-schema-ref-resolver": "^1.0.1", + "fast-uri": "^3.0.0", + "json-schema-ref-resolver": "^2.0.0", "rfdc": "^1.2.0" } }, @@ -5991,39 +6069,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/fast-json-stringify/node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/fast-json-stringify/node_modules/ajv/node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/fast-json-stringify/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -6063,15 +6108,25 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", - "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==", - "license": "MIT" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, "node_modules/fastify": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-4.29.1.tgz", - "integrity": "sha512-m2kMNHIG92tSNWv+Z3UeTR9AWLLuo7KctC7mlFPtMEVrfjIhmQhkQnT9v15qA/BfVq3vvj134Y0jl9SBje3jXQ==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.4.0.tgz", + "integrity": "sha512-I4dVlUe+WNQAhKSyv15w+dwUh2EPiEl4X2lGYMmNSgF83WzTMAPKGdWEv5tPsCQOb+SOZwz8Vlta2vF+OeDgRw==", "funding": [ { "type": "github", @@ -6084,55 +6139,44 @@ ], "license": "MIT", "dependencies": { - "@fastify/ajv-compiler": "^3.5.0", - "@fastify/error": "^3.4.0", - "@fastify/fast-json-stringify-compiler": "^4.3.0", + "@fastify/ajv-compiler": "^4.0.0", + "@fastify/error": "^4.0.0", + "@fastify/fast-json-stringify-compiler": "^5.0.0", + "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", - "avvio": "^8.3.0", - "fast-content-type-parse": "^1.1.0", - "fast-json-stringify": "^5.8.0", - "find-my-way": "^8.0.0", - "light-my-request": "^5.11.0", + "avvio": "^9.0.0", + "fast-json-stringify": "^6.0.0", + "find-my-way": "^9.0.0", + "light-my-request": "^6.0.0", "pino": "^9.0.0", - "process-warning": "^3.0.0", - "proxy-addr": "^2.0.7", - "rfdc": "^1.3.0", - "secure-json-parse": "^2.7.0", - "semver": "^7.5.4", - "toad-cache": "^3.3.0" + "process-warning": "^5.0.0", + "rfdc": "^1.3.1", + "secure-json-parse": "^4.0.0", + "semver": "^7.6.0", + "toad-cache": "^3.7.0" } }, "node_modules/fastify-plugin": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-4.5.1.tgz", - "integrity": "sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==", - "license": "MIT" - }, - "node_modules/fastify/node_modules/@fastify/error": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", - "integrity": "sha512-wWSvph+29GR783IhmvdwWnN4bUxTD01Vm5Xad4i7i1VuAOItLvbPAb69sb0IQ2N57yprvhNIwAP5B6xfKTmjmQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.0.1.tgz", + "integrity": "sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==", "license": "MIT" }, - "node_modules/fastify/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fastify/node_modules/light-my-request": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-5.14.0.tgz", - "integrity": "sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==", - "license": "BSD-3-Clause", - "dependencies": { - "cookie": "^0.7.0", - "process-warning": "^3.0.0", - "set-cookie-parser": "^2.4.1" - } + "node_modules/fastify/node_modules/secure-json-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.0.0.tgz", + "integrity": "sha512-dxtLJO6sc35jWidmLxo7ij+Eg48PM/kleBsxpC8QJE0qJICe+KawkDQmvCMZUr9u7WKVHgMW6vy3fQ7zMiFZMA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" }, "node_modules/fastq": { "version": "1.19.1", @@ -6193,18 +6237,18 @@ } }, "node_modules/file-type": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.4.1.tgz", - "integrity": "sha512-hw9gNZXUfZ02Jo0uafWLaFVPter5/k2rfcrjFJJHX/77xtSDOfJuEFb6oKlFV86FLP1SuyHMW1PSk0U9M5tKkQ==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz", + "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==", "license": "MIT", "dependencies": { - "@tokenizer/inflate": "^0.2.6", - "strtok3": "^10.2.0", + "@tokenizer/inflate": "^0.2.7", + "strtok3": "^10.2.2", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sindresorhus/file-type?sponsor=1" @@ -6224,17 +6268,17 @@ } }, "node_modules/find-my-way": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-8.2.2.tgz", - "integrity": "sha512-Dobi7gcTEq8yszimcfp/R7+owiT4WncAJ7VTTgFH1jYJ5GaG1FbhjwDG820hptN0QDFvzVY3RfCzdInvGPGzjA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.3.0.tgz", + "integrity": "sha512-eRoFWQw+Yv2tuYlK2pjFS2jGXSxSppAs3hSQjfxVKxM5amECzIgYYc1FEI8ZmhSh/Ig+FrKEz43NLRKJjYCZVg==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-querystring": "^1.0.0", - "safe-regex2": "^3.1.0" + "safe-regex2": "^5.0.0" }, "engines": { - "node": ">=14" + "node": ">=20" } }, "node_modules/find-up": { @@ -6352,15 +6396,6 @@ "node": ">=0.4.x" } }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -6472,21 +6507,24 @@ "license": "MIT" }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", "license": "ISC", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" + "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, + "engines": { + "node": "20 || >=22" + }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -6513,6 +6551,21 @@ "license": "BSD-2-Clause", "peer": true }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", @@ -6600,12 +6653,12 @@ } }, "node_modules/helmet": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz", - "integrity": "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-8.1.0.tgz", + "integrity": "sha512-jOiHyAZsmnr8LqoPGmCjYAaiuWwjAPLgY8ZX2XrmHawt99/u1y6RgrZMTeoPfpUbV96HOalYgz1qzkRbw54Pmg==", "license": "MIT", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/html-escaper": { @@ -6741,12 +6794,12 @@ } }, "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">= 10" } }, "node_modules/is-binary-path": { @@ -6898,6 +6951,19 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", @@ -6937,18 +7003,18 @@ } }, "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, + "engines": { + "node": "20 || >=22" + }, "funding": { "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/jest-worker": { @@ -6967,23 +7033,6 @@ "node": ">= 10.13.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/js-tokens": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", @@ -7043,12 +7092,22 @@ "peer": true }, "node_modules/json-schema-ref-resolver": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", - "integrity": "sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz", + "integrity": "sha512-HG0SIB9X4J8bwbxCbnd5FfPEbcXAJYTi1pBJeP/QPON+w8ovSME8iRG+ElHNxZNX2Qh6eYn1GdzJFS4cDFfx0Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.3" + "dequal": "^2.0.3" } }, "node_modules/json-schema-traverse": { @@ -7217,9 +7276,19 @@ "license": "MIT" }, "node_modules/light-my-request": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.3.0.tgz", - "integrity": "sha512-bWTAPJmeWQH5suJNYwG0f5cs0p6ho9e6f1Ppoxv5qMosY+s9Ir2+ZLvvHcgA7VTDop4zl/NCHhOVVqU+kd++Ow==", + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", + "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause", "dependencies": { "cookie": "^1.0.1", @@ -7243,6 +7312,25 @@ ], "license": "MIT" }, + "node_modules/load-esm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/load-esm/-/load-esm-1.0.2.tgz", + "integrity": "sha512-nVAvWk/jeyrWyXEAs84mpQCYccxRqgKY4OznLuJhJCa0XsPSfdOIr2zvBZEj3IHEHbX97jjscKRRV539bW0Gpw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + }, + { + "type": "buymeacoffee", + "url": "https://buymeacoffee.com/borewit" + } + ], + "license": "MIT", + "engines": { + "node": ">=13.2.0" + } + }, "node_modules/load-tsconfig": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", @@ -7396,10 +7484,13 @@ "license": "MIT" }, "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "license": "ISC", + "engines": { + "node": "20 || >=22" + } }, "node_modules/luxon": { "version": "3.6.1", @@ -8441,6 +8532,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -8535,15 +8627,6 @@ "pathe": "^2.0.1" } }, - "node_modules/mnemonist": { - "version": "0.39.6", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.6.tgz", - "integrity": "sha512-A/0v5Z59y63US00cRSLiloEIw3t5G+MiKz4BhX21FI+YBJXBOGW0ohFxTxO08dsOYlzxo87T7vGfZKYp2bcAWA==", - "license": "MIT", - "dependencies": { - "obliterator": "^2.0.1" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8563,12 +8646,6 @@ "multicast-dns": "cli.js" } }, - "node_modules/nan": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.2.tgz", - "integrity": "sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==", - "license": "MIT" - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", @@ -8640,6 +8717,12 @@ "node": ">=10" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, "node_modules/node-cache": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", @@ -8652,26 +8735,6 @@ "node": ">= 8.0.0" } }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -8816,12 +8879,6 @@ "node": ">= 6" } }, - "node_modules/obliterator": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", - "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", - "license": "MIT" - }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", @@ -9072,26 +9129,29 @@ } }, "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", "license": "BlueOak-1.0.0", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=16 || 14 >=14.18" + "node": "20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/path-to-regexp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", - "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", - "license": "MIT" + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } }, "node_modules/pathe": { "version": "2.0.3", @@ -9172,22 +9232,6 @@ "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", "license": "MIT" }, - "node_modules/pino/node_modules/process-warning": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", - "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, "node_modules/pkg-types": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.1.0.tgz", @@ -9345,24 +9389,21 @@ "license": "MIT" }, "node_modules/process-warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", - "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT" }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "license": "MIT", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -9661,9 +9702,9 @@ "license": "ISC" }, "node_modules/ret": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.4.3.tgz", - "integrity": "sha512-0f4Memo5QP7WQyUEAYUO3esD/XjOc3Zjjg5CPsAq1p8sIu0XPeMbHJemKA0BO7tV0X7+A0FoEpbmHXWxPyD3wQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", + "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", "license": "MIT", "engines": { "node": ">=10" @@ -9705,89 +9746,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rollup": { "version": "4.44.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.0.tgz", @@ -9882,12 +9840,22 @@ "license": "MIT" }, "node_modules/safe-regex2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-3.1.0.tgz", - "integrity": "sha512-RAAZAGbap2kBfbVhvmnTFv73NWLMvDGOITFYTZBAaY8eR+Ir4ef7Up/e7amo+y1+AH+3PtLkrt9mvcTsG9LXug==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.0.0.tgz", + "integrity": "sha512-YwJwe5a51WlK7KbOJREPdjNrpViQBI3p4T50lfwPuDhZnE3XGVTlGvi+aolc5+RvxDD6bnUmjVsU9n1eboLUYw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "MIT", "dependencies": { - "ret": "~0.4.0" + "ret": "~0.5.0" } }, "node_modules/safe-stable-stringify": { @@ -9938,6 +9906,25 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/schema-utils/node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/schema-utils/node_modules/ajv-keywords": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", @@ -9952,24 +9939,6 @@ "ajv": "^8.8.2" } }, - "node_modules/schema-utils/node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause", - "peer": true - }, "node_modules/schema-utils/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -9994,9 +9963,19 @@ } }, "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-3.0.2.tgz", + "integrity": "sha512-H6nS2o8bWfpFEV6U38sOSjS7bTbdgbCGU9wEM6W14P5H0QOsz94KCusifV44GpHDTu2nqZbuDNhTzu+mjDSw1w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause" }, "node_modules/semver": { @@ -10345,15 +10324,6 @@ "dev": true, "license": "MIT" }, - "node_modules/stream-wormhole": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stream-wormhole/-/stream-wormhole-1.1.0.tgz", - "integrity": "sha512-gHFfL3px0Kctd6Po0M8TzEvt3De/xu6cnRrjlfYNhwbhLPLwigI2t1nc6jrzNuaYg5C4YF78PPFuQPzRiqn9ew==", - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -10529,21 +10499,25 @@ } }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/swagger-ui-dist": { - "version": "5.18.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.18.2.tgz", - "integrity": "sha512-J+y4mCw/zXh1FOj5wGJvnAajq6XgHOyywsa9yITmwxIlJbMqITq3gYRZHaeqLVH/eV/HOPphE6NjF+nbSNC5Zw==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.21.0.tgz", + "integrity": "sha512-E0K3AB6HvQd8yQNSMR7eE5bk+323AUxjtCz/4ZNKiahOlPhPJxqn3UPIGs00cyY/dhrTDJ61L7C/a8u6zhGrZg==", "license": "Apache-2.0", "dependencies": { "@scarf/scarf": "=1.4.0" @@ -10774,6 +10748,67 @@ "node": ">=18" } }, + "node_modules/test-exclude/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/test-exclude/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/test-exclude/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/thirty-two": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", @@ -10945,12 +10980,6 @@ "nodetouch": "bin/nodetouch.js" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -11596,12 +11625,6 @@ "defaults": "^1.0.3" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" - }, "node_modules/webpack": { "version": "5.99.9", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.9.tgz", @@ -11695,16 +11718,6 @@ "node": ">=4.0" } }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 0b7932006..ad0d36acc 100644 --- a/package.json +++ b/package.json @@ -79,27 +79,27 @@ "watch:ui": "npm run start --prefix ui" }, "dependencies": { - "@fastify/helmet": "11.1.1", - "@fastify/multipart": "8.3.1", - "@fastify/static": "7.0.4", + "@fastify/helmet": "13.0.1", + "@fastify/multipart": "9.0.3", + "@fastify/static": "8.2.0", "@homebridge/hap-client": "3.1.0", - "@homebridge/node-pty-prebuilt-multiarch": "0.11.14", - "@nestjs/axios": "3.1.3", - "@nestjs/common": "10.4.18", - "@nestjs/core": "10.4.18", - "@nestjs/jwt": "10.2.0", - "@nestjs/passport": "10.0.3", - "@nestjs/platform-fastify": "10.4.18", - "@nestjs/platform-socket.io": "10.4.18", - "@nestjs/swagger": "8.1.1", - "@nestjs/websockets": "10.4.18", + "@homebridge/node-pty-prebuilt-multiarch": "0.13.0-beta.4", + "@nestjs/axios": "4.0.0", + "@nestjs/common": "11.1.3", + "@nestjs/core": "11.1.3", + "@nestjs/jwt": "11.0.0", + "@nestjs/passport": "11.0.5", + "@nestjs/platform-fastify": "11.1.3", + "@nestjs/platform-socket.io": "11.1.3", + "@nestjs/swagger": "11.2.0", + "@nestjs/websockets": "11.1.3", "axios": "1.10.0", "bash-color": "0.0.4", "class-transformer": "0.5.1", "class-validator": "0.14.2", - "commander": "13.1.0", + "commander": "14.0.0", "dayjs": "1.11.13", - "fastify": "4.29.1", + "fastify": "5.4.0", "fs-extra": "11.3.0", "jsonwebtoken": "9.0.2", "lodash": "4.17.21", @@ -121,7 +121,7 @@ }, "devDependencies": { "@antfu/eslint-config": "^4.15.0", - "@nestjs/testing": "^10.4.18", + "@nestjs/testing": "^11.1.3", "@prettier/plugin-xml": "^3.4.1", "@types/fs-extra": "^11.0.4", "@types/lodash": "^4.17.18", @@ -147,7 +147,7 @@ }, "overrides": { "@nestjs/platform-fastify": { - "fastify": "4.29.1" + "fastify": "5.4.0" } }, "maintainers": [ diff --git a/src/index.ts b/src/index.ts index 71edc3a52..a0794ba99 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,8 +28,8 @@ class HomebridgeUi { .option('-T, --no-timestamp', '', () => process.env.UIX_LOG_NO_TIMESTAMPS = '1') .parse(process.argv) - if (!satisfies(process.version, '>=18.15.0')) { - const msg = `Node.js v18.15.0 higher is required. You may experience issues running this plugin running on ${process.version}.` + if (!satisfies(process.version, '>=20.18.0')) { + const msg = `Node.js v20.18.0 higher is required. You may experience issues running this plugin running on ${process.version}.` log.error(msg) log.warn(msg) } diff --git a/src/modules/accessories/accessories.controller.ts b/src/modules/accessories/accessories.controller.ts index 8a5fe98d7..180f4f5cb 100644 --- a/src/modules/accessories/accessories.controller.ts +++ b/src/modules/accessories/accessories.controller.ts @@ -4,7 +4,7 @@ import { Get, Param, Put, - Req, + Request, UseGuards, } from '@nestjs/common' import { AuthGuard } from '@nestjs/passport' @@ -35,7 +35,7 @@ export class AccessoriesController { summary: 'Get the accessory and room layout for the authenticating user.', }) @Get('/layout') - getAccessoryLayout(@Req() req) { + getAccessoryLayout(@Request() req) { return this.accessoriesService.getAccessoryLayout(req.user.username) } diff --git a/src/modules/config-editor/config-editor.controller.ts b/src/modules/config-editor/config-editor.controller.ts index b9ef4af75..79a1750de 100644 --- a/src/modules/config-editor/config-editor.controller.ts +++ b/src/modules/config-editor/config-editor.controller.ts @@ -121,7 +121,7 @@ export class ConfigEditorController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Return the Homebridge `config.json` file for the given backup ID.' }) @ApiParam({ name: 'backupId', type: 'number' }) - @Get('/backups/:backupId(\\d+)') + @Get('/backups/:backupId') getBackup(@Param('backupId', ParseIntPipe) backupId) { return this.configEditorService.getConfigBackup(backupId) } diff --git a/src/modules/platform-tools/hb-service/hb-service.controller.ts b/src/modules/platform-tools/hb-service/hb-service.controller.ts index f31cc5d2b..63599a4de 100644 --- a/src/modules/platform-tools/hb-service/hb-service.controller.ts +++ b/src/modules/platform-tools/hb-service/hb-service.controller.ts @@ -4,7 +4,7 @@ import { Get, Put, Query, - Req, + Request, UseGuards, } from '@nestjs/common' import { AuthGuard } from '@nestjs/passport' @@ -58,7 +58,7 @@ export class HbServiceController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Truncate/empty the log file.' }) @Put('log/truncate') - truncateLogFile(@Req() req) { + truncateLogFile(@Request() req) { return this.hbServiceService.truncateLogFile(req.user.username) } } diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index 150eb6788..ae54ec241 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -7,7 +7,7 @@ import { ParseIntPipe, Patch, Post, - Req, + Request, UseGuards, } from '@nestjs/common' import { AuthGuard } from '@nestjs/passport' @@ -53,7 +53,7 @@ export class UsersController { @ApiResponse({ type: UserDto, status: 200 }) @ApiOperation({ summary: 'Update a user.' }) @ApiParam({ name: 'userId', type: 'number' }) - @Patch('/:userId(\\d+)') + @Patch('/:userId') updateUser(@Param('userId', ParseIntPipe) userId: number, @Body() body: UserDto) { return this.authService.updateUser(userId, body) } @@ -61,7 +61,7 @@ export class UsersController { @UseGuards(AdminGuard) @ApiOperation({ summary: 'Delete a user.' }) @ApiParam({ name: 'userId', type: 'number' }) - @Delete('/:userId(\\d+)') + @Delete('/:userId') deleteUser(@Param('userId', ParseIntPipe) userId: number) { return this.authService.deleteUser(userId) } @@ -69,27 +69,27 @@ export class UsersController { @ApiOperation({ summary: 'Update the password for the current user.' }) @ApiBody({ type: UserUpdatePasswordDto }) @Post('/change-password') - updateOwnPassword(@Req() req, @Body() body: UserUpdatePasswordDto) { + updateOwnPassword(@Request() req, @Body() body: UserUpdatePasswordDto) { return this.authService.updateOwnPassword(req.user.username, body.currentPassword, body.newPassword) } @ApiOperation({ summary: 'Start 2FA setup for the current user.' }) @Post('/otp/setup') - setupOtp(@Req() req) { + setupOtp(@Request() req) { return this.authService.setupOtp(req.user.username) } @ApiOperation({ summary: 'Activate 2FA setup for the current user.' }) @ApiBody({ type: UserActivateOtpDto }) @Post('/otp/activate') - activateOtp(@Req() req, @Body() body: UserActivateOtpDto) { + activateOtp(@Request() req, @Body() body: UserActivateOtpDto) { return this.authService.activateOtp(req.user.username, body.code) } @ApiOperation({ summary: 'Deactivate 2FA setup for the current user.' }) @ApiBody({ type: UserDeactivateOtpDto }) @Post('/otp/deactivate') - deactivateOtp(@Req() req, @Body() body: UserDeactivateOtpDto) { + deactivateOtp(@Request() req, @Body() body: UserDeactivateOtpDto) { return this.authService.deactivateOtp(req.user.username, body.password) } }