From 01c0d34230f92c09548db1cdb11c8bb91108bf75 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Mon, 2 Dec 2024 13:51:45 +0930 Subject: [PATCH 01/23] refactor(spie-ui): move icons loading to app component --- apps/spie-ui/src/app/app.component.ts | 20 ++++++++++++++++++- .../src/app/pages/home/home.component.ts | 16 --------------- .../update-modal/update-modal.component.ts | 4 ++-- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/apps/spie-ui/src/app/app.component.ts b/apps/spie-ui/src/app/app.component.ts index f64be71..5fced85 100644 --- a/apps/spie-ui/src/app/app.component.ts +++ b/apps/spie-ui/src/app/app.component.ts @@ -1,5 +1,14 @@ import { Component } from '@angular/core'; import { IonApp, IonRouterOutlet } from '@ionic/angular/standalone'; +import { addIcons } from 'ionicons'; +import { + cloudUploadOutline, + documentOutline, + settingsOutline, + speedometerOutline, + statsChartOutline, + timeOutline, +} from 'ionicons/icons'; @Component({ selector: 'app-root', @@ -8,4 +17,13 @@ import { IonApp, IonRouterOutlet } from '@ionic/angular/standalone'; standalone: true, imports: [IonApp, IonRouterOutlet], }) -export class AppComponent {} +export class AppComponent { + constructor() { + addIcons({ settingsOutline }); + addIcons({ documentOutline }); + addIcons({ cloudUploadOutline }); + addIcons({ speedometerOutline }); + addIcons({ statsChartOutline }); + addIcons({ timeOutline }); + } +} diff --git a/apps/spie-ui/src/app/pages/home/home.component.ts b/apps/spie-ui/src/app/pages/home/home.component.ts index 6c6ccf2..ab312e4 100644 --- a/apps/spie-ui/src/app/pages/home/home.component.ts +++ b/apps/spie-ui/src/app/pages/home/home.component.ts @@ -15,15 +15,6 @@ import { } from '@ionic/angular/standalone'; import { type OpenOptions } from '@serialport/bindings-interface'; import { type SerialPortEvent } from '@spie/types'; -import { addIcons } from 'ionicons'; -import { - cloudUploadOutline, - documentOutline, - settingsOutline, - speedometerOutline, - statsChartOutline, - timeOutline, -} from 'ionicons/icons'; import { Subject, filter, @@ -70,13 +61,6 @@ export class HomeComponent { private readonly electronService = inject(ElectronService); constructor() { - addIcons({ settingsOutline }); - addIcons({ documentOutline }); - addIcons({ cloudUploadOutline }); - addIcons({ speedometerOutline }); - addIcons({ statsChartOutline }); - addIcons({ timeOutline }); - this.reconnectSubject .pipe( takeUntilDestroyed(), diff --git a/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts b/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts index 2523c2f..db673fc 100644 --- a/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts +++ b/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts @@ -38,10 +38,10 @@ import { type ProgressInfo } from 'electron-updater'; ], }) export class UpdateModalComponent { - updateModal = viewChild.required('updateModal'); - progressInfo = input.required(); + updateModal = viewChild.required('updateModal'); + formatBytes(bytes: number, decimals = 2): string { if (bytes === 0) return '0 Bytes'; const k = 1024; From 4966721687f5848ce8cbb876d69a356ad55efcc5 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Mon, 2 Dec 2024 22:04:46 +0930 Subject: [PATCH 02/23] refactor(spie-ui): create serial port service --- apps/spie-ui-e2e/src/e2e/updater.ts | 201 ++++++++++++ apps/spie-ui/src/app/app.component.ts | 4 +- .../connection-advanced-modal.component.ts | 8 +- .../home/connection/connection.component.html | 5 +- .../home/connection/connection.component.ts | 53 +++- .../src/app/pages/home/home.component.html | 20 +- .../src/app/pages/home/home.component.ts | 299 +----------------- .../send-advanced-modal.component.ts | 8 +- .../app/pages/home/send/send.component.html | 2 +- .../src/app/pages/home/send/send.component.ts | 9 +- .../terminal-advanced-modal.component.ts | 20 +- .../home/terminal/terminal.component.html | 5 +- .../pages/home/terminal/terminal.component.ts | 33 +- .../update-modal/update-modal.component.ts | 116 ++++++- .../src/app/services/serial-port.service.ts | 133 ++++++++ 15 files changed, 544 insertions(+), 372 deletions(-) create mode 100644 apps/spie-ui-e2e/src/e2e/updater.ts create mode 100644 apps/spie-ui/src/app/services/serial-port.service.ts diff --git a/apps/spie-ui-e2e/src/e2e/updater.ts b/apps/spie-ui-e2e/src/e2e/updater.ts new file mode 100644 index 0000000..e91c231 --- /dev/null +++ b/apps/spie-ui-e2e/src/e2e/updater.ts @@ -0,0 +1,201 @@ +import { type SerialPortEvent } from '@spie/types'; + +import { mockElectronAPI } from '../fixtures/mocks/electron-api.mock'; + +describe('Send component', () => { + const mockSerialPortList = [ + { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, + { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, + ]; + + let onEventTrigger: ((event: SerialPortEvent) => void) | null; + + beforeEach(() => { + cy.visit('/'); + + cy.on('window:before:load', (win) => { + const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; + + win.electron = mockElectronAPI(); + win.electron.serialPort.list = cy.stub().resolves(mockSerialPortList); + + win.electron.serialPort.onEvent = cy + .stub() + .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { + listeners.push(callback); + + onEventTrigger = (serialPortEvent) => { + listeners.forEach((listener) => listener(serialPortEvent)); + }; + + return () => { + const index = listeners.indexOf(callback); + if (index !== -1) { + listeners.splice(index, 1); + } + }; + }); + }); + }); + + it('should enable/disable send based on serial port status', () => { + const data = 'test test test test test test test test test test'; + + cy.wrap(null).then(() => { + if (onEventTrigger) { + onEventTrigger({ event: 'open' }); + } + }); + + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + + cy.get('app-send ion-button') + .contains('Send') + .should('not.have.class', 'button-disabled'); + + cy.wrap(null).then(() => { + if (onEventTrigger) { + onEventTrigger({ event: 'close' }); + } + }); + + cy.get('app-send ion-button') + .contains('Send') + .should('have.class', 'button-disabled'); + }); + + it('should clear input after pressing clear input button', () => { + const data = 'test test test test test test test test test test'; + + cy.wrap(null).then(() => { + if (onEventTrigger) { + onEventTrigger({ event: 'open' }); + } + }); + + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + cy.get('app-send ion-input button').click(); + + cy.get('app-send ion-input input').should('have.value', ''); + }); + + it('should send input with default options', () => { + const data = 'test test test test test test test test test test'; + const formattedData = `${data}\n`; + + cy.wrap(null).then(() => { + if (onEventTrigger) { + onEventTrigger({ event: 'open' }); + } + }); + + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + + cy.get('app-send ion-button').contains('Send').click(); + + cy.window().then((win) => { + cy.wrap(win.electron.serialPort.write).should( + 'have.been.calledOnceWithExactly', + formattedData, + 'ascii' + ); + }); + }); + + it('should open and close the advanced modal', () => { + cy.get('app-send ion-button ion-icon').parent().click(); + cy.get('ion-modal').should('be.visible'); + cy.get('ion-modal ion-toolbar ion-button').click(); + cy.get('ion-modal').should('not.be.visible'); + }); + + it('should clear input after changing encoding', () => { + const data = 'test test test test test test test test test test'; + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + + cy.get('app-send ion-button ion-icon').parent().click(); + cy.getAdvancedModalSelectElement( + 'send-advanced-modal', + 'Encoding' + ).selectOption('Hex'); + cy.get('ion-modal ion-toolbar ion-button').click(); + + cy.get('app-send ion-input input').should('have.value', ''); + }); + + it('should format hex input', () => { + const data = 'test test test test test test test test test test'; + const expectedHexData = 'EE EE EE EE EE'; + + cy.get('app-send ion-button ion-icon').parent().click(); + cy.getAdvancedModalSelectElement( + 'send-advanced-modal', + 'Encoding' + ).selectOption('Hex'); + cy.get('ion-modal ion-toolbar ion-button').click(); + + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + + cy.get('app-send ion-input input').should('have.value', expectedHexData); + }); + + it('should send input with hex encoding', () => { + const data = 'test test test test test test test test test test\n\n\n'; + const formattedData = 'EEEEEEEEEE'; + + cy.get('app-send ion-button ion-icon').parent().click(); + cy.getAdvancedModalSelectElement( + 'send-advanced-modal', + 'Encoding' + ).selectOption('Hex'); + cy.get('ion-modal ion-toolbar ion-button').click(); + + cy.wrap(null).then(() => { + if (onEventTrigger) { + onEventTrigger({ event: 'open' }); + } + }); + + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + + cy.get('app-send ion-button').contains('Send').click(); + + cy.window().then((win) => { + cy.wrap(win.electron.serialPort.write).should( + 'have.been.calledOnceWithExactly', + formattedData, + 'hex' + ); + }); + }); + + it('should send input with advanced delimiter', () => { + const data = 'test test test test test test test test test test'; + const formattedData = `${data}\r\n`; + + cy.get('app-send ion-button ion-icon').parent().click(); + cy.getAdvancedModalSelectElement( + 'send-advanced-modal', + 'Delimiter' + ).selectOption('CRLF (\\r\\n)'); + cy.get('ion-modal ion-toolbar ion-button').click(); + + cy.wrap(null).then(() => { + if (onEventTrigger) { + onEventTrigger({ event: 'open' }); + } + }); + + cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + + cy.get('app-send ion-button').contains('Send').click(); + + cy.window().then((win) => { + cy.wrap(win.electron.serialPort.write).should( + 'have.been.calledOnceWithExactly', + formattedData, + 'ascii' + ); + }); + }); +}); diff --git a/apps/spie-ui/src/app/app.component.ts b/apps/spie-ui/src/app/app.component.ts index 5fced85..14a6860 100644 --- a/apps/spie-ui/src/app/app.component.ts +++ b/apps/spie-ui/src/app/app.component.ts @@ -19,9 +19,9 @@ import { }) export class AppComponent { constructor() { - addIcons({ settingsOutline }); - addIcons({ documentOutline }); addIcons({ cloudUploadOutline }); + addIcons({ documentOutline }); + addIcons({ settingsOutline }); addIcons({ speedometerOutline }); addIcons({ statsChartOutline }); addIcons({ timeOutline }); diff --git a/apps/spie-ui/src/app/pages/home/connection/connection-advanced-modal/connection-advanced-modal.component.ts b/apps/spie-ui/src/app/pages/home/connection/connection-advanced-modal/connection-advanced-modal.component.ts index 89a32c0..7ec5e93 100644 --- a/apps/spie-ui/src/app/pages/home/connection/connection-advanced-modal/connection-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/pages/home/connection/connection-advanced-modal/connection-advanced-modal.component.ts @@ -1,4 +1,4 @@ -import { Component, input, model, viewChild } from '@angular/core'; +import { Component, inject, input, viewChild } from '@angular/core'; import { IonButton, IonButtons, @@ -13,13 +13,13 @@ import { IonTitle, IonToolbar, } from '@ionic/angular/standalone'; -import { type OpenOptions } from '@serialport/bindings-interface'; import { type Subject } from 'rxjs'; import { type CheckboxCustomEvent, type SelectCustomEvent, } from '../../../../interfaces/ionic.interface'; +import { SerialPortService } from '../../../../services/serial-port.service'; @Component({ selector: 'app-connection-advanced-modal', @@ -42,8 +42,10 @@ import { ], }) export class ConnectionAdvancedComponent { + private readonly serialPortService = inject(SerialPortService); + reconnectSubject = input.required>(); - openOptions = model.required(); + openOptions = this.serialPortService.openOptions; connectionAdvancedModal = viewChild.required( 'connectionAdvancedModal' diff --git a/apps/spie-ui/src/app/pages/home/connection/connection.component.html b/apps/spie-ui/src/app/pages/home/connection/connection.component.html index 5595e27..81dd7ee 100644 --- a/apps/spie-ui/src/app/pages/home/connection/connection.component.html +++ b/apps/spie-ui/src/app/pages/home/connection/connection.component.html @@ -69,8 +69,5 @@ - + diff --git a/apps/spie-ui/src/app/pages/home/connection/connection.component.ts b/apps/spie-ui/src/app/pages/home/connection/connection.component.ts index 5c914ed..f1ee258 100644 --- a/apps/spie-ui/src/app/pages/home/connection/connection.component.ts +++ b/apps/spie-ui/src/app/pages/home/connection/connection.component.ts @@ -1,11 +1,5 @@ -import { - Component, - inject, - input, - model, - signal, - viewChild, -} from '@angular/core'; +import { Component, inject, signal, viewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { IonButton, IonCard, @@ -20,15 +14,13 @@ import { IonText, LoadingController, } from '@ionic/angular/standalone'; -import { - type OpenOptions, - type PortInfo, -} from '@serialport/bindings-interface'; -import { type Subject } from 'rxjs'; +import { type PortInfo } from '@serialport/bindings-interface'; +import { Subject, tap } from 'rxjs'; import { ConnectionAdvancedComponent } from './connection-advanced-modal/connection-advanced-modal.component'; import { type SelectCustomEvent } from '../../../interfaces/ionic.interface'; import { ElectronService } from '../../../services/electron.service'; +import { SerialPortService } from '../../../services/serial-port.service'; import { ToasterService } from '../../../services/toaster.service'; @Component({ @@ -55,10 +47,37 @@ export class ConnectionComponent { private readonly loadingController = inject(LoadingController); private readonly toasterService = inject(ToasterService); private readonly electronService = inject(ElectronService); + private readonly serialPortService = inject(SerialPortService); + + constructor() { + this.reconnectSubject + .pipe( + takeUntilDestroyed(), + + tap(async () => { + if (this.isOpen()) { + const loading = await this.loadingController.create(); + await loading.present(); + try { + await this.electronService.serialPort.close(); + await this.electronService.serialPort.open(this.openOptions()); + this.serialPortService.clearDataSubject.next({ + event: 'data', + data: '', + }); + } catch (error) { + await this.toasterService.presentErrorToast(error); + } + await loading.dismiss(); + } + }) + ) + .subscribe(); + } - reconnectSubject = input.required>(); - isOpen = input.required(); - openOptions = model.required(); + isOpen = this.serialPortService.isOpen; + openOptions = this.serialPortService.openOptions; + reconnectSubject = new Subject(); private connectionAdvancedComponent = viewChild.required( ConnectionAdvancedComponent @@ -111,7 +130,7 @@ export class ConnectionComponent { baudRate: parseInt(selectedOption, 10), })); - this.reconnectSubject().next(); + this.reconnectSubject.next(); } async onClickDisconnect(): Promise { diff --git a/apps/spie-ui/src/app/pages/home/home.component.html b/apps/spie-ui/src/app/pages/home/home.component.html index 6493f6b..4fa7c2f 100644 --- a/apps/spie-ui/src/app/pages/home/home.component.html +++ b/apps/spie-ui/src/app/pages/home/home.component.html @@ -5,22 +5,10 @@ - - - - - - - - + + + + diff --git a/apps/spie-ui/src/app/pages/home/home.component.scss b/apps/spie-ui/src/app/components/plotter/plotter.component.scss similarity index 100% rename from apps/spie-ui/src/app/pages/home/home.component.scss rename to apps/spie-ui/src/app/components/plotter/plotter.component.scss diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts new file mode 100644 index 0000000..9ce091c --- /dev/null +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -0,0 +1,247 @@ +import { Component, computed, inject, signal, viewChild } from '@angular/core'; +import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; +import { + IonButton, + IonCard, + IonCardContent, + IonCardHeader, + IonCol, + IonGrid, + IonIcon, + IonRow, + IonText, +} from '@ionic/angular/standalone'; +import { + type ApexChart, + type ApexDataLabels, + type ApexGrid, + type ApexStroke, + type ApexTooltip, + type ApexXAxis, + type ApexYAxis, + type ChartComponent, + NgApexchartsModule, +} from 'ng-apexcharts'; +import { BehaviorSubject, Subject, filter, map, merge, tap } from 'rxjs'; + +import { + type DataEvent, + SerialPortService, +} from '../../services/serial-port.service'; + +interface ChartOptions { + dataLabels: ApexDataLabels; + yaxis: ApexYAxis; + xaxis: ApexXAxis; + grid: ApexGrid; + stroke: ApexStroke; +} + +@Component({ + selector: 'app-plotter-component', + templateUrl: 'plotter.component.html', + styleUrls: ['./plotter.component.scss'], + standalone: true, + imports: [ + IonButton, + IonCard, + IonCardContent, + IonCardHeader, + IonCol, + IonGrid, + IonIcon, + IonRow, + IonText, + NgApexchartsModule, + ], +}) +export class PlotterComponent { + private readonly serialPortService = inject(SerialPortService); + + constructor() { + this.dataEvent$.subscribe(); + } + + chartArea = viewChild.required('chartObj'); + + clearSeriesSubject = new Subject(); + isOpen = this.serialPortService.isOpen; + private dataEvent$ = merge( + this.serialPortService.dataEvent$.pipe( + filter(() => !this.isDataEventPausedSubject.getValue()) + ), + this.clearSeriesSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) + ).pipe( + tap((dataEvent) => { + if (dataEvent.type === 'clear') { + // Clear series + this.series.set([]); + return; + } + + const data = dataEvent.data; + const isDataTruncated = data.split('\n').length - 1 > 1; + if (isDataTruncated) { + console.warn('data truncated:'); + return; + } + + // Detect separator + const detectedSeparator = this.detectSeparator(data); + + // Split values + const values = detectedSeparator + ? data.split(detectedSeparator).map((v) => parseFloat(v)) + : [parseFloat(data)]; + + // Update series with the correct amount of variables + if (this.series().length !== values.length) { + const newSeries = values.map((value, index) => ({ + name: `Variable ${index + 1}`, + data: [{ x: Date.now(), y: value }], + })); + + this.series.set(newSeries); + return; + } + + let variableData: { x: number; y: number }[][] = []; + + // Initialize variableData for the first time based on the number of variables + if (variableData.length === 0) { + variableData = Array.from({ length: values.length }, () => []); + } + + // Populate data points for each variable + values.forEach((value, variableIndex) => { + variableData[variableIndex].push({ + x: Date.now(), + y: value, + }); + }); + + // TODO: plotter options scrollbackLength + const scrollbackLength = 1000; + + // Slice series based on scrollbackLength + if (this.series()[0].data.length > scrollbackLength) { + this.series.update((series) => { + return series.map((variable) => { + const data = variable.data as { x: any; y: any }[]; + const truncatedData = data.slice(1); + + return { ...variable, data: truncatedData }; + }); + }); + } + + // Update series + this.series.update((series) => { + return series.map((variable, index) => { + const data = variable.data as { x: any; y: any }[]; + const updatedData = [...data, variableData[index][0]]; + + return { ...variable, data: updatedData }; + }); + }); + }), + takeUntilDestroyed() + ); + series = signal([]); + + isDataEventPausedSubject = new BehaviorSubject(false); + private isDataEventPaused = toSignal(this.isDataEventPausedSubject, { + initialValue: false, + }); + + private detectSeparator(line: string): string { + if (line.includes('\t')) return '\t'; + if (line.includes(',')) return ','; + if (line.includes(' ')) return ' '; + return ''; + } + + chart = computed(() => { + return { + type: 'line', + animations: { + enabled: false, + }, + zoom: { + enabled: this.isDataEventPaused(), + }, + }; + }); + + tooltip = computed(() => { + return { + enabled: this.isDataEventPaused(), + x: { + show: true, + // format: 'dd/MM/yy HH:mm:ss:fff', // milliseconds is not working here + formatter: (timestamp: number) => { + const date = new Date(timestamp); + + const day = String(date.getDate()).padStart(2, '0'); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const year = String(date.getFullYear()).slice(-2); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); + + return `${day}/${month}/${year} ${hours}:${minutes}:${seconds}:${milliseconds}`; + }, + }, + }; + }); + + chartOptions: ChartOptions = { + dataLabels: { + enabled: false, + }, + yaxis: { + // axisTicks: { + // show: false, + // }, + }, + xaxis: { + type: 'datetime', + // axisTicks: { + // show: false, + // }, + }, + grid: { + show: true, + strokeDashArray: 2, + xaxis: { + lines: { + show: true, + }, + }, + yaxis: { + lines: { + show: true, + }, + }, + }, + stroke: { + show: true, + curve: 'straight', + width: 2, + }, + }; + + onClickClearTerminal(): void { + this.clearSeriesSubject.next(); + } + + onClickPauseTerminal(): void { + const currentValue = this.isDataEventPausedSubject.getValue(); + this.isDataEventPausedSubject.next(!currentValue); + } + + async onClickTerminalAdvancedModal() { + // this.terminalAdvancedComponent().terminalAdvancedModal().present(); // TODO + } +} diff --git a/apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.html b/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.html similarity index 100% rename from apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.html rename to apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.html diff --git a/apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.scss b/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.scss similarity index 100% rename from apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.scss rename to apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.scss diff --git a/apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.ts b/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts similarity index 76% rename from apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.ts rename to apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts index 196ffa0..53518d0 100644 --- a/apps/spie-ui/src/app/pages/home/send/send-advanced-modal/send-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts @@ -14,11 +14,11 @@ import { } from '@ionic/angular/standalone'; import { type Delimiter, type Encoding } from '@spie/types'; -import { type SelectCustomEvent } from '../../../../interfaces/ionic.interface'; -import { SerialPortService } from '../../../../services/serial-port.service'; +import { type SelectCustomEvent } from '../../interfaces/ionic.interface'; +import { SerialPortService } from '../../services/serial-port.service'; @Component({ - selector: 'app-send-advanced-modal', + selector: 'app-send-advanced-modal-component', templateUrl: 'send-advanced-modal.component.html', styleUrls: ['./send-advanced-modal.component.scss'], standalone: true, @@ -45,16 +45,16 @@ export class SendAdvancedComponent { onChangeSendEncoding(event: SelectCustomEvent): void { const selectedOption = event.detail.value; - this.sendOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.sendOptions.update((sendOptions) => ({ + ...sendOptions, encoding: selectedOption, })); } onChangeDelimiter(event: SelectCustomEvent): void { const selectedOption = event.detail.value; - this.sendOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.sendOptions.update((sendOptions) => ({ + ...sendOptions, delimiter: selectedOption, })); } diff --git a/apps/spie-ui/src/app/components/send/send.component.html b/apps/spie-ui/src/app/components/send/send.component.html new file mode 100644 index 0000000..ca3b94f --- /dev/null +++ b/apps/spie-ui/src/app/components/send/send.component.html @@ -0,0 +1,45 @@ + + + Send + + + + + + + + + + + + + Clear Send + + + + + + + + + + + + + diff --git a/apps/spie-ui/src/app/pages/home/send/send.component.scss b/apps/spie-ui/src/app/components/send/send.component.scss similarity index 100% rename from apps/spie-ui/src/app/pages/home/send/send.component.scss rename to apps/spie-ui/src/app/components/send/send.component.scss diff --git a/apps/spie-ui/src/app/pages/home/send/send.component.ts b/apps/spie-ui/src/app/components/send/send.component.ts similarity index 83% rename from apps/spie-ui/src/app/pages/home/send/send.component.ts rename to apps/spie-ui/src/app/components/send/send.component.ts index 85b9de1..8e81568 100644 --- a/apps/spie-ui/src/app/pages/home/send/send.component.ts +++ b/apps/spie-ui/src/app/components/send/send.component.ts @@ -3,6 +3,7 @@ import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; import { IonButton, IonCard, + IonCardContent, IonCardHeader, IonCol, IonGrid, @@ -15,20 +16,21 @@ import { import { type Delimiter } from '@spie/types'; import { scan } from 'rxjs'; -import { SendAdvancedComponent } from './send-advanced-modal/send-advanced-modal.component'; -import { type IonInputCustomEvent } from '../../../interfaces/ionic.interface'; -import { ElectronService } from '../../../services/electron.service'; -import { SerialPortService } from '../../../services/serial-port.service'; -import { ToasterService } from '../../../services/toaster.service'; +import { type IonInputCustomEvent } from '../../interfaces/ionic.interface'; +import { ElectronService } from '../../services/electron.service'; +import { SerialPortService } from '../../services/serial-port.service'; +import { ToasterService } from '../../services/toaster.service'; +import { SendAdvancedComponent } from '../send-advanced-modal/send-advanced-modal.component'; @Component({ - selector: 'app-send', + selector: 'app-send-component', templateUrl: 'send.component.html', styleUrls: ['./send.component.scss'], standalone: true, imports: [ IonButton, IonCard, + IonCardContent, IonCardHeader, IonCol, IonGrid, @@ -106,16 +108,16 @@ export class SendComponent { onChangeSendInput(event: IonInputCustomEvent): void { const inputValue = event.detail.value; if (!inputValue) { - this.sendOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.sendOptions.update((sendOptions) => ({ + ...sendOptions, isSendInputValid: false, })); return; } if (this.sendOptions().encoding !== 'hex') { - this.sendOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.sendOptions.update((sendOptions) => ({ + ...sendOptions, isSendInputValid: true, })); return; @@ -129,8 +131,8 @@ export class SendComponent { ?.join(' ') ?? ''; event.target.value = formattedHexValue; const isEvenLength = formattedHexValue.replace(/\s+/g, '').length % 2 === 0; - this.sendOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.sendOptions.update((sendOptions) => ({ + ...sendOptions, isSendInputValid: isEvenLength, })); } diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.html b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html similarity index 100% rename from apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.html rename to apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.scss b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.scss similarity index 100% rename from apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.scss rename to apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.scss diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.ts b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts similarity index 65% rename from apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.ts rename to apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts index 301a92d..8315442 100644 --- a/apps/spie-ui/src/app/pages/home/terminal/terminal-advanced-modal/terminal-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts @@ -1,4 +1,4 @@ -import { Component, inject, viewChild } from '@angular/core'; +import { Component, inject, input, viewChild } from '@angular/core'; import { IonButton, IonButtons, @@ -15,17 +15,18 @@ import { IonToolbar, } from '@ionic/angular/standalone'; import { type Encoding } from '@spie/types'; +import { type Subject } from 'rxjs'; import { type CheckboxCustomEvent, type RangeCustomEvent, type SelectCustomEvent, -} from '../../../../interfaces/ionic.interface'; -import { ElectronService } from '../../../../services/electron.service'; -import { SerialPortService } from '../../../../services/serial-port.service'; +} from '../../interfaces/ionic.interface'; +import { ElectronService } from '../../services/electron.service'; +import { SerialPortService } from '../../services/serial-port.service'; @Component({ - selector: 'app-terminal-advanced-modal', + selector: 'app-terminal-advanced-modal-component', templateUrl: 'terminal-advanced-modal.component.html', styleUrls: ['./terminal-advanced-modal.component.scss'], standalone: true, @@ -49,49 +50,49 @@ export class TerminalAdvancedComponent { private readonly electronService = inject(ElectronService); private readonly serialPortService = inject(SerialPortService); - clearDataSubject = this.serialPortService.clearDataSubject; + clearTerminalSubject = input.required>(); terminalOptions = this.serialPortService.terminalOptions; terminalAdvancedModal = viewChild.required('terminalAdvancedModal'); onChangeTerminalEncoding(event: SelectCustomEvent): void { const selectedOption = event.detail.value; - this.terminalOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.terminalOptions.update((terminalOptions) => ({ + ...terminalOptions, encoding: selectedOption, })); this.electronService.serialPort.setReadEncoding(selectedOption); - this.clearDataSubject.next({ event: 'data', data: '' }); + this.clearTerminalSubject().next(); } onChangeShowTimestamps(event: CheckboxCustomEvent): void { const selectedOption = event.detail.checked; - this.terminalOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.terminalOptions.update((terminalOptions) => ({ + ...terminalOptions, showTimestampsEnabled: selectedOption, })); - this.clearDataSubject.next({ event: 'data', data: '' }); + this.clearTerminalSubject().next(); } onChangeAutoScroll(event: CheckboxCustomEvent): void { const selectedOption = event.detail.checked; - this.terminalOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.terminalOptions.update((terminalOptions) => ({ + ...terminalOptions, isAutoScrollEnabled: selectedOption, })); - // this.clearDataSubject.next({ event: 'data', data: '' }); + // this.clearTerminalSubject().next(); } onScrollbackLength(event: RangeCustomEvent): void { const selectedOption = event.detail.value as number; - this.terminalOptions.update((currentOpenOptions) => ({ - ...currentOpenOptions, + this.terminalOptions.update((terminalOptions) => ({ + ...terminalOptions, scrollbackLength: selectedOption, })); - // this.clearDataSubject.next({ event: 'data', data: '' }); + // this.clearTerminalSubject().next(); } pinFormatter(value: number): string { diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.html b/apps/spie-ui/src/app/components/terminal/terminal.component.html new file mode 100644 index 0000000..2e67c45 --- /dev/null +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.html @@ -0,0 +1,73 @@ + + + Terminal + + + + + + + + + + + + + {{ + isDataEventPausedSubject.getValue() && isOpen() + ? 'Continue' + : 'Pause' + }} + + + + + + + Clear + + + + + + + + + + + + + diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.component.scss b/apps/spie-ui/src/app/components/terminal/terminal.component.scss similarity index 100% rename from apps/spie-ui/src/app/pages/home/terminal/terminal.component.scss rename to apps/spie-ui/src/app/components/terminal/terminal.component.scss diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.ts b/apps/spie-ui/src/app/components/terminal/terminal.component.ts new file mode 100644 index 0000000..811c375 --- /dev/null +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.ts @@ -0,0 +1,146 @@ +import { Component, inject, signal, viewChild } from '@angular/core'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { + IonButton, + IonCard, + IonCardContent, + IonCardHeader, + IonCol, + IonGrid, + IonIcon, + IonItem, + IonRow, + IonText, + IonTextarea, +} from '@ionic/angular/standalone'; +import { BehaviorSubject, Subject, filter, map, merge, tap } from 'rxjs'; + +import { ElectronService } from '../../services/electron.service'; +import { + type DataEvent, + SerialPortService, +} from '../../services/serial-port.service'; +import { TerminalAdvancedComponent } from '../terminal-advanced-modal/terminal-advanced-modal.component'; + +@Component({ + selector: 'app-terminal-component', + templateUrl: 'terminal.component.html', + styleUrls: ['./terminal.component.scss'], + standalone: true, + imports: [ + IonButton, + IonCard, + IonCardContent, + IonCardHeader, + IonCol, + IonGrid, + IonIcon, + IonItem, + IonRow, + IonText, + IonTextarea, + TerminalAdvancedComponent, + ], +}) +export class TerminalComponent { + private readonly serialPortService = inject(SerialPortService); + private readonly electronService = inject(ElectronService); + + constructor() { + // Retrieve previous readEncoding (useful for development) + this.electronService.serialPort.getReadEncoding().then((readEncoding) => { + this.terminalOptions.update((terminalOptions) => ({ + ...terminalOptions, + encoding: readEncoding, + })); + }); + + this.dataEvent$.subscribe(); + } + + clearTerminalSubject = new Subject(); + isOpen = this.serialPortService.isOpen; + terminalOptions = this.serialPortService.terminalOptions; + private dataEvent$ = merge( + this.serialPortService.dataEvent$.pipe( + filter(() => !this.isDataEventPausedSubject.getValue()) + ), + this.clearTerminalSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) + ).pipe( + tap(async (dataEvent) => { + if (dataEvent.type === 'clear') { + this.data.set(''); + return; + } + + const data = dataEvent.data; + const isDataTruncated = data.split('\n').length - 1 > 1; + if (isDataTruncated) { + console.warn('data truncated:'); + return; + } + + this.data.update((prevData) => { + // Append timestamp if it is enabled + if (this.terminalOptions().showTimestampsEnabled) { + const date = new Date(); + const hours = date.getHours().toString().padStart(2, '0'); + const minutes = date.getMinutes().toString().padStart(2, '0'); + const seconds = date.getSeconds().toString().padStart(2, '0'); + + prevData += `[${hours}:${minutes}:${seconds}] `; + } + + // Append data + prevData += `${data}`; + + // TODO: evaluate if this should also be done for ascii + // Append new line if hex encoding + if (this.terminalOptions().encoding === 'hex') { + prevData += '\n'; + } + + const excess = + prevData.length - this.terminalOptions().scrollbackLength * 10000; + + if (excess > 0) { + return prevData.slice(excess); + } + + return prevData; + }); + + // Apply autoscroll + const isAutoScrollEnabled = this.terminalOptions().isAutoScrollEnabled; + if (isAutoScrollEnabled) { + const terminalTextArea = this.terminalTextArea(); + const textarea = await terminalTextArea.getInputElement(); + textarea.scrollTo({ + top: textarea.scrollHeight, + behavior: 'instant', + }); + } + }), + takeUntilDestroyed() + ); + data = signal(''); + isDataEventPausedSubject = new BehaviorSubject(false); + + terminalTextArea = viewChild.required('terminalTextArea'); + private terminalAdvancedComponent = viewChild.required( + TerminalAdvancedComponent + ); + + onClickClearTerminal(): void { + this.clearTerminalSubject.next(); + } + + onClickPauseTerminal(): void { + const currentValue = this.isDataEventPausedSubject.getValue(); + this.isDataEventPausedSubject.next(!currentValue); + } + + async onClickTerminalAdvancedModal() { + this.terminalAdvancedComponent().terminalAdvancedModal().present(); + } +} diff --git a/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.html b/apps/spie-ui/src/app/components/update-modal/update-modal.component.html similarity index 100% rename from apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.html rename to apps/spie-ui/src/app/components/update-modal/update-modal.component.html diff --git a/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.scss b/apps/spie-ui/src/app/components/update-modal/update-modal.component.scss similarity index 100% rename from apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.scss rename to apps/spie-ui/src/app/components/update-modal/update-modal.component.scss diff --git a/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts similarity index 94% rename from apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts rename to apps/spie-ui/src/app/components/update-modal/update-modal.component.ts index 012a5f8..1a3250e 100644 --- a/apps/spie-ui/src/app/pages/home/update-modal/update-modal.component.ts +++ b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts @@ -17,14 +17,15 @@ import { IonTitle, IonToolbar, } from '@ionic/angular/standalone'; +import { type ProgressInfo } from 'electron-updater'; import { of, switchMap, tap } from 'rxjs'; -import { ElectronService } from '../../../services/electron.service'; -import { ToasterService } from '../../../services/toaster.service'; +import { ElectronService } from '../../services/electron.service'; +import { ToasterService } from '../../services/toaster.service'; @Component({ selector: 'app-update-modal', - templateUrl: './update-modal.component.html', + templateUrl: 'update-modal.component.html', styleUrls: ['./update-modal.component.scss'], standalone: true, imports: [ @@ -133,7 +134,7 @@ export class UpdateModalComponent { transferred: 0, percent: 0, bytesPerSecond: 0, - }, + } as ProgressInfo, } ); diff --git a/apps/spie-ui/src/app/pages/home/connection/connection.component.html b/apps/spie-ui/src/app/pages/home/connection/connection.component.html deleted file mode 100644 index 81dd7ee..0000000 --- a/apps/spie-ui/src/app/pages/home/connection/connection.component.html +++ /dev/null @@ -1,73 +0,0 @@ - - - Connection - - - - - - - - @for (serialPort of serialPorts(); track $index) { - - {{ serialPort.path }} - {{ serialPort.manufacturer }} - - } - - - - - - - - @for (baudRate of baudRates; track $index) { - {{ - baudRate - }} - } - - - - - - - - @if (isOpen()) { - Disconnect - } @else { - Connect - } - - - - - - - - - - - diff --git a/apps/spie-ui/src/app/pages/home/home.component.html b/apps/spie-ui/src/app/pages/home/home.component.html deleted file mode 100644 index 4fa7c2f..0000000 --- a/apps/spie-ui/src/app/pages/home/home.component.html +++ /dev/null @@ -1,16 +0,0 @@ - - - Serial Monitor - - - - - - - - - - - diff --git a/apps/spie-ui/src/app/pages/home/home.component.ts b/apps/spie-ui/src/app/pages/home/home.component.ts deleted file mode 100644 index a204ca2..0000000 --- a/apps/spie-ui/src/app/pages/home/home.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component } from '@angular/core'; -import { - IonContent, - IonHeader, - IonTitle, - IonToolbar, -} from '@ionic/angular/standalone'; - -import { ConnectionComponent } from './connection/connection.component'; -import { SendComponent } from './send/send.component'; -import { TerminalComponent } from './terminal/terminal.component'; -import { UpdateModalComponent } from './update-modal/update-modal.component'; - -@Component({ - selector: 'app-home', - templateUrl: 'home.component.html', - styleUrls: ['./home.component.scss'], - standalone: true, - imports: [ - IonContent, - IonHeader, - IonTitle, - IonToolbar, - SendComponent, - ConnectionComponent, - TerminalComponent, - UpdateModalComponent, - ], -}) -export class HomeComponent {} diff --git a/apps/spie-ui/src/app/pages/home/home.page.html b/apps/spie-ui/src/app/pages/home/home.page.html new file mode 100644 index 0000000..b971d87 --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/home.page.html @@ -0,0 +1,17 @@ + + + + + + + Terminal + + + + + Plotter + + + + + diff --git a/apps/spie-ui/src/app/pages/home/home.page.scss b/apps/spie-ui/src/app/pages/home/home.page.scss new file mode 100644 index 0000000..e69de29 diff --git a/apps/spie-ui/src/app/pages/home/home.page.ts b/apps/spie-ui/src/app/pages/home/home.page.ts new file mode 100644 index 0000000..2de879f --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/home.page.ts @@ -0,0 +1,28 @@ +import { Component } from '@angular/core'; +import { + IonIcon, + IonLabel, + IonTabBar, + IonTabButton, + IonTabs, +} from '@ionic/angular/standalone'; + +import { ConnectionComponent } from '../../components/connection/connection.component'; +import { UpdateModalComponent } from '../../components/update-modal/update-modal.component'; + +@Component({ + selector: 'app-home', + templateUrl: 'home.page.html', + styleUrls: ['./home.page.scss'], + standalone: true, + imports: [ + IonIcon, + IonLabel, + IonTabBar, + IonTabButton, + IonTabs, + ConnectionComponent, + UpdateModalComponent, + ], +}) +export class HomePage {} diff --git a/apps/spie-ui/src/app/pages/home/home.routes.ts b/apps/spie-ui/src/app/pages/home/home.routes.ts new file mode 100644 index 0000000..529acee --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/home.routes.ts @@ -0,0 +1,37 @@ +import { type Routes } from '@angular/router'; + +import { HomePage } from './home.page'; + +export const routes: Routes = [ + { + path: '', + component: HomePage, + children: [ + { + path: 'terminal', + loadComponent: () => + import('./terminal/terminal.page').then((m) => m.TerminalPage), + }, + { + path: 'plotter', + loadComponent: () => + import('./plotter/plotter.page').then((m) => m.PlotterPage), + }, + { + path: '', + redirectTo: 'terminal', + pathMatch: 'full', + }, + { + path: '**', + redirectTo: '', + pathMatch: 'full', + }, + ], + }, + { + path: '**', + redirectTo: '', + pathMatch: 'full', + }, +]; diff --git a/apps/spie-ui/src/app/pages/home/plotter/plotter.page.html b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.html new file mode 100644 index 0000000..fb316d5 --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.html @@ -0,0 +1,9 @@ + + + Plotter + + + + + + diff --git a/apps/spie-ui/src/app/pages/home/plotter/plotter.page.scss b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.scss new file mode 100644 index 0000000..e69de29 diff --git a/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts new file mode 100644 index 0000000..388af27 --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; +import { + IonContent, + IonHeader, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; + +import { PlotterComponent } from '../../../components/plotter/plotter.component'; + +@Component({ + selector: 'app-plotter', + templateUrl: 'plotter.page.html', + styleUrls: ['./plotter.page.scss'], + standalone: true, + imports: [IonContent, IonHeader, IonTitle, IonToolbar, PlotterComponent], +}) +export class PlotterPage {} diff --git a/apps/spie-ui/src/app/pages/home/send/send.component.html b/apps/spie-ui/src/app/pages/home/send/send.component.html deleted file mode 100644 index 7dd546e..0000000 --- a/apps/spie-ui/src/app/pages/home/send/send.component.html +++ /dev/null @@ -1,41 +0,0 @@ - - - Send - - - - - - - - - - Send - - - - - - - - - - - diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.component.html b/apps/spie-ui/src/app/pages/home/terminal/terminal.component.html deleted file mode 100644 index f6b58c1..0000000 --- a/apps/spie-ui/src/app/pages/home/terminal/terminal.component.html +++ /dev/null @@ -1,40 +0,0 @@ - - - Terminal - - - - - - - - - - Clear Terminal - - - - - - - - - - - diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.component.ts b/apps/spie-ui/src/app/pages/home/terminal/terminal.component.ts deleted file mode 100644 index 3ffe3a1..0000000 --- a/apps/spie-ui/src/app/pages/home/terminal/terminal.component.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { Component, effect, inject, viewChild } from '@angular/core'; -import { - IonButton, - IonCard, - IonCardHeader, - IonCol, - IonGrid, - IonIcon, - IonItem, - IonRow, - IonText, - IonTextarea, -} from '@ionic/angular/standalone'; - -import { TerminalAdvancedComponent } from './terminal-advanced-modal/terminal-advanced-modal.component'; -import { SerialPortService } from '../../../services/serial-port.service'; - -@Component({ - selector: 'app-terminal', - templateUrl: 'terminal.component.html', - styleUrls: ['./terminal.component.scss'], - standalone: true, - imports: [ - IonButton, - IonCard, - IonCardHeader, - IonCol, - IonGrid, - IonIcon, - IonItem, - IonRow, - IonText, - IonTextarea, - TerminalAdvancedComponent, - ], -}) -export class TerminalComponent { - private readonly serialPortService = inject(SerialPortService); - - constructor() { - effect(async () => { - if (this.data() !== '') { - // Apply auto scroll - const isAutoScrollEnabled = this.terminalOptions().isAutoScrollEnabled; - if (isAutoScrollEnabled) { - const terminalTextArea = this.terminalTextArea(); - const textarea = await terminalTextArea.getInputElement(); - textarea.scrollTo({ - top: textarea.scrollHeight, - behavior: 'instant', - }); - } - } - }); - } - - clearDataSubject = this.serialPortService.clearDataSubject; - data = this.serialPortService.data; - terminalOptions = this.serialPortService.terminalOptions; - - terminalTextArea = viewChild.required('terminalTextArea'); - private terminalAdvancedComponent = viewChild.required( - TerminalAdvancedComponent - ); - - onClickClearTerminal(): void { - this.clearDataSubject.next({ event: 'data', data: '' }); - } - - async onClickTerminalAdvancedModal() { - this.terminalAdvancedComponent().terminalAdvancedModal().present(); - } -} diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.page.html b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.html new file mode 100644 index 0000000..9360848 --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.html @@ -0,0 +1,10 @@ + + + Terminal + + + + + + + diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.page.scss b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.scss new file mode 100644 index 0000000..e69de29 diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts new file mode 100644 index 0000000..b8e2e16 --- /dev/null +++ b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts @@ -0,0 +1,26 @@ +import { Component } from '@angular/core'; +import { + IonContent, + IonHeader, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; + +import { SendComponent } from '../../../components/send/send.component'; +import { TerminalComponent } from '../../../components/terminal/terminal.component'; + +@Component({ + selector: 'app-terminal', + templateUrl: 'terminal.page.html', + styleUrls: ['./terminal.page.scss'], + standalone: true, + imports: [ + IonContent, + IonHeader, + IonTitle, + IonToolbar, + SendComponent, + TerminalComponent, + ], +}) +export class TerminalPage {} diff --git a/apps/spie-ui/src/app/services/electron.service.ts b/apps/spie-ui/src/app/services/electron.service.ts index ea7473f..e265208 100644 --- a/apps/spie-ui/src/app/services/electron.service.ts +++ b/apps/spie-ui/src/app/services/electron.service.ts @@ -14,9 +14,7 @@ import { Observable } from 'rxjs'; providedIn: 'root', }) export class ElectronService { - getPlatform(): string { - return window.electron.platform; - } + platform = window.electron.platform; quit(code = 0): void { window.electron.quit(code); @@ -79,6 +77,14 @@ export class ElectronService { return window.electron.serialPort.setReadEncoding(encoding); } + getReadEncoding(): Promise { + return window.electron.serialPort.getReadEncoding(); + } + + getOpenOptions(): Promise { + return window.electron.serialPort.getOpenOptions(); + } + onEvent(): Observable { return new Observable((observer) => { const removeListener = window.electron.serialPort.onEvent((data) => { diff --git a/apps/spie-ui/src/app/services/serial-port.service.ts b/apps/spie-ui/src/app/services/serial-port.service.ts index e8b6d5b..fe6703a 100644 --- a/apps/spie-ui/src/app/services/serial-port.service.ts +++ b/apps/spie-ui/src/app/services/serial-port.service.ts @@ -1,8 +1,17 @@ import { Injectable, inject, signal } from '@angular/core'; import { toObservable, toSignal } from '@angular/core/rxjs-interop'; import { type OpenOptions } from '@serialport/bindings-interface'; -import { type SerialPortEvent } from '@spie/types'; -import { Subject, filter, from, map, merge, scan, switchMap } from 'rxjs'; +import { + type Observable, + Subject, + filter, + from, + map, + merge, + scan, + startWith, + switchMap, +} from 'rxjs'; import { ElectronService } from './electron.service'; import { @@ -43,23 +52,19 @@ export class SerialPortService { isSendInputValid: false, }); - clearDataSubject = new Subject(); + clearDataSubject = new Subject(); isOpen = toSignal( from(this.electronService.serialPort.isOpen()).pipe( switchMap((isOpen) => this.electronService.serialPort.onEvent().pipe( - filter( - (serialPortEvent) => - serialPortEvent.event === 'close' || - serialPortEvent.event === 'open' - ), + startWith({ type: isOpen ? 'open' : 'close' }), scan((currentIsOpen, serialPortEvent) => { - if (serialPortEvent.event === 'open') { + if (serialPortEvent.type === 'open') { return true; } - if (serialPortEvent.event === 'close') { + if (serialPortEvent.type === 'close') { return false; } @@ -71,63 +76,23 @@ export class SerialPortService { { initialValue: false } ); - data = toSignal( - toObservable(this.isOpen).pipe( - switchMap(() => - merge( - // Emissions to this.isOpen will resubscribe these - this.electronService.serialPort.onEvent(), - this.clearDataSubject - ) - ), - filter((serialPortEvent) => serialPortEvent.event === 'data'), - map((serialPortEvent) => { - const data = serialPortEvent.data; - // If data it a "clear terminal" signal - if (data === '') { - return ''; - } - - if (this.terminalOptions().showTimestampsEnabled) { - const date = new Date(); - const hours = date.getHours().toString().padStart(2, '0'); - const minutes = date.getMinutes().toString().padStart(2, '0'); - const seconds = date.getSeconds().toString().padStart(2, '0'); - return `[${hours}:${minutes}:${seconds}] ${data}`; - } - - return data; - }), - scan( - (acc, value) => { - // Reset on empty string - if (value === '') { - return { items: [] as string[], length: 0 }; - } - - acc.items.push(value); - acc.length += value.length; - const maxLength = this.terminalOptions().scrollbackLength * 10000; - - while (acc.length > maxLength) { - const removed = acc.items.shift(); - if (removed) { - acc.length -= removed.length; - } - } - - return acc; - }, - { items: [] as string[], length: 0 } - ), - map((buffer) => { - if (this.terminalOptions().encoding === 'hex') { - return buffer.items.join('\n'); - } - - return buffer.items.join(''); - }) + dataEvent$: Observable = toObservable(this.isOpen).pipe( + switchMap(() => + merge( + this.electronService.serialPort.onEvent(), + this.clearDataSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) + ) ), - { initialValue: '' } + filter( + (serialPortEvent) => + serialPortEvent.type === 'data' || serialPortEvent.type === 'clear' + ) ); } + +export type DataEvent = + | { + type: 'data'; + data: string; + } + | { type: 'clear' }; diff --git a/apps/spie/src/app/api/main.preload.ts b/apps/spie/src/app/api/main.preload.ts index be46e72..a3eb918 100644 --- a/apps/spie/src/app/api/main.preload.ts +++ b/apps/spie/src/app/api/main.preload.ts @@ -37,6 +37,8 @@ export const electronAPI: ElectronAPI = { isOpen: () => ipcRenderer.invoke('serial-port-is-open'), setReadEncoding: (encoding: Encoding) => ipcRenderer.invoke('serial-port-set-read-encoding', encoding), + getReadEncoding: () => ipcRenderer.invoke('serial-port-get-read-encoding'), + getOpenOptions: () => ipcRenderer.invoke('serial-port-get-open-options'), onEvent: (callback: (serialPortEvent: SerialPortEvent) => void) => { const eventName = 'serial-port-notification'; const dataListener = ( diff --git a/apps/spie/src/app/events/serial-port.events.ts b/apps/spie/src/app/events/serial-port.events.ts index 1a3a785..f2e83dc 100644 --- a/apps/spie/src/app/events/serial-port.events.ts +++ b/apps/spie/src/app/events/serial-port.events.ts @@ -20,10 +20,13 @@ export default class SerialPortEvents { >(); private static encoding: Encoding = 'ascii'; private static areListenersRegistered = false; + private static openOptions: OpenOptions | null = null; - private static addEventListeners(event: Electron.IpcMainEvent) { + private static addEventListeners( + event: Electron.IpcMainEvent + ): Promise { if (SerialPortEvents.areListenersRegistered) { - return; + return Promise.resolve(); } const addEventListener = ( @@ -36,7 +39,7 @@ export default class SerialPortEvents { !SerialPortEvents.serialPort.isOpen ) { if (!SerialPortEvents.listenerQueue.has(event)) { - // console.log('addEventListener queue', event, callback); + // console.log('SerialPortEvents.addEventListener queue', event, callback); // Port is not open, queue the callback SerialPortEvents.listenerQueue.set(event, callback); } @@ -44,7 +47,7 @@ export default class SerialPortEvents { } if (!SerialPortEvents.eventListeners.has(event)) { - // console.log('addEventListener attach', event, callback); + // console.log('SerialPortEvents.addEventListener attach', event, callback); // Port is open, attach callback immediately if (event === 'data') { SerialPortEvents.parser.on(event, callback); @@ -56,17 +59,17 @@ export default class SerialPortEvents { }; addEventListener('error', (error: Error) => { - const notification: SerialPortEvent = { event: 'error', error }; + const notification: SerialPortEvent = { type: 'error', error }; event.sender.send('serial-port-notification', notification); }); addEventListener('open', () => { - const notification: SerialPortEvent = { event: 'open' }; + const notification: SerialPortEvent = { type: 'open' }; event.sender.send('serial-port-notification', notification); }); addEventListener('close', () => { - const notification: SerialPortEvent = { event: 'close' }; + const notification: SerialPortEvent = { type: 'close' }; event.sender.send('serial-port-notification', notification); }); @@ -76,25 +79,27 @@ export default class SerialPortEvents { ? chunk.toString('hex').toUpperCase().match(/.{2}/g).join(' ') : chunk.toString('ascii'); - const notification: SerialPortEvent = { event: 'data', data }; + const notification: SerialPortEvent = { type: 'data', data }; event.sender.send('serial-port-notification', notification); }); addEventListener('drain', () => { - const notification: SerialPortEvent = { event: 'drain' }; + const notification: SerialPortEvent = { type: 'drain' }; event.sender.send('serial-port-notification', notification); }); SerialPortEvents.areListenersRegistered = true; + + return Promise.resolve(); } - private static removeEventListeners() { + private static removeEventListeners(): Promise { if (!SerialPortEvents.areListenersRegistered) { - return; + return Promise.resolve(); } SerialPortEvents.eventListeners.forEach((callback, event) => { - // console.log('removeEventListener', event, callback); + // console.log('SerialPortEvents.removeEventListener', event, callback); if (event === 'data') { SerialPortEvents.parser.off(event, callback); } else { @@ -104,6 +109,8 @@ export default class SerialPortEvents { SerialPortEvents.eventListeners.clear(); SerialPortEvents.areListenersRegistered = false; + + return Promise.resolve(); } static bootstrapEvents(): void { @@ -154,6 +161,8 @@ export default class SerialPortEvents { return reject(error); } + SerialPortEvents.openOptions = openOptions; + resolve(); }); }); @@ -216,26 +225,38 @@ export default class SerialPortEvents { ipcMain.handle('serial-port-is-open', () => { // console.warn('serial-port-is-open'); if (SerialPortEvents.serialPort && SerialPortEvents.serialPort.isOpen) { - return true; + return Promise.resolve(true); } - return false; + return Promise.resolve(false); }); ipcMain.handle('serial-port-set-read-encoding', (_, encoding: Encoding) => { // console.warn('serial-port-set-read-encoding'); SerialPortEvents.encoding = encoding; + + return Promise.resolve(); + }); + + ipcMain.handle('serial-port-get-read-encoding', () => { + // console.warn('serial-port-get-read-encoding'); + + return Promise.resolve(SerialPortEvents.encoding); + }); + + ipcMain.handle('serial-port-get-open-options', () => { + // console.warn('serial-port-get-open-options'); + return Promise.resolve(SerialPortEvents.openOptions); }); ipcMain.on('serial-port-add-notification-event-listener', (event) => { // console.warn('serial-port-add-notification-event-listener'); - - SerialPortEvents.addEventListeners(event); + return SerialPortEvents.addEventListeners(event); }); ipcMain.on('serial-port-remove-notification-event-listener', () => { // console.warn('serial-port-remove-notification-event-listener'); - SerialPortEvents.removeEventListeners(); + return SerialPortEvents.removeEventListeners(); }); } } diff --git a/apps/spie/src/app/events/update.events.ts b/apps/spie/src/app/events/update.events.ts index 80014f5..591f240 100644 --- a/apps/spie/src/app/events/update.events.ts +++ b/apps/spie/src/app/events/update.events.ts @@ -19,6 +19,111 @@ export default class UpdateEvents { (...args: any[]) => void >(); + private static addEventListeners( + event: Electron.IpcMainEvent + ): Promise { + if (UpdateEvents.areListenersRegistered) { + return Promise.resolve(); + } + + UpdateEvents.areListenersRegistered = true; + + const addEventListener = ( + event: UpdaterEvents, + callback: (...args: any[]) => void + ) => { + if (!UpdateEvents.eventListeners.has(event)) { + // console.log('UpdateEvents.addEventListener attach', event, callback); + autoUpdater.on(event, callback); + UpdateEvents.eventListeners.set(event, callback); + } + }; + + addEventListener('error', (error: Error, message: string) => { + const updateNotification: AutoUpdaterEvent = { + event: 'error', + error, + message, + }; + event.sender.send('app-update-notification', updateNotification); + }); + + addEventListener('checking-for-update', () => { + const updateNotification: AutoUpdaterEvent = { + event: 'checking-for-update', + }; + event.sender.send('app-update-notification', updateNotification); + }); + + addEventListener('update-not-available', (updateInfo: UpdateInfo) => { + const updateNotification: AutoUpdaterEvent = { + event: 'update-not-available', + updateInfo, + }; + event.sender.send('app-update-notification', updateNotification); + }); + + addEventListener('update-available', (updateInfo: UpdateInfo) => { + new Notification({ + title: 'Update Available for Download', + body: `Version ${updateInfo.releaseName} is ready for download.`, + icon: join(__dirname, 'assets/icon.ico'), + }).show(); + + const updateNotification: AutoUpdaterEvent = { + event: 'update-available', + updateInfo, + }; + + event.sender.send('app-update-notification', updateNotification); + }); + + addEventListener( + 'update-downloaded', + (updateDownloadedEvent: UpdateDownloadedEvent) => { + const updateNotification: AutoUpdaterEvent = { + event: 'update-downloaded', + updateDownloadedEvent, + }; + event.sender.send('app-update-notification', updateNotification); + } + ); + + addEventListener('download-progress', (progressInfo: ProgressInfo) => { + const updateNotification: AutoUpdaterEvent = { + event: 'download-progress', + progressInfo, + }; + event.sender.send('app-update-notification', updateNotification); + }); + + addEventListener('update-cancelled', (updateInfo: UpdateInfo) => { + const updateNotification: AutoUpdaterEvent = { + event: 'update-cancelled', + updateInfo, + }; + event.sender.send('app-update-notification', updateNotification); + }); + + return Promise.resolve(); + } + + private static removeEventListeners(): Promise { + if (!UpdateEvents.areListenersRegistered) { + return Promise.resolve(); + } + + UpdateEvents.eventListeners.forEach((listener, event) => { + // console.log('UpdateEvents.removeEventListener', event, callback); + autoUpdater.off(event, listener); + }); + UpdateEvents.eventListeners.clear(); + + UpdateEvents.areListenersRegistered = false; + + return Promise.resolve(); + } + static bootstrapEvents(): void { const checkForUpdates = async () => { try { @@ -50,108 +155,26 @@ export default class UpdateEvents { setTimeout(checkForUpdates, delayAfterAppReady); ipcMain.on('app-update-add-notification-event-listener', (event) => { - if (UpdateEvents.areListenersRegistered) { - return; - } + // console.warn('app-update-add-notification-event-listener'); - UpdateEvents.areListenersRegistered = true; - - const addEventListener = ( - event: UpdaterEvents, - callback: (...args: any[]) => void - ) => { - if (!UpdateEvents.eventListeners.has(event)) { - autoUpdater.on(event, callback); - UpdateEvents.eventListeners.set(event, callback); - } - }; - - addEventListener('error', (error: Error, message: string) => { - const updateNotification: AutoUpdaterEvent = { - event: 'error', - error, - message, - }; - event.sender.send('app-update-notification', updateNotification); - }); - - addEventListener('checking-for-update', () => { - const updateNotification: AutoUpdaterEvent = { - event: 'checking-for-update', - }; - event.sender.send('app-update-notification', updateNotification); - }); - - addEventListener('update-not-available', (updateInfo: UpdateInfo) => { - const updateNotification: AutoUpdaterEvent = { - event: 'update-not-available', - updateInfo, - }; - event.sender.send('app-update-notification', updateNotification); - }); - - addEventListener('update-available', (updateInfo: UpdateInfo) => { - new Notification({ - title: 'Update Available for Download', - body: `Version ${updateInfo.releaseName} is ready for download.`, - icon: join(__dirname, 'assets/icon.ico'), - }).show(); - - const updateNotification: AutoUpdaterEvent = { - event: 'update-available', - updateInfo, - }; - - event.sender.send('app-update-notification', updateNotification); - }); - - addEventListener( - 'update-downloaded', - (updateDownloadedEvent: UpdateDownloadedEvent) => { - const updateNotification: AutoUpdaterEvent = { - event: 'update-downloaded', - updateDownloadedEvent, - }; - event.sender.send('app-update-notification', updateNotification); - } - ); - - addEventListener('download-progress', (progressInfo: ProgressInfo) => { - const updateNotification: AutoUpdaterEvent = { - event: 'download-progress', - progressInfo, - }; - event.sender.send('app-update-notification', updateNotification); - }); - - addEventListener('update-cancelled', (updateInfo: UpdateInfo) => { - const updateNotification: AutoUpdaterEvent = { - event: 'update-cancelled', - updateInfo, - }; - event.sender.send('app-update-notification', updateNotification); - }); + return UpdateEvents.addEventListeners(event); }); ipcMain.on('app-update-remove-notification-event-listener', () => { - if (!UpdateEvents.areListenersRegistered) { - return; - } - - UpdateEvents.eventListeners.forEach((listener, event) => { - autoUpdater.off(event, listener); - }); - UpdateEvents.eventListeners.clear(); - - UpdateEvents.areListenersRegistered = false; + // console.warn('app-update-remove-notification-event-listener'); + return UpdateEvents.removeEventListeners(); }); ipcMain.handle('app-download-update', () => { + // console.warn('app-download-update'); return autoUpdater.downloadUpdate(); }); ipcMain.handle('app-install-update', () => { + // console.warn('app-install-update'); autoUpdater.quitAndInstall(); + + return Promise.resolve(); }); } } diff --git a/libs/types/src/lib/electron.d.ts b/libs/types/src/lib/electron.d.ts index 7049522..bba42cb 100644 --- a/libs/types/src/lib/electron.d.ts +++ b/libs/types/src/lib/electron.d.ts @@ -24,11 +24,11 @@ export type Encoding = 'ascii' | 'hex'; export type SerialPortEventType = 'error' | 'open' | 'close' | 'data' | 'drain'; export type SerialPortEvent = - | { event: 'error'; error: Error } - | { event: 'open' } - | { event: 'close' } - | { event: 'data'; data: string } - | { event: 'drain' }; + | { type: 'error'; error: Error } + | { type: 'open' } + | { type: 'close' } + | { type: 'data'; data: string } + | { type: 'drain' }; export interface SerialPortAPI { list: () => Promise; @@ -37,6 +37,8 @@ export interface SerialPortAPI { write: (data: string, encoding: Encoding) => Promise; isOpen: () => Promise; setReadEncoding: (encoding: Encoding) => Promise; + getReadEncoding: () => Promise; + getOpenOptions: () => Promise; onEvent: (callback: (serialPortEvent: SerialPortEvent) => void) => () => void; } diff --git a/package-lock.json b/package-lock.json index 62d1ee0..3bcdb02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,8 +19,10 @@ "@angular/platform-browser-dynamic": "~18.2.0", "@angular/router": "~18.2.0", "@ionic/angular": "^8.0.0", + "apexcharts": "^4.1.0", "electron-updater": "^6.3.9", "ionicons": "^7.0.0", + "ng-apexcharts": "^1.13.0", "patch-package": "^8.0.0", "rxjs": "~7.8.0", "serialport": "^12.0.0", @@ -9297,6 +9299,62 @@ "npm": ">=7.10.0" } }, + "node_modules/@svgdotjs/svg.draggable.js": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.4.tgz", + "integrity": "sha512-vWi/Col5Szo74HJVBgMHz23kLVljt3jvngmh0DzST45iO2ubIZ487uUAHIxSZH2tVRyiaaTL+Phaasgp4gUD2g==", + "license": "MIT", + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, + "node_modules/@svgdotjs/svg.filter.js": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.8.tgz", + "integrity": "sha512-YshF2YDaeRA2StyzAs5nUPrev7npQ38oWD0eTRwnsciSL2KrRPMoUw8BzjIXItb3+dccKGTX3IQOd2NFzmHkog==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.js": "^3.1.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/@svgdotjs/svg.js": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.4.tgz", + "integrity": "sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Fuzzyma" + } + }, + "node_modules/@svgdotjs/svg.resize.js": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz", + "integrity": "sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==", + "license": "MIT", + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.select.js": "^4.0.1" + } + }, + "node_modules/@svgdotjs/svg.select.js": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.2.tgz", + "integrity": "sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g==", + "license": "MIT", + "engines": { + "node": ">= 14.18" + }, + "peerDependencies": { + "@svgdotjs/svg.js": "^3.2.4" + } + }, "node_modules/@swc-node/core": { "version": "1.13.3", "resolved": "https://registry.npmjs.org/@swc-node/core/-/core-1.13.3.tgz", @@ -10646,6 +10704,12 @@ "node": ">=14.15.0" } }, + "node_modules/@yr/monotone-cubic-spline": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz", + "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==", + "license": "MIT" + }, "node_modules/@zkochan/js-yaml": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.7.tgz", @@ -11011,6 +11075,20 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/apexcharts": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.1.0.tgz", + "integrity": "sha512-TE0q0cXeS5k/AByLqlZAQ/aRQfdD3z0Ajd1uQWWZEjxiIC5qcBpMrTaG+aT+c3golqkvLH3u6kxDW8HBrggpLw==", + "license": "MIT", + "dependencies": { + "@svgdotjs/svg.draggable.js": "^3.0.4", + "@svgdotjs/svg.filter.js": "^3.0.8", + "@svgdotjs/svg.js": "^3.2.4", + "@svgdotjs/svg.resize.js": "^2.0.2", + "@svgdotjs/svg.select.js": "^4.0.1", + "@yr/monotone-cubic-spline": "^1.0.3" + } + }, "node_modules/app-builder-bin": { "version": "5.0.0-alpha.10", "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.10.tgz", @@ -23803,6 +23881,21 @@ "dev": true, "license": "MIT" }, + "node_modules/ng-apexcharts": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/ng-apexcharts/-/ng-apexcharts-1.13.0.tgz", + "integrity": "sha512-YftYLsYTabbGYZZTceXRnliLaQ1/uAp4yx/kanRP5VJtNl4hObRv9hV5WLTXoQnYY0fzfseotgf7Uz0bUMLvAw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/common": "^18.0.4", + "@angular/core": "^18.0.4", + "apexcharts": "^4.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, "node_modules/nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", diff --git a/package.json b/package.json index dae3e62..8998a5f 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,10 @@ "@angular/platform-browser-dynamic": "~18.2.0", "@angular/router": "~18.2.0", "@ionic/angular": "^8.0.0", + "apexcharts": "^4.1.0", "electron-updater": "^6.3.9", "ionicons": "^7.0.0", + "ng-apexcharts": "^1.13.0", "patch-package": "^8.0.0", "rxjs": "~7.8.0", "serialport": "^12.0.0", From 128e72378ad4502ddfc8ebf3c83dc56be6b02e8d Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Thu, 5 Dec 2024 22:11:40 +0930 Subject: [PATCH 04/23] test(repo): fix unit tests --- .../update-modal/update-modal.component.ts | 18 +-- .../src/app/services/electron.service.spec.ts | 151 +++++++++--------- .../src/app/events/electron.events.spec.ts | 6 - .../src/app/events/serial-port.events.spec.ts | 46 +++++- .../spie/src/app/events/serial-port.events.ts | 48 +++--- .../spie/src/app/events/update.events.spec.ts | 16 +- apps/spie/src/app/events/update.events.ts | 30 ++-- libs/types/src/lib/electron.d.ts | 14 +- 8 files changed, 175 insertions(+), 154 deletions(-) diff --git a/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts index 1a3250e..0aa25f0 100644 --- a/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts +++ b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts @@ -52,15 +52,15 @@ export class UpdateModalComponent { progressInfo = toSignal( this.electronService.onUpdateEvent().pipe( tap(async (autoUpdaterEvent) => { - if (autoUpdaterEvent.event === 'checking-for-update') { + if (autoUpdaterEvent.type === 'checking-for-update') { await this.toasterService.presentInfoToast('Checking for Updates'); } - if (autoUpdaterEvent.event === 'update-not-available') { + if (autoUpdaterEvent.type === 'update-not-available') { await this.toasterService.presentInfoToast('No Updates Available'); } - if (autoUpdaterEvent.event === 'update-available') { + if (autoUpdaterEvent.type === 'update-available') { await this.presentAlert( 'Update Available for Download', `Version ${autoUpdaterEvent.updateInfo.version} is ready for download.`, @@ -81,7 +81,7 @@ export class UpdateModalComponent { ); } - if (autoUpdaterEvent.event === 'update-downloaded') { + if (autoUpdaterEvent.type === 'update-downloaded') { await this.presentAlert( 'Update Ready to Install', `Version ${autoUpdaterEvent.updateDownloadedEvent.version} is ready to install.`, @@ -101,20 +101,20 @@ export class UpdateModalComponent { ); } - if (autoUpdaterEvent.event === 'update-cancelled') { + if (autoUpdaterEvent.type === 'update-cancelled') { await this.toasterService.presentErrorToast('Update Cancelled'); } if ( - autoUpdaterEvent.event === 'update-downloaded' || - autoUpdaterEvent.event === 'update-cancelled' || - autoUpdaterEvent.event === 'error' + autoUpdaterEvent.type === 'update-downloaded' || + autoUpdaterEvent.type === 'update-cancelled' || + autoUpdaterEvent.type === 'error' ) { await this.updateModal().dismiss(); } }), switchMap((autoUpdaterEvent) => { - if (autoUpdaterEvent.event === 'download-progress') { + if (autoUpdaterEvent.type === 'download-progress') { return of(autoUpdaterEvent.progressInfo); } diff --git a/apps/spie-ui/src/app/services/electron.service.spec.ts b/apps/spie-ui/src/app/services/electron.service.spec.ts index 1478ca2..5a58927 100644 --- a/apps/spie-ui/src/app/services/electron.service.spec.ts +++ b/apps/spie-ui/src/app/services/electron.service.spec.ts @@ -31,6 +31,8 @@ describe('ElectronService', () => { write: jest.fn(), isOpen: jest.fn(), setReadEncoding: jest.fn(), + getReadEncoding: jest.fn(), + getOpenOptions: jest.fn(), onEvent: jest.fn(), }, }; @@ -117,49 +119,40 @@ describe('ElectronService', () => { describe('onUpdateEvent', () => { it('should handle error event', (done) => { const error = new Error('Test error'); - const mockEvent: AutoUpdaterEvent = { event: 'error', error }; - + const mockEvent: AutoUpdaterEvent = { type: 'error', error }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); it('should handle checking-for-update event', (done) => { - const mockEvent: AutoUpdaterEvent = { event: 'checking-for-update' }; - + const mockEvent: AutoUpdaterEvent = { type: 'checking-for-update' }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); - it('should handle update-not-available event', (done) => { const updateInfo: UpdateInfo = { version: '1.0.0', @@ -169,29 +162,24 @@ describe('ElectronService', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-not-available', + type: 'update-not-available', updateInfo, }; - (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); - it('should handle update-available event', (done) => { const updateInfo: UpdateInfo = { version: '1.0.0', @@ -201,29 +189,24 @@ describe('ElectronService', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-available', + type: 'update-available', updateInfo, }; - (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); - it('should handle update-downloaded event', (done) => { const updateDownloadedEvent: UpdateDownloadedEvent = { downloadedFile: '/test/test.exe', @@ -234,29 +217,24 @@ describe('ElectronService', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-downloaded', + type: 'update-downloaded', updateDownloadedEvent, }; - (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); - it('should handle download-progress event', (done) => { const progressInfo: ProgressInfo = { total: 100, @@ -266,29 +244,24 @@ describe('ElectronService', () => { bytesPerSecond: 1115.55, }; const mockEvent: AutoUpdaterEvent = { - event: 'download-progress', + type: 'download-progress', progressInfo, }; - (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); - it('should handle update-cancelled event', (done) => { const updateInfo: UpdateInfo = { version: '1.0.0', @@ -298,36 +271,29 @@ describe('ElectronService', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-cancelled', + type: 'update-cancelled', updateInfo, }; - (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); return jest.fn(); } ); - const observer = { - next: (event: AutoUpdaterEvent) => { - expect(event).toEqual(mockEvent); + next: (type: AutoUpdaterEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; - const subscription = service.onUpdateEvent().subscribe(observer); - subscription.unsubscribe(); }); - it('should clean up the listener when unsubscribed', () => { const callback = jest.fn(); - (mockElectronAPI.onUpdateEvent as jest.Mock).mockReturnValue(callback); const subscription = service.onUpdateEvent().subscribe(); subscription.unsubscribe(); - expect(callback).toHaveBeenCalled(); }); }); @@ -430,10 +396,39 @@ describe('ElectronService', () => { }); }); + describe('serialPort.getReadEncoding', () => { + it('should set the read encoding', async () => { + const mockEncoding = 'hex'; + + ( + mockElectronAPI.serialPort.getReadEncoding as jest.Mock + ).mockResolvedValue(mockEncoding); + + const encoding = await service.serialPort.getReadEncoding(); + expect(mockElectronAPI.serialPort.getReadEncoding).toHaveBeenCalled(); + expect(encoding).toEqual(mockEncoding); + }); + }); + + describe('serialPort.getOpenOptions', () => { + it('should get the open options', async () => { + const mockOpenOptions = { path: '/dev/ttyUSB0', baudRate: 9600 }; + + ( + mockElectronAPI.serialPort.getOpenOptions as jest.Mock + ).mockResolvedValue(mockOpenOptions); + + const openOptions = await service.serialPort.getOpenOptions(); + + expect(mockElectronAPI.serialPort.getOpenOptions).toHaveBeenCalled(); + expect(openOptions).toEqual(mockOpenOptions); + }); + }); + describe('serialPort.onEvent', () => { it('should handle error event', (done) => { const error = new Error('Test error'); - const mockEvent: SerialPortEvent = { event: 'error', error }; + const mockEvent: SerialPortEvent = { type: 'error', error }; (mockElectronAPI.serialPort.onEvent as jest.Mock).mockImplementation( (callback) => { @@ -443,8 +438,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; @@ -455,7 +450,7 @@ describe('ElectronService', () => { }); it('should handle open event', (done) => { - const mockEvent: SerialPortEvent = { event: 'open' }; + const mockEvent: SerialPortEvent = { type: 'open' }; (mockElectronAPI.serialPort.onEvent as jest.Mock).mockImplementation( (callback) => { @@ -465,8 +460,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; @@ -477,7 +472,7 @@ describe('ElectronService', () => { }); it('should handle open event', (done) => { - const mockEvent: SerialPortEvent = { event: 'open' }; + const mockEvent: SerialPortEvent = { type: 'open' }; (mockElectronAPI.serialPort.onEvent as jest.Mock).mockImplementation( (callback) => { @@ -487,8 +482,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; @@ -499,7 +494,7 @@ describe('ElectronService', () => { }); it('should handle close event', (done) => { - const mockEvent: SerialPortEvent = { event: 'close' }; + const mockEvent: SerialPortEvent = { type: 'close' }; (mockElectronAPI.serialPort.onEvent as jest.Mock).mockImplementation( (callback) => { @@ -509,8 +504,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; @@ -524,7 +519,7 @@ describe('ElectronService', () => { const encoding = 'hex'; const chunk = Buffer.from('test data'); const mockEvent: SerialPortEvent = { - event: 'data', + type: 'data', data: chunk .toString('hex') .toUpperCase() @@ -542,8 +537,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); // done(); }, }; @@ -557,7 +552,7 @@ describe('ElectronService', () => { const encoding = 'ascii'; const chunk = Buffer.from('test data'); const mockEvent: SerialPortEvent = { - event: 'data', + type: 'data', data: chunk.toString('ascii'), }; @@ -571,8 +566,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); }, }; @@ -582,7 +577,7 @@ describe('ElectronService', () => { }); it('should handle drain event', (done) => { - const mockEvent: SerialPortEvent = { event: 'drain' }; + const mockEvent: SerialPortEvent = { type: 'drain' }; (mockElectronAPI.serialPort.onEvent as jest.Mock).mockImplementation( (callback) => { @@ -592,8 +587,8 @@ describe('ElectronService', () => { ); const observer = { - next: (event: SerialPortEvent) => { - expect(event).toEqual(mockEvent); + next: (type: SerialPortEvent) => { + expect(type).toEqual(mockEvent); done(); }, }; diff --git a/apps/spie/src/app/events/electron.events.spec.ts b/apps/spie/src/app/events/electron.events.spec.ts index 3955f4b..7e6b2ce 100644 --- a/apps/spie/src/app/events/electron.events.spec.ts +++ b/apps/spie/src/app/events/electron.events.spec.ts @@ -23,12 +23,6 @@ describe('Electron events', () => { jest.clearAllMocks(); }); - describe('platform', () => { - it('should expose the correct platform value', () => { - expect(window.electron.platform).toBe(process.platform); - }); - }); - describe('quit', () => { it('should send quit event with the specified code', () => { const code = 1; diff --git a/apps/spie/src/app/events/serial-port.events.spec.ts b/apps/spie/src/app/events/serial-port.events.spec.ts index 85aa1a5..9fa936d 100644 --- a/apps/spie/src/app/events/serial-port.events.spec.ts +++ b/apps/spie/src/app/events/serial-port.events.spec.ts @@ -146,6 +146,36 @@ describe('Serial Port events', () => { }); }); + describe('getReadEncoding', () => { + it('should invoke serial-port-get-read-encoding and get encoding', async () => { + const mockEncoding = 'hex'; + + (ipcRenderer.invoke as jest.Mock).mockResolvedValue(mockEncoding); + + const encoding = await window.electron.serialPort.getReadEncoding(); + + expect(ipcRenderer.invoke).toHaveBeenCalledWith( + 'serial-port-get-read-encoding' + ); + expect(encoding).toEqual(mockEncoding); + }); + }); + + describe('getOpenOptions', () => { + it('should invoke serial-port-get-open-options and get open options', async () => { + const mockOpenOptions = { path: '/dev/ttyUSB0', baudRate: 9600 }; + + (ipcRenderer.invoke as jest.Mock).mockResolvedValue(mockOpenOptions); + + const openOptions = await window.electron.serialPort.getOpenOptions(); + + expect(ipcRenderer.invoke).toHaveBeenCalledWith( + 'serial-port-get-open-options' + ); + expect(openOptions).toEqual(openOptions); + }); + }); + describe('onEvent', () => { it('should add listener', () => { const callback = jest.fn(); @@ -166,7 +196,7 @@ describe('Serial Port events', () => { it('should handle error event', () => { const callback = jest.fn(); const error = new Error('Test error'); - const mockEvent: SerialPortEvent = { event: 'error', error }; + const mockEvent: SerialPortEvent = { type: 'error', error }; (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { listener({}, mockEvent); @@ -179,7 +209,7 @@ describe('Serial Port events', () => { it('should handle open event', () => { const callback = jest.fn(); - const mockEvent: SerialPortEvent = { event: 'open' }; + const mockEvent: SerialPortEvent = { type: 'open' }; (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { listener({}, mockEvent); @@ -192,7 +222,7 @@ describe('Serial Port events', () => { it('should handle close event', () => { const callback = jest.fn(); - const mockEvent: SerialPortEvent = { event: 'close' }; + const mockEvent: SerialPortEvent = { type: 'close' }; (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { listener({}, mockEvent); @@ -208,14 +238,14 @@ describe('Serial Port events', () => { const encoding = 'hex'; const chunk = Buffer.from('test data'); const mockEvent: SerialPortEvent = { - event: 'data', + type: 'data', data: chunk.toString('hex').toUpperCase().match(/.{2}/g).join(' '), }; await window.electron.serialPort.setReadEncoding(encoding); (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { - listener({}, { event: 'data', data: mockEvent.data }); + listener({}, { type: 'data', data: mockEvent.data }); }); window.electron.serialPort.onEvent(callback); @@ -228,14 +258,14 @@ describe('Serial Port events', () => { const encoding = 'ascii'; const chunk = Buffer.from('test data'); const mockEvent: SerialPortEvent = { - event: 'data', + type: 'data', data: chunk.toString('ascii'), }; await window.electron.serialPort.setReadEncoding(encoding); (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { - listener({}, { event: 'data', data: mockEvent.data }); + listener({}, { type: 'data', data: mockEvent.data }); }); window.electron.serialPort.onEvent(callback); @@ -245,7 +275,7 @@ describe('Serial Port events', () => { it('should handle drain event', () => { const callback = jest.fn(); - const mockEvent: SerialPortEvent = { event: 'drain' }; + const mockEvent: SerialPortEvent = { type: 'drain' }; (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { listener({}, mockEvent); diff --git a/apps/spie/src/app/events/serial-port.events.ts b/apps/spie/src/app/events/serial-port.events.ts index f2e83dc..ee973d6 100644 --- a/apps/spie/src/app/events/serial-port.events.ts +++ b/apps/spie/src/app/events/serial-port.events.ts @@ -30,7 +30,7 @@ export default class SerialPortEvents { } const addEventListener = ( - event: SerialPortEventType, + serialPortEventType: SerialPortEventType, callback: (...args: any[]) => void ) => { if ( @@ -38,23 +38,23 @@ export default class SerialPortEvents { !SerialPortEvents.parser || !SerialPortEvents.serialPort.isOpen ) { - if (!SerialPortEvents.listenerQueue.has(event)) { - // console.log('SerialPortEvents.addEventListener queue', event, callback); + if (!SerialPortEvents.listenerQueue.has(serialPortEventType)) { + // console.log('SerialPortEvents.addEventListener queue', serialPortEventType, callback); // Port is not open, queue the callback - SerialPortEvents.listenerQueue.set(event, callback); + SerialPortEvents.listenerQueue.set(serialPortEventType, callback); } return; } - if (!SerialPortEvents.eventListeners.has(event)) { - // console.log('SerialPortEvents.addEventListener attach', event, callback); + if (!SerialPortEvents.eventListeners.has(serialPortEventType)) { + // console.log('SerialPortEvents.addEventListener attach', serialPortEventType, callback); // Port is open, attach callback immediately - if (event === 'data') { - SerialPortEvents.parser.on(event, callback); + if (serialPortEventType === 'data') { + SerialPortEvents.parser.on(serialPortEventType, callback); } else { - SerialPortEvents.serialPort.on(event, callback); + SerialPortEvents.serialPort.on(serialPortEventType, callback); } - SerialPortEvents.eventListeners.set(event, callback); + SerialPortEvents.eventListeners.set(serialPortEventType, callback); } }; @@ -98,12 +98,12 @@ export default class SerialPortEvents { return Promise.resolve(); } - SerialPortEvents.eventListeners.forEach((callback, event) => { - // console.log('SerialPortEvents.removeEventListener', event, callback); - if (event === 'data') { - SerialPortEvents.parser.off(event, callback); + SerialPortEvents.eventListeners.forEach((callback, serialPortEventType) => { + // console.log('SerialPortEvents.removeEventListener', serialPortEventType, callback); + if (serialPortEventType === 'data') { + SerialPortEvents.parser.off(serialPortEventType, callback); } else { - SerialPortEvents.serialPort.off(event, callback); + SerialPortEvents.serialPort.off(serialPortEventType, callback); } }); @@ -145,15 +145,17 @@ export default class SerialPortEvents { ); // Process queued listeners after opening - SerialPortEvents.listenerQueue.forEach((callback, event) => { - // console.log(`Processing queued listener for event: ${event}`); - if (event === 'data') { - SerialPortEvents.parser.on(event, callback); - } else { - SerialPortEvents.serialPort.on(event, callback); + SerialPortEvents.listenerQueue.forEach( + (callback, serialPortEventType) => { + // console.log(`Processing queued listener for serialPortEventType: ${serialPortEventType}`); + if (serialPortEventType === 'data') { + SerialPortEvents.parser.on(serialPortEventType, callback); + } else { + SerialPortEvents.serialPort.on(serialPortEventType, callback); + } + SerialPortEvents.eventListeners.set(serialPortEventType, callback); } - SerialPortEvents.eventListeners.set(event, callback); - }); + ); SerialPortEvents.listenerQueue.clear(); SerialPortEvents.serialPort.open((error) => { diff --git a/apps/spie/src/app/events/update.events.spec.ts b/apps/spie/src/app/events/update.events.spec.ts index 5e446de..8be8b99 100644 --- a/apps/spie/src/app/events/update.events.spec.ts +++ b/apps/spie/src/app/events/update.events.spec.ts @@ -84,7 +84,7 @@ describe('Update Events', () => { it('should handle update notifications correctly', () => { const callback = jest.fn(); const mockData = { - event: 'update-available', + type: 'update-available', updateInfo: { version: '1.2.3' }, }; @@ -136,7 +136,7 @@ describe('onUpdateEvent', () => { it('should handle error event', () => { const callback = jest.fn(); const error = new Error('Test error'); - const mockEvent: AutoUpdaterEvent = { event: 'error', error }; + const mockEvent: AutoUpdaterEvent = { type: 'error', error }; (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { listener({}, mockEvent); @@ -149,7 +149,7 @@ describe('onUpdateEvent', () => { it('should handle checking-for-update event', () => { const callback = jest.fn(); - const mockEvent: AutoUpdaterEvent = { event: 'checking-for-update' }; + const mockEvent: AutoUpdaterEvent = { type: 'checking-for-update' }; (ipcRenderer.on as jest.Mock).mockImplementationOnce((_, listener) => { listener({}, mockEvent); @@ -170,7 +170,7 @@ describe('onUpdateEvent', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-not-available', + type: 'update-not-available', updateInfo, }; @@ -193,7 +193,7 @@ describe('onUpdateEvent', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-available', + type: 'update-available', updateInfo, }; @@ -217,7 +217,7 @@ describe('onUpdateEvent', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-downloaded', + type: 'update-downloaded', updateDownloadedEvent, }; @@ -240,7 +240,7 @@ describe('onUpdateEvent', () => { bytesPerSecond: 1115.55, }; const mockEvent: AutoUpdaterEvent = { - event: 'download-progress', + type: 'download-progress', progressInfo, }; @@ -263,7 +263,7 @@ describe('onUpdateEvent', () => { releaseDate: new Date().toISOString(), }; const mockEvent: AutoUpdaterEvent = { - event: 'update-cancelled', + type: 'update-cancelled', updateInfo, }; diff --git a/apps/spie/src/app/events/update.events.ts b/apps/spie/src/app/events/update.events.ts index 591f240..8ef0e5b 100644 --- a/apps/spie/src/app/events/update.events.ts +++ b/apps/spie/src/app/events/update.events.ts @@ -29,19 +29,19 @@ export default class UpdateEvents { UpdateEvents.areListenersRegistered = true; const addEventListener = ( - event: UpdaterEvents, + updaterEventType: UpdaterEvents, callback: (...args: any[]) => void ) => { - if (!UpdateEvents.eventListeners.has(event)) { - // console.log('UpdateEvents.addEventListener attach', event, callback); - autoUpdater.on(event, callback); - UpdateEvents.eventListeners.set(event, callback); + if (!UpdateEvents.eventListeners.has(updaterEventType)) { + // console.log('UpdateEvents.addEventListener attach', updaterEventType, callback); + autoUpdater.on(updaterEventType, callback); + UpdateEvents.eventListeners.set(updaterEventType, callback); } }; addEventListener('error', (error: Error, message: string) => { const updateNotification: AutoUpdaterEvent = { - event: 'error', + type: 'error', error, message, }; @@ -50,14 +50,14 @@ export default class UpdateEvents { addEventListener('checking-for-update', () => { const updateNotification: AutoUpdaterEvent = { - event: 'checking-for-update', + type: 'checking-for-update', }; event.sender.send('app-update-notification', updateNotification); }); addEventListener('update-not-available', (updateInfo: UpdateInfo) => { const updateNotification: AutoUpdaterEvent = { - event: 'update-not-available', + type: 'update-not-available', updateInfo, }; event.sender.send('app-update-notification', updateNotification); @@ -71,7 +71,7 @@ export default class UpdateEvents { }).show(); const updateNotification: AutoUpdaterEvent = { - event: 'update-available', + type: 'update-available', updateInfo, }; @@ -82,7 +82,7 @@ export default class UpdateEvents { 'update-downloaded', (updateDownloadedEvent: UpdateDownloadedEvent) => { const updateNotification: AutoUpdaterEvent = { - event: 'update-downloaded', + type: 'update-downloaded', updateDownloadedEvent, }; event.sender.send('app-update-notification', updateNotification); @@ -91,7 +91,7 @@ export default class UpdateEvents { addEventListener('download-progress', (progressInfo: ProgressInfo) => { const updateNotification: AutoUpdaterEvent = { - event: 'download-progress', + type: 'download-progress', progressInfo, }; event.sender.send('app-update-notification', updateNotification); @@ -99,7 +99,7 @@ export default class UpdateEvents { addEventListener('update-cancelled', (updateInfo: UpdateInfo) => { const updateNotification: AutoUpdaterEvent = { - event: 'update-cancelled', + type: 'update-cancelled', updateInfo, }; event.sender.send('app-update-notification', updateNotification); @@ -113,9 +113,9 @@ export default class UpdateEvents { return Promise.resolve(); } - UpdateEvents.eventListeners.forEach((listener, event) => { - // console.log('UpdateEvents.removeEventListener', event, callback); - autoUpdater.off(event, listener); + UpdateEvents.eventListeners.forEach((listener, updaterEventType) => { + // console.log('UpdateEvents.removeEventListener', updaterEventType, callback); + autoUpdater.off(updaterEventType, listener); }); UpdateEvents.eventListeners.clear(); diff --git a/libs/types/src/lib/electron.d.ts b/libs/types/src/lib/electron.d.ts index bba42cb..92c083b 100644 --- a/libs/types/src/lib/electron.d.ts +++ b/libs/types/src/lib/electron.d.ts @@ -9,13 +9,13 @@ import { } from 'electron-updater'; export type AutoUpdaterEvent = - | { event: 'error'; error: Error; message?: string } - | { event: 'checking-for-update' } - | { event: 'update-not-available'; updateInfo: UpdateInfo } - | { event: 'update-available'; updateInfo: UpdateInfo } - | { event: 'update-downloaded'; updateDownloadedEvent: UpdateDownloadedEvent } - | { event: 'download-progress'; progressInfo: ProgressInfo } - | { event: 'update-cancelled'; updateInfo: UpdateInfo }; + | { type: 'error'; error: Error; message?: string } + | { type: 'checking-for-update' } + | { type: 'update-not-available'; updateInfo: UpdateInfo } + | { type: 'update-available'; updateInfo: UpdateInfo } + | { type: 'update-downloaded'; updateDownloadedEvent: UpdateDownloadedEvent } + | { type: 'download-progress'; progressInfo: ProgressInfo } + | { type: 'update-cancelled'; updateInfo: UpdateInfo }; export type Delimiter = 'none' | 'cr' | 'lf' | 'crlf'; From 7105af665ef53146935ce7bb8018bdacce1881ee Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Sat, 7 Dec 2024 00:36:08 +0930 Subject: [PATCH 05/23] test(spie-ui-e2e): fix e2e tests --- README.md | 4 +- apps/spie-ui-e2e/src/e2e/send.cy.ts | 173 +++++++-------- apps/spie-ui-e2e/src/e2e/serial-port.cy.ts | 136 ++++-------- apps/spie-ui-e2e/src/e2e/terminal.cy.ts | 175 ++++++++------- apps/spie-ui-e2e/src/e2e/updater.ts | 202 +----------------- .../src/fixtures/mocks/electron-api.mock.ts | 37 +++- apps/spie-ui-e2e/src/support/commands.ts | 39 +++- .../components/plotter/plotter.component.ts | 16 +- .../components/terminal/terminal.component.ts | 6 +- .../src/app/services/serial-port.service.ts | 8 +- libs/types/src/lib/electron.d.ts | 2 + 11 files changed, 290 insertions(+), 508 deletions(-) diff --git a/README.md b/README.md index 7d389b2..eefaa87 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

- + GitHub Workflow Status (with event) @@ -199,7 +199,7 @@ Output files are located in `dist\executables` ### Known issues -- Serial data may be delivered in more than one .on('data') event. This means data received by the serialport library might arrive in multiple packets. For details, see [node-serialport/issues/659](https://github.com/serialport/node-serialport/issues/659) for more information. This is not a problem in most cases, but things may start looking strange if you are trying to monitor data at a fast rate. A good way to demonstrate the issues is to send data every `5ms`, `115200` baud rate and with `show timestamps`. You will notice that every so often there is a "broken" message. If you are developing your own application, I would recommend having a specific line terminator and use one of the [parsers](https://serialport.io/docs/api-parsers-overview) available. +- Serial data may be delivered in more than one `.on('data')` event. This means data received by the serialport library might arrive in multiple packets. For details, see [node-serialport/issues/659](https://github.com/serialport/node-serialport/issues/659) for more information. This is not a problem in most cases, but things may start looking strange if you are trying to monitor data at a fast rate. A good way to demonstrate the issues is to send data every `5ms`, `115200` baud rate and with `show timestamps`. You will notice that every so often there is a "broken" message. If you are developing your own application, I would recommend having a specific line terminator and use one of the [parsers](https://serialport.io/docs/api-parsers-overview) available. ### Limitations diff --git a/apps/spie-ui-e2e/src/e2e/send.cy.ts b/apps/spie-ui-e2e/src/e2e/send.cy.ts index e91c231..abad9dc 100644 --- a/apps/spie-ui-e2e/src/e2e/send.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/send.cy.ts @@ -1,97 +1,59 @@ -import { type SerialPortEvent } from '@spie/types'; - -import { mockElectronAPI } from '../fixtures/mocks/electron-api.mock'; +import { + mockElectronAPI, + mockSerialPortList, +} from '../fixtures/mocks/electron-api.mock'; describe('Send component', () => { - const mockSerialPortList = [ - { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, - { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, - ]; - - let onEventTrigger: ((event: SerialPortEvent) => void) | null; - beforeEach(() => { cy.visit('/'); cy.on('window:before:load', (win) => { - const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; - - win.electron = mockElectronAPI(); - win.electron.serialPort.list = cy.stub().resolves(mockSerialPortList); - - win.electron.serialPort.onEvent = cy - .stub() - .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { - listeners.push(callback); - - onEventTrigger = (serialPortEvent) => { - listeners.forEach((listener) => listener(serialPortEvent)); - }; - - return () => { - const index = listeners.indexOf(callback); - if (index !== -1) { - listeners.splice(index, 1); - } - }; - }); + win.electron = mockElectronAPI(win); }); + + cy.connect(mockSerialPortList[0].path, 9600); }); it('should enable/disable send based on serial port status', () => { - const data = 'test test test test test test test test test test'; + const mockData = 'test test test test test test test test test test'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); - cy.get('app-send ion-button') + cy.get('app-send-component ion-button') .contains('Send') .should('not.have.class', 'button-disabled'); - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'close' }); - } - }); + cy.disconnect(); - cy.get('app-send ion-button') + cy.get('app-send-component ion-button') .contains('Send') .should('have.class', 'button-disabled'); }); - it('should clear input after pressing clear input button', () => { - const data = 'test test test test test test test test test test'; + it('should set and clear input', () => { + const mockData = 'test test test test test test test test test test'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - cy.get('app-send ion-input button').click(); + cy.get('app-send-component ion-input input').should('have.value', mockData); + cy.get('app-send-component ion-input button').click(); - cy.get('app-send ion-input input').should('have.value', ''); + cy.get('app-send-component ion-input input').should('have.value', ''); }); it('should send input with default options', () => { - const data = 'test test test test test test test test test test'; - const formattedData = `${data}\n`; + const mockData = 'test test test test test test test test test test'; + const formattedData = `${mockData}\n`; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); - cy.get('app-send ion-button').contains('Send').click(); + cy.get('app-send-component ion-button').contains('Send').click(); cy.window().then((win) => { cy.wrap(win.electron.serialPort.write).should( @@ -103,62 +65,73 @@ describe('Send component', () => { }); it('should open and close the advanced modal', () => { - cy.get('app-send ion-button ion-icon').parent().click(); + cy.get('app-send-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.get('ion-modal').should('be.visible'); cy.get('ion-modal ion-toolbar ion-button').click(); cy.get('ion-modal').should('not.be.visible'); }); it('should clear input after changing encoding', () => { - const data = 'test test test test test test test test test test'; - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button ion-icon').parent().click(); + const mockData = 'test test test test test test test test test test'; + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); + + cy.get('app-send-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.getAdvancedModalSelectElement( 'send-advanced-modal', 'Encoding' - ).selectOption('Hex'); + ).selectDropdownOption('Hex'); cy.get('ion-modal ion-toolbar ion-button').click(); - cy.get('app-send ion-input input').should('have.value', ''); + cy.get('app-send-component ion-input input').should('have.value', ''); }); it('should format hex input', () => { - const data = 'test test test test test test test test test test'; + const mockData = 'test test test test test test test test test test'; const expectedHexData = 'EE EE EE EE EE'; - cy.get('app-send ion-button ion-icon').parent().click(); + cy.get('app-send-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.getAdvancedModalSelectElement( 'send-advanced-modal', 'Encoding' - ).selectOption('Hex'); + ).selectDropdownOption('Hex'); cy.get('ion-modal ion-toolbar ion-button').click(); - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); - cy.get('app-send ion-input input').should('have.value', expectedHexData); + cy.get('app-send-component ion-input input').should( + 'have.value', + expectedHexData + ); }); it('should send input with hex encoding', () => { - const data = 'test test test test test test test test test test\n\n\n'; + const mockData = 'test test test test test test test test test test\n\n\n'; const formattedData = 'EEEEEEEEEE'; - cy.get('app-send ion-button ion-icon').parent().click(); + cy.get('app-send-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.getAdvancedModalSelectElement( 'send-advanced-modal', 'Encoding' - ).selectOption('Hex'); + ).selectDropdownOption('Hex'); cy.get('ion-modal ion-toolbar ion-button').click(); - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button').contains('Send').click(); + cy.get('app-send-component ion-button').contains('Send').click(); cy.window().then((win) => { cy.wrap(win.electron.serialPort.write).should( @@ -170,25 +143,23 @@ describe('Send component', () => { }); it('should send input with advanced delimiter', () => { - const data = 'test test test test test test test test test test'; - const formattedData = `${data}\r\n`; + const mockData = 'test test test test test test test test test test'; + const formattedData = `${mockData}\r\n`; - cy.get('app-send ion-button ion-icon').parent().click(); + cy.get('app-send-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.getAdvancedModalSelectElement( 'send-advanced-modal', 'Delimiter' - ).selectOption('CRLF (\\r\\n)'); + ).selectDropdownOption('CRLF (\\r\\n)'); cy.get('ion-modal ion-toolbar ion-button').click(); - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); + cy.get('app-send-component ion-input input') + .invoke('val', mockData) + .trigger('input'); - cy.get('app-send ion-button').contains('Send').click(); + cy.get('app-send-component ion-button').contains('Send').click(); cy.window().then((win) => { cy.wrap(win.electron.serialPort.write).should( diff --git a/apps/spie-ui-e2e/src/e2e/serial-port.cy.ts b/apps/spie-ui-e2e/src/e2e/serial-port.cy.ts index c437f87..f503b88 100644 --- a/apps/spie-ui-e2e/src/e2e/serial-port.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/serial-port.cy.ts @@ -1,46 +1,21 @@ -import { type OpenOptions } from '@serialport/bindings-interface'; -import { type SerialPortEvent } from '@spie/types'; - -import { mockElectronAPI } from '../fixtures/mocks/electron-api.mock'; +import { + mockElectronAPI, + mockSerialPortList, +} from '../fixtures/mocks/electron-api.mock'; describe('Serial Port component', () => { - const mockSerialPortList = [ - { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, - { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, - ]; - - let onEventTrigger: ((event: SerialPortEvent) => void) | null; - beforeEach(() => { cy.visit('/'); cy.on('window:before:load', (win) => { - const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; - - win.electron = mockElectronAPI(); - - win.electron.serialPort.list = cy.stub().resolves(mockSerialPortList); - win.electron.serialPort.onEvent = cy - .stub() - .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { - listeners.push(callback); - - onEventTrigger = (serialPortEvent) => { - listeners.forEach((listener) => listener(serialPortEvent)); - }; - - return () => { - const index = listeners.indexOf(callback); - if (index !== -1) { - listeners.splice(index, 1); - } - }; - }); + win.electron = mockElectronAPI(win); }); }); it('should display available serial ports in the dropdown', () => { - cy.get('app-connection [placeholder="Select Serial Port"]').click(); + cy.get( + 'app-connection-component [placeholder="Select Serial Port"]' + ).click(); cy.get('ion-alert .alert-radio-button').should( 'have.length', mockSerialPortList.length @@ -56,11 +31,11 @@ describe('Serial Port component', () => { it('should allow selecting a serial port', () => { const expectedPath = mockSerialPortList[0].path; - cy.get('app-connection [placeholder="Select Serial Port"]').selectOption( - expectedPath - ); + cy.get( + 'app-connection-component [placeholder="Select Serial Port"]' + ).selectDropdownOption(expectedPath); - cy.get('app-connection [placeholder="Select Serial Port"]') + cy.get('app-connection-component [placeholder="Select Serial Port"]') .shadow() .find('.select-text') .should('contain', expectedPath); @@ -69,18 +44,18 @@ describe('Serial Port component', () => { it('should allow selecting a baud rate', () => { const expectedBaudRate = 115200; - cy.get('app-connection [placeholder="Select Baud Rate"]').selectOption( - expectedBaudRate - ); + cy.get( + 'app-connection-component [placeholder="Select Baud Rate"]' + ).selectDropdownOption(expectedBaudRate); - cy.get('app-connection [placeholder="Select Baud Rate"]') + cy.get('app-connection-component [placeholder="Select Baud Rate"]') .shadow() .find('.select-text') .should('contain', expectedBaudRate); }); it('should disable the Connect button when no serial port is selected', () => { - cy.get('app-connection ion-button') + cy.get('app-connection-component ion-button') .contains('Connect') .should('have.class', 'button-disabled'); }); @@ -88,67 +63,38 @@ describe('Serial Port component', () => { it('should enable the Connect button after selecting a port', () => { const expectedPath = mockSerialPortList[0].path; - cy.get('app-connection [placeholder="Select Serial Port"]').selectOption( - expectedPath - ); - cy.get('app-connection ion-button') + cy.get( + 'app-connection-component [placeholder="Select Serial Port"]' + ).selectDropdownOption(expectedPath); + cy.get('app-connection-component ion-button') .contains('Connect') .should('not.have.class', 'button-disabled'); }); it('should correctly call the IPC open and close methods', () => { - const openOptions: OpenOptions = { - path: mockSerialPortList[0].path, - baudRate: 9600, - }; + cy.connect(mockSerialPortList[0].path, 9600); - cy.get('app-connection [placeholder="Select Serial Port"]').selectOption( - openOptions.path - ); - cy.get('app-connection [placeholder="Select Baud Rate"]').selectOption( - openOptions.baudRate - ); - - cy.get('app-connection ion-button').contains('Connect').click(); - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - cy.window().then((win) => { - cy.wrap(win.electron.serialPort.open).should( - 'have.been.calledOnceWith', - Cypress.sinon.match(openOptions) - ); - }); - cy.get('app-connection ion-button') + cy.get('app-connection-component ion-button') .contains('Disconnect') .should('be.visible'); - cy.get('app-connection ion-button').contains('Disconnect').click(); - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'close' }); - } - }); + cy.disconnect(); + cy.window().then((win) => { cy.wrap(win.electron.serialPort.close).should('have.been.calledOnce'); }); - cy.get('app-connection ion-button') + + cy.get('app-connection-component ion-button') .contains('Connect') .should('be.visible'); }); it('should reconnect when baud rate changes', () => { - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); + cy.connect(mockSerialPortList[0].path, 9600); - cy.get('app-connection [placeholder="Select Baud Rate"]').selectOption( - 115200 - ); + cy.get( + 'app-connection-component [placeholder="Select Baud Rate"]' + ).selectDropdownOption(115200); cy.window().then((win) => { cy.wrap(win.electron.serialPort.open).should( @@ -157,26 +103,26 @@ describe('Serial Port component', () => { ); }); - cy.get('app-connection ion-button') + cy.get('app-connection-component ion-button') .contains('Disconnect') .should('be.visible'); }); it('should open and close the advanced modal', () => { - cy.get('app-connection ion-button ion-icon').parent().click(); + cy.get('app-connection-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.get('ion-modal').should('be.visible'); cy.get('ion-modal ion-toolbar ion-button').click(); cy.get('ion-modal').should('not.be.visible'); }); it('should reconnect after changing advanced settings', () => { - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); + cy.connect(mockSerialPortList[0].path, 9600); - cy.get('app-connection ion-button ion-icon').parent().click(); + cy.get('app-connection-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.getAdvancedModalCheckboxElement( 'connection-advanced-modal', @@ -186,7 +132,7 @@ describe('Serial Port component', () => { cy.getAdvancedModalSelectElement( 'connection-advanced-modal', 'Data Bits' - ).selectOption('5'); + ).selectDropdownOption('5'); cy.window().then((win) => { setTimeout(() => { @@ -198,7 +144,7 @@ describe('Serial Port component', () => { ); cy.wrap(win.electron.serialPort.close).should('have.been.calledOnce'); - cy.get('app-connection ion-button') + cy.get('app-connection-component ion-button') .contains('Disconnect') .should('be.visible'); }, 500); diff --git a/apps/spie-ui-e2e/src/e2e/terminal.cy.ts b/apps/spie-ui-e2e/src/e2e/terminal.cy.ts index 81a3f6d..ce79d41 100644 --- a/apps/spie-ui-e2e/src/e2e/terminal.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/terminal.cy.ts @@ -1,84 +1,62 @@ -import { type SerialPortEvent } from '@spie/types'; - -import { mockElectronAPI } from '../fixtures/mocks/electron-api.mock'; +import { + mockElectronAPI, + mockSerialPortList, +} from '../fixtures/mocks/electron-api.mock'; describe('Terminal component', () => { - const mockSerialPortList = [ - { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, - { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, - ]; - - let onEventTrigger: ((event: SerialPortEvent) => void) | null; + const mockData = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'; beforeEach(() => { cy.visit('/'); cy.on('window:before:load', (win) => { - const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; - - win.electron = mockElectronAPI(); - win.electron.serialPort.list = cy.stub().resolves(mockSerialPortList); - - win.electron.serialPort.onEvent = cy - .stub() - .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { - listeners.push(callback); - - onEventTrigger = (serialPortEvent) => { - listeners.forEach((listener) => listener(serialPortEvent)); - }; - - return () => { - const index = listeners.indexOf(callback); - if (index !== -1) { - listeners.splice(index, 1); - } - }; - }); + win.electron = mockElectronAPI(win); }); + + cy.connect(mockSerialPortList[0].path, 9600); }); it('should display data on the terminal', () => { - const data = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ - event: 'data', - data: data, - }); - } + cy.window().then((win) => { + win.onEventTrigger({ + type: 'data', + data: mockData, + }); }); - cy.get('app-terminal ion-textarea textarea').should('contain', data); + cy.get('app-terminal-component ion-textarea textarea').should( + 'contain', + mockData + ); }); it('should clear the terminal', () => { - const data = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ - event: 'data', - data: data, - }); - } + cy.window().then((win) => { + win.onEventTrigger({ + type: 'data', + data: mockData, + }); }); - cy.get('app-terminal ion-button').contains('Clear Terminal').click(); - cy.get('app-terminal ion-textarea textarea').should('contain', ''); + cy.get('app-terminal-component ion-button').contains('Clear').click(); + cy.get('app-terminal-component ion-textarea textarea').should( + 'contain', + '' + ); }); it('should auto scroll when data is emitted', () => { - const data = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ - event: 'data', - data: data, + cy.window().then((win) => { + for (let index = 0; index < 10; index++) { + win.onEventTrigger({ + type: 'data', + data: mockData, }); } }); - cy.get('app-terminal ion-textarea textarea').then((textarea) => { + cy.get('app-terminal-component ion-textarea textarea').then((textarea) => { const scrollTop = textarea[0].scrollTop; const scrollHeight = textarea[0].scrollHeight; const clientHeight = textarea[0].clientHeight; @@ -87,59 +65,90 @@ describe('Terminal component', () => { }); }); + it('should clear the terminal with clear event', () => { + cy.window().then((win) => { + win.onEventTrigger({ + type: 'data', + data: mockData, + }); + }); + + cy.window().then((win) => { + win.onEventTrigger({ + type: 'clear', + }); + }); + + // cy.get('app-terminal-component ion-button').contains('Clear').click(); + cy.get('app-terminal-component ion-textarea textarea').should( + 'contain', + '' + ); + }); + it('should open and close the advanced modal', () => { - cy.get('app-terminal ion-button ion-icon').parent().click(); + cy.get('app-terminal-component ion-button [name="settings-outline"]') + .parent() + .click(); cy.get('ion-modal').should('be.visible'); cy.get('ion-modal ion-toolbar ion-button').click(); cy.get('ion-modal').should('not.be.visible'); }); it('should clear the terminal after changing encoding', () => { - const data = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ - event: 'data', - data: data, + cy.window().then((win) => { + for (let index = 0; index < 10; index++) { + win.onEventTrigger({ + type: 'data', + data: mockData, }); } }); - cy.get('app-terminal ion-button ion-icon').parent().click(); + cy.get('app-terminal-component ion-button [name="settings-outline"') + .parent() + .click(); cy.getAdvancedModalSelectElement( 'terminal-advanced-modal', 'Encoding' - ).selectOption('Hex'); + ).selectDropdownOption('Hex'); - cy.get('app-terminal ion-textarea textarea').should('contain', ''); + cy.get('app-terminal-component ion-textarea textarea').should( + 'contain', + '' + ); }); it('should clear the terminal after changing show timestamps', () => { - const data = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n'; - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ - event: 'data', - data: data, + cy.window().then((win) => { + for (let index = 0; index < 10; index++) { + win.onEventTrigger({ + type: 'data', + data: mockData, }); } }); - cy.get('app-terminal ion-button ion-icon').parent().click(); + cy.get('app-terminal-component ion-button [name="settings-outline"') + .parent() + .click(); cy.getAdvancedModalCheckboxElement( 'terminal-advanced-modal', 'Show Timestamps' ).click(); - cy.get('app-terminal ion-textarea textarea').should('contain', ''); + cy.get('app-terminal-component ion-textarea textarea').should( + 'contain', + '' + ); }); it('should not auto scroll when auto scroll is disabled and data is emitted', () => { let initialScrollTop = 0; - const data = 'test\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\ntest\n'; - - cy.get('app-terminal ion-button ion-icon').parent().click(); + cy.get('app-terminal-component ion-button [name="settings-outline"') + .parent() + .click(); cy.getAdvancedModalCheckboxElement( 'terminal-advanced-modal', 'Auto Scroll' @@ -150,16 +159,16 @@ describe('Terminal component', () => { initialScrollTop = textarea[0].scrollTop; }); - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ - event: 'data', - data: data, + cy.window().then((win) => { + for (let index = 0; index < 10; index++) { + win.onEventTrigger({ + type: 'data', + data: mockData, }); } }); - cy.get('app-terminal ion-textarea textarea').then((textarea) => { + cy.get('app-terminal-component ion-textarea textarea').then((textarea) => { const currentScrollTop = textarea[0].scrollTop; expect(currentScrollTop).to.equal(initialScrollTop); }); diff --git a/apps/spie-ui-e2e/src/e2e/updater.ts b/apps/spie-ui-e2e/src/e2e/updater.ts index e91c231..726cd24 100644 --- a/apps/spie-ui-e2e/src/e2e/updater.ts +++ b/apps/spie-ui-e2e/src/e2e/updater.ts @@ -1,201 +1,3 @@ -import { type SerialPortEvent } from '@spie/types'; - -import { mockElectronAPI } from '../fixtures/mocks/electron-api.mock'; - -describe('Send component', () => { - const mockSerialPortList = [ - { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, - { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, - ]; - - let onEventTrigger: ((event: SerialPortEvent) => void) | null; - - beforeEach(() => { - cy.visit('/'); - - cy.on('window:before:load', (win) => { - const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; - - win.electron = mockElectronAPI(); - win.electron.serialPort.list = cy.stub().resolves(mockSerialPortList); - - win.electron.serialPort.onEvent = cy - .stub() - .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { - listeners.push(callback); - - onEventTrigger = (serialPortEvent) => { - listeners.forEach((listener) => listener(serialPortEvent)); - }; - - return () => { - const index = listeners.indexOf(callback); - if (index !== -1) { - listeners.splice(index, 1); - } - }; - }); - }); - }); - - it('should enable/disable send based on serial port status', () => { - const data = 'test test test test test test test test test test'; - - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button') - .contains('Send') - .should('not.have.class', 'button-disabled'); - - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'close' }); - } - }); - - cy.get('app-send ion-button') - .contains('Send') - .should('have.class', 'button-disabled'); - }); - - it('should clear input after pressing clear input button', () => { - const data = 'test test test test test test test test test test'; - - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - cy.get('app-send ion-input button').click(); - - cy.get('app-send ion-input input').should('have.value', ''); - }); - - it('should send input with default options', () => { - const data = 'test test test test test test test test test test'; - const formattedData = `${data}\n`; - - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button').contains('Send').click(); - - cy.window().then((win) => { - cy.wrap(win.electron.serialPort.write).should( - 'have.been.calledOnceWithExactly', - formattedData, - 'ascii' - ); - }); - }); - - it('should open and close the advanced modal', () => { - cy.get('app-send ion-button ion-icon').parent().click(); - cy.get('ion-modal').should('be.visible'); - cy.get('ion-modal ion-toolbar ion-button').click(); - cy.get('ion-modal').should('not.be.visible'); - }); - - it('should clear input after changing encoding', () => { - const data = 'test test test test test test test test test test'; - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button ion-icon').parent().click(); - cy.getAdvancedModalSelectElement( - 'send-advanced-modal', - 'Encoding' - ).selectOption('Hex'); - cy.get('ion-modal ion-toolbar ion-button').click(); - - cy.get('app-send ion-input input').should('have.value', ''); - }); - - it('should format hex input', () => { - const data = 'test test test test test test test test test test'; - const expectedHexData = 'EE EE EE EE EE'; - - cy.get('app-send ion-button ion-icon').parent().click(); - cy.getAdvancedModalSelectElement( - 'send-advanced-modal', - 'Encoding' - ).selectOption('Hex'); - cy.get('ion-modal ion-toolbar ion-button').click(); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-input input').should('have.value', expectedHexData); - }); - - it('should send input with hex encoding', () => { - const data = 'test test test test test test test test test test\n\n\n'; - const formattedData = 'EEEEEEEEEE'; - - cy.get('app-send ion-button ion-icon').parent().click(); - cy.getAdvancedModalSelectElement( - 'send-advanced-modal', - 'Encoding' - ).selectOption('Hex'); - cy.get('ion-modal ion-toolbar ion-button').click(); - - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button').contains('Send').click(); - - cy.window().then((win) => { - cy.wrap(win.electron.serialPort.write).should( - 'have.been.calledOnceWithExactly', - formattedData, - 'hex' - ); - }); - }); - - it('should send input with advanced delimiter', () => { - const data = 'test test test test test test test test test test'; - const formattedData = `${data}\r\n`; - - cy.get('app-send ion-button ion-icon').parent().click(); - cy.getAdvancedModalSelectElement( - 'send-advanced-modal', - 'Delimiter' - ).selectOption('CRLF (\\r\\n)'); - cy.get('ion-modal ion-toolbar ion-button').click(); - - cy.wrap(null).then(() => { - if (onEventTrigger) { - onEventTrigger({ event: 'open' }); - } - }); - - cy.get('app-send ion-input input').invoke('val', data).trigger('input'); - - cy.get('app-send ion-button').contains('Send').click(); - - cy.window().then((win) => { - cy.wrap(win.electron.serialPort.write).should( - 'have.been.calledOnceWithExactly', - formattedData, - 'ascii' - ); - }); - }); +describe('Update', () => { + // TODO: }); diff --git a/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts b/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts index 79212a7..c3aa024 100644 --- a/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts +++ b/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts @@ -1,7 +1,14 @@ -import { type ElectronAPI } from '@spie/types'; +import { type ElectronAPI, type SerialPortEvent } from '@spie/types'; -export function mockElectronAPI(): ElectronAPI { - return { +export const mockSerialPortList = [ + { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, + { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, +]; + +export function mockElectronAPI(win: any): ElectronAPI { + const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; + + const electronAPI: ElectronAPI = { platform: '', quit: cy.stub(), getVersion: cy.stub(), @@ -9,13 +16,33 @@ export function mockElectronAPI(): ElectronAPI { installUpdate: cy.stub(), onUpdateEvent: cy.stub(), serialPort: { - list: cy.stub(), + list: cy.stub().resolves(mockSerialPortList), open: cy.stub(), close: cy.stub(), isOpen: cy.stub().resolves(false), write: cy.stub().resolves(true), setReadEncoding: cy.stub(), - onEvent: cy.stub(), + getReadEncoding: cy.stub().resolves('hex'), + getOpenOptions: cy.stub().resolves(null), + onEvent: cy + .stub() + .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { + listeners.push(callback); + + // Assign the passed `onEventTrigger` function to trigger the events + win.onEventTrigger = (serialPortEvent: SerialPortEvent) => { + listeners.forEach((listener) => listener(serialPortEvent)); + }; + + return () => { + const index = listeners.indexOf(callback); + if (index !== -1) { + listeners.splice(index, 1); + } + }; + }), }, }; + + return electronAPI; } diff --git a/apps/spie-ui-e2e/src/support/commands.ts b/apps/spie-ui-e2e/src/support/commands.ts index 675a427..dda62e0 100644 --- a/apps/spie-ui-e2e/src/support/commands.ts +++ b/apps/spie-ui-e2e/src/support/commands.ts @@ -1,7 +1,15 @@ -export {}; +import { + type DataEvent, + type ElectronAPI, + type SerialPortEvent, +} from '@spie/types'; declare global { namespace Cypress { + interface Window { + electron: ElectronAPI; + onEventTrigger: (serialPortEvent: SerialPortEvent | DataEvent) => void; + } // eslint-disable-next-line @typescript-eslint/no-unused-vars interface Chainable { getAdvancedModalSelectElement( @@ -12,7 +20,9 @@ declare global { modal: string, label: string ): Cypress.Chainable; - selectOption(option: string | number): Cypress.Chainable; + selectDropdownOption(option: string | number): Cypress.Chainable; + connect(path: string, baudRate: number): void; + disconnect(): void; } } } @@ -36,7 +46,7 @@ Cypress.Commands.add( ); Cypress.Commands.add( - 'selectOption', + 'selectDropdownOption', { prevSubject: 'element' }, (subject, option: string | number) => { cy.wrap(subject).click(); @@ -44,3 +54,26 @@ Cypress.Commands.add( cy.get('ion-alert button.alert-button').contains('OK').click(); } ); + +Cypress.Commands.add('connect', (path: string, baudRate: number) => { + cy.get( + 'app-connection-component [placeholder="Select Serial Port"]' + ).selectDropdownOption(path); + cy.get( + 'app-connection-component [placeholder="Select Baud Rate"]' + ).selectDropdownOption(baudRate); + + cy.get('app-connection-component ion-button').contains('Connect').click(); + + cy.window().then((win) => { + win.onEventTrigger({ type: 'open' }); + }); +}); + +Cypress.Commands.add('disconnect', () => { + cy.get('app-connection-component ion-button').contains('Disconnect').click(); + + cy.window().then((win) => { + win.onEventTrigger({ type: 'close' }); + }); +}); diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts index 9ce091c..dd91e13 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.ts +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -11,6 +11,7 @@ import { IonRow, IonText, } from '@ionic/angular/standalone'; +import { type DataEvent } from '@spie/types'; import { type ApexChart, type ApexDataLabels, @@ -24,10 +25,7 @@ import { } from 'ng-apexcharts'; import { BehaviorSubject, Subject, filter, map, merge, tap } from 'rxjs'; -import { - type DataEvent, - SerialPortService, -} from '../../services/serial-port.service'; +import { SerialPortService } from '../../services/serial-port.service'; interface ChartOptions { dataLabels: ApexDataLabels; @@ -91,12 +89,14 @@ export class PlotterComponent { // Split values const values = detectedSeparator - ? data.split(detectedSeparator).map((v) => parseFloat(v)) + ? data + .split(detectedSeparator) + .map((value: string) => parseFloat(value)) : [parseFloat(data)]; // Update series with the correct amount of variables if (this.series().length !== values.length) { - const newSeries = values.map((value, index) => ({ + const newSeries = values.map((value: number, index: number) => ({ name: `Variable ${index + 1}`, data: [{ x: Date.now(), y: value }], })); @@ -113,8 +113,8 @@ export class PlotterComponent { } // Populate data points for each variable - values.forEach((value, variableIndex) => { - variableData[variableIndex].push({ + values.forEach((value: number, index: number) => { + variableData[index].push({ x: Date.now(), y: value, }); diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.ts b/apps/spie-ui/src/app/components/terminal/terminal.component.ts index 811c375..ca74ec8 100644 --- a/apps/spie-ui/src/app/components/terminal/terminal.component.ts +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.ts @@ -13,13 +13,11 @@ import { IonText, IonTextarea, } from '@ionic/angular/standalone'; +import { type DataEvent } from '@spie/types'; import { BehaviorSubject, Subject, filter, map, merge, tap } from 'rxjs'; import { ElectronService } from '../../services/electron.service'; -import { - type DataEvent, - SerialPortService, -} from '../../services/serial-port.service'; +import { SerialPortService } from '../../services/serial-port.service'; import { TerminalAdvancedComponent } from '../terminal-advanced-modal/terminal-advanced-modal.component'; @Component({ diff --git a/apps/spie-ui/src/app/services/serial-port.service.ts b/apps/spie-ui/src/app/services/serial-port.service.ts index fe6703a..d323a15 100644 --- a/apps/spie-ui/src/app/services/serial-port.service.ts +++ b/apps/spie-ui/src/app/services/serial-port.service.ts @@ -1,6 +1,7 @@ import { Injectable, inject, signal } from '@angular/core'; import { toObservable, toSignal } from '@angular/core/rxjs-interop'; import { type OpenOptions } from '@serialport/bindings-interface'; +import { type DataEvent } from '@spie/types'; import { type Observable, Subject, @@ -89,10 +90,3 @@ export class SerialPortService { ) ); } - -export type DataEvent = - | { - type: 'data'; - data: string; - } - | { type: 'clear' }; diff --git a/libs/types/src/lib/electron.d.ts b/libs/types/src/lib/electron.d.ts index 92c083b..05d09f0 100644 --- a/libs/types/src/lib/electron.d.ts +++ b/libs/types/src/lib/electron.d.ts @@ -30,6 +30,8 @@ export type SerialPortEvent = | { type: 'data'; data: string } | { type: 'drain' }; +export type DataEvent = { type: 'data'; data: string } | { type: 'clear' }; + export interface SerialPortAPI { list: () => Promise; open: (openOptions: OpenOptions) => Promise; From b16954bd6a877b698e8712962490dc57e5ac6966 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Mon, 9 Dec 2024 12:56:42 +0930 Subject: [PATCH 06/23] feat(spie-ui): add error handling to auto updated event --- .../update-modal/update-modal.component.html | 2 +- .../update-modal/update-modal.component.ts | 4 + .../src/app/services/electron.service.spec.ts | 94 +++++++++---------- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/apps/spie-ui/src/app/components/update-modal/update-modal.component.html b/apps/spie-ui/src/app/components/update-modal/update-modal.component.html index 2ddd42c..f5b67db 100644 --- a/apps/spie-ui/src/app/components/update-modal/update-modal.component.html +++ b/apps/spie-ui/src/app/components/update-modal/update-modal.component.html @@ -2,7 +2,7 @@ - Transfer Progress + Download Progress diff --git a/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts index 0aa25f0..a510515 100644 --- a/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts +++ b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts @@ -52,6 +52,10 @@ export class UpdateModalComponent { progressInfo = toSignal( this.electronService.onUpdateEvent().pipe( tap(async (autoUpdaterEvent) => { + if (autoUpdaterEvent.type === 'error') { + await this.toasterService.presentErrorToast(autoUpdaterEvent.error); + } + if (autoUpdaterEvent.type === 'checking-for-update') { await this.toasterService.presentInfoToast('Checking for Updates'); } diff --git a/apps/spie-ui/src/app/services/electron.service.spec.ts b/apps/spie-ui/src/app/services/electron.service.spec.ts index 5a58927..f90c5e7 100644 --- a/apps/spie-ui/src/app/services/electron.service.spec.ts +++ b/apps/spie-ui/src/app/services/electron.service.spec.ts @@ -6,11 +6,6 @@ import type { ElectronAPI, SerialPortEvent, } from '@spie/types'; -import { - type ProgressInfo, - type UpdateDownloadedEvent, - type UpdateInfo, -} from 'electron-updater'; import { ElectronService } from './electron.service'; @@ -118,8 +113,10 @@ describe('ElectronService', () => { describe('onUpdateEvent', () => { it('should handle error event', (done) => { - const error = new Error('Test error'); - const mockEvent: AutoUpdaterEvent = { type: 'error', error }; + const mockEvent: AutoUpdaterEvent = { + type: 'error', + error: new Error('Test error'), + }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { callback(mockEvent); @@ -153,17 +150,17 @@ describe('ElectronService', () => { const subscription = service.onUpdateEvent().subscribe(observer); subscription.unsubscribe(); }); + it('should handle update-not-available event', (done) => { - const updateInfo: UpdateInfo = { - version: '1.0.0', - files: [], - path: '/test', - sha512: 'test', - releaseDate: new Date().toISOString(), - }; const mockEvent: AutoUpdaterEvent = { type: 'update-not-available', - updateInfo, + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { @@ -180,17 +177,17 @@ describe('ElectronService', () => { const subscription = service.onUpdateEvent().subscribe(observer); subscription.unsubscribe(); }); + it('should handle update-available event', (done) => { - const updateInfo: UpdateInfo = { - version: '1.0.0', - files: [], - path: '/test', - sha512: 'test', - releaseDate: new Date().toISOString(), - }; const mockEvent: AutoUpdaterEvent = { type: 'update-available', - updateInfo, + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { @@ -207,18 +204,18 @@ describe('ElectronService', () => { const subscription = service.onUpdateEvent().subscribe(observer); subscription.unsubscribe(); }); + it('should handle update-downloaded event', (done) => { - const updateDownloadedEvent: UpdateDownloadedEvent = { - downloadedFile: '/test/test.exe', - version: '1.0.0', - files: [], - path: '/test', - sha512: 'test', - releaseDate: new Date().toISOString(), - }; const mockEvent: AutoUpdaterEvent = { type: 'update-downloaded', - updateDownloadedEvent, + updateDownloadedEvent: { + downloadedFile: '/test/test.exe', + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { @@ -235,17 +232,17 @@ describe('ElectronService', () => { const subscription = service.onUpdateEvent().subscribe(observer); subscription.unsubscribe(); }); + it('should handle download-progress event', (done) => { - const progressInfo: ProgressInfo = { - total: 100, - delta: 1, - transferred: 75.5, - percent: 75.5, - bytesPerSecond: 1115.55, - }; const mockEvent: AutoUpdaterEvent = { type: 'download-progress', - progressInfo, + progressInfo: { + total: 100, + delta: 1, + transferred: 75.5, + percent: 75.5, + bytesPerSecond: 1115.55, + }, }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { @@ -262,17 +259,17 @@ describe('ElectronService', () => { const subscription = service.onUpdateEvent().subscribe(observer); subscription.unsubscribe(); }); + it('should handle update-cancelled event', (done) => { - const updateInfo: UpdateInfo = { - version: '1.0.0', - files: [], - path: '/test', - sha512: 'test', - releaseDate: new Date().toISOString(), - }; const mockEvent: AutoUpdaterEvent = { type: 'update-cancelled', - updateInfo, + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, }; (mockElectronAPI.onUpdateEvent as jest.Mock).mockImplementation( (callback) => { @@ -289,6 +286,7 @@ describe('ElectronService', () => { const subscription = service.onUpdateEvent().subscribe(observer); subscription.unsubscribe(); }); + it('should clean up the listener when unsubscribed', () => { const callback = jest.fn(); (mockElectronAPI.onUpdateEvent as jest.Mock).mockReturnValue(callback); From c9a17f8d7df81a606bc6515e1d667647b9aa09d8 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Mon, 9 Dec 2024 16:34:25 +0930 Subject: [PATCH 07/23] test(spie-ui-e2e): add uto updater test and improve other tests --- .../e2e/{serial-port.cy.ts => connect.cy.ts} | 13 +- apps/spie-ui-e2e/src/e2e/send.cy.ts | 11 +- apps/spie-ui-e2e/src/e2e/terminal.cy.ts | 29 +- apps/spie-ui-e2e/src/e2e/updater.cy.ts | 266 ++++++++++++++++++ apps/spie-ui-e2e/src/e2e/updater.ts | 3 - .../src/fixtures/mocks/electron-api.mock.ts | 72 +++-- apps/spie-ui-e2e/src/support/commands.ts | 10 +- 7 files changed, 364 insertions(+), 40 deletions(-) rename apps/spie-ui-e2e/src/e2e/{serial-port.cy.ts => connect.cy.ts} (92%) create mode 100644 apps/spie-ui-e2e/src/e2e/updater.cy.ts delete mode 100644 apps/spie-ui-e2e/src/e2e/updater.ts diff --git a/apps/spie-ui-e2e/src/e2e/serial-port.cy.ts b/apps/spie-ui-e2e/src/e2e/connect.cy.ts similarity index 92% rename from apps/spie-ui-e2e/src/e2e/serial-port.cy.ts rename to apps/spie-ui-e2e/src/e2e/connect.cy.ts index f503b88..e897dc7 100644 --- a/apps/spie-ui-e2e/src/e2e/serial-port.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/connect.cy.ts @@ -3,16 +3,20 @@ import { mockSerialPortList, } from '../fixtures/mocks/electron-api.mock'; -describe('Serial Port component', () => { +describe('Connect routine', () => { beforeEach(() => { cy.visit('/'); cy.on('window:before:load', (win) => { win.electron = mockElectronAPI(win); }); + + cy.window().should((win) => { + expect(win.onSerialPortEventTrigger).to.be.a('function'); + }); }); - it('should display available serial ports in the dropdown', () => { + it('should show available serial ports in the dropdown', () => { cy.get( 'app-connection-component [placeholder="Select Serial Port"]' ).click(); @@ -112,7 +116,10 @@ describe('Serial Port component', () => { cy.get('app-connection-component ion-button [name="settings-outline"]') .parent() .click(); - cy.get('ion-modal').should('be.visible'); + cy.get('ion-modal ion-toolbar ion-title').should( + 'contain', + 'Advanced Connection Settings' + ); cy.get('ion-modal ion-toolbar ion-button').click(); cy.get('ion-modal').should('not.be.visible'); }); diff --git a/apps/spie-ui-e2e/src/e2e/send.cy.ts b/apps/spie-ui-e2e/src/e2e/send.cy.ts index abad9dc..491e06b 100644 --- a/apps/spie-ui-e2e/src/e2e/send.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/send.cy.ts @@ -3,7 +3,7 @@ import { mockSerialPortList, } from '../fixtures/mocks/electron-api.mock'; -describe('Send component', () => { +describe('Send routine', () => { beforeEach(() => { cy.visit('/'); @@ -11,6 +11,10 @@ describe('Send component', () => { win.electron = mockElectronAPI(win); }); + cy.window().should((win) => { + expect(win.onSerialPortEventTrigger).to.be.a('function'); + }); + cy.connect(mockSerialPortList[0].path, 9600); }); @@ -68,7 +72,10 @@ describe('Send component', () => { cy.get('app-send-component ion-button [name="settings-outline"]') .parent() .click(); - cy.get('ion-modal').should('be.visible'); + cy.get('ion-modal ion-toolbar ion-title').should( + 'contain', + 'Advanced Send Settings' + ); cy.get('ion-modal ion-toolbar ion-button').click(); cy.get('ion-modal').should('not.be.visible'); }); diff --git a/apps/spie-ui-e2e/src/e2e/terminal.cy.ts b/apps/spie-ui-e2e/src/e2e/terminal.cy.ts index ce79d41..4b0a13a 100644 --- a/apps/spie-ui-e2e/src/e2e/terminal.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/terminal.cy.ts @@ -3,7 +3,7 @@ import { mockSerialPortList, } from '../fixtures/mocks/electron-api.mock'; -describe('Terminal component', () => { +describe('Terminal routine', () => { const mockData = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'; @@ -14,12 +14,16 @@ describe('Terminal component', () => { win.electron = mockElectronAPI(win); }); + cy.window().should((win) => { + expect(win.onSerialPortEventTrigger).to.be.a('function'); + }); + cy.connect(mockSerialPortList[0].path, 9600); }); it('should display data on the terminal', () => { cy.window().then((win) => { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); @@ -33,7 +37,7 @@ describe('Terminal component', () => { it('should clear the terminal', () => { cy.window().then((win) => { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); @@ -49,7 +53,7 @@ describe('Terminal component', () => { it('should auto scroll when data is emitted', () => { cy.window().then((win) => { for (let index = 0; index < 10; index++) { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); @@ -67,14 +71,14 @@ describe('Terminal component', () => { it('should clear the terminal with clear event', () => { cy.window().then((win) => { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); }); cy.window().then((win) => { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'clear', }); }); @@ -90,7 +94,10 @@ describe('Terminal component', () => { cy.get('app-terminal-component ion-button [name="settings-outline"]') .parent() .click(); - cy.get('ion-modal').should('be.visible'); + cy.get('ion-modal ion-toolbar ion-title').should( + 'contain', + 'Advanced Terminal Settings' + ); cy.get('ion-modal ion-toolbar ion-button').click(); cy.get('ion-modal').should('not.be.visible'); }); @@ -98,7 +105,7 @@ describe('Terminal component', () => { it('should clear the terminal after changing encoding', () => { cy.window().then((win) => { for (let index = 0; index < 10; index++) { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); @@ -122,7 +129,7 @@ describe('Terminal component', () => { it('should clear the terminal after changing show timestamps', () => { cy.window().then((win) => { for (let index = 0; index < 10; index++) { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); @@ -161,7 +168,7 @@ describe('Terminal component', () => { cy.window().then((win) => { for (let index = 0; index < 10; index++) { - win.onEventTrigger({ + win.onSerialPortEventTrigger({ type: 'data', data: mockData, }); @@ -173,4 +180,6 @@ describe('Terminal component', () => { expect(currentScrollTop).to.equal(initialScrollTop); }); }); + + // TODO: PAUSE/CONTINUE }); diff --git a/apps/spie-ui-e2e/src/e2e/updater.cy.ts b/apps/spie-ui-e2e/src/e2e/updater.cy.ts new file mode 100644 index 0000000..c250c67 --- /dev/null +++ b/apps/spie-ui-e2e/src/e2e/updater.cy.ts @@ -0,0 +1,266 @@ +import { type AutoUpdaterEvent } from '@spie/types'; + +import { mockElectronAPI } from '../fixtures/mocks/electron-api.mock'; + +describe('Send routine', () => { + beforeEach(() => { + cy.visit('/'); + + cy.on('window:before:load', (win) => { + win.electron = mockElectronAPI(win); + }); + + cy.window().should((win) => { + expect(win.onSerialPortEventTrigger).to.be.a('function'); + expect(win.onAutoUpdaterEventTrigger).to.be.a('function'); + }); + }); + + it('should handle error event ', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'error', + error: new Error('Test error'), + }; + + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-toast') + .should('have.attr', 'color', 'danger') + .then(console.log); + + cy.get('ion-toast') + .shadow() + .find('.toast-header') + .should('contain', 'Error'); + + cy.get('ion-toast') + .shadow() + .find('.toast-content') + .should('contain', mockEvent.error); + }); + + it('should handle checking-for-update event ', () => { + const mockEvent: AutoUpdaterEvent = { type: 'checking-for-update' }; + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-toast') + .shadow() + .find('.toast-header') + .should('contain', 'Checking for Updates'); + }); + + it('should handle update-not-available event', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'update-not-available', + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-toast') + .shadow() + .find('.toast-header') + .should('contain', 'No Updates Available'); + }); + + it('should handle update-available event', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'update-available', + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-alert') + .find('.alert-head') + .should('contain', 'Update Available for Download'); + cy.get('ion-alert') + .find('.alert-message') + .should( + 'contain', + `Version ${mockEvent.updateInfo.version} is ready for download.` + ); + }); + + it('should handle download button click', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'update-available', + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-alert button').contains('Download').click(); + + cy.window().then((win) => { + cy.wrap(win.electron.downloadUpdate).should('have.been.calledOnce'); + }); + }); + + it('should handle update-downloaded event', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'update-downloaded', + updateDownloadedEvent: { + downloadedFile: '/test/test.exe', + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-alert') + .find('.alert-head') + .should('contain', 'Update Ready to Install'); + cy.get('ion-alert') + .find('.alert-message') + .should( + 'contain', + `Version ${mockEvent.updateDownloadedEvent.version} is ready to install.` + ); + }); + + it('should handle install button click', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'update-downloaded', + updateDownloadedEvent: { + downloadedFile: '/test/test.exe', + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-alert button').contains('Install').click(); + + cy.window().then((win) => { + cy.wrap(win.electron.installUpdate).should('have.been.calledOnce'); + }); + }); + + it('should handle download-progress event', () => { + const mockUpdateAvailableEvent: AutoUpdaterEvent = { + type: 'update-available', + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + const mockDownloadProgressEvent: AutoUpdaterEvent = { + type: 'download-progress', + progressInfo: { + total: 100, + delta: 1, + transferred: 75.5, + percent: 25, + bytesPerSecond: 725, + }, + }; + + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockUpdateAvailableEvent); + win.onAutoUpdaterEventTrigger(mockDownloadProgressEvent); + }); + + cy.get('ion-alert button').contains('Download').click(); + + cy.get('ion-modal ion-toolbar ion-title').should( + 'contain', + 'Download Progress' + ); + cy.get('ion-modal ion-content ion-list') + .contains('Total Size') + .parent() + .find('ion-note') + .should('contain', `${mockDownloadProgressEvent.progressInfo.total}`); + cy.get('ion-modal ion-content ion-list') + .contains('Transferred') + .parent() + .find('ion-note') + .should( + 'contain', + `${mockDownloadProgressEvent.progressInfo.transferred}` + ); + cy.get('ion-modal ion-content ion-list') + .contains('Speed') + .parent() + .find('ion-note') + .should( + 'contain', + `${mockDownloadProgressEvent.progressInfo.bytesPerSecond}` + ); + cy.get('ion-modal ion-content ion-list') + .contains('Progress') + .parent() + .find('ion-note') + .should('contain', `${mockDownloadProgressEvent.progressInfo.percent}`); + }); + + it('should handle update-cancelled event ', () => { + const mockEvent: AutoUpdaterEvent = { + type: 'update-cancelled', + updateInfo: { + version: '1.0.0', + files: [], + path: '/test', + sha512: 'test', + releaseDate: new Date().toISOString(), + }, + }; + cy.window().then((win) => { + win.onAutoUpdaterEventTrigger(mockEvent); + }); + + cy.get('ion-toast') + .should('have.attr', 'color', 'danger') + .then(console.log); + cy.get('ion-toast') + .shadow() + .find('.toast-header') + .should('contain', 'Error'); + cy.get('ion-toast') + .shadow() + .find('.toast-content') + .should('contain', 'Update Cancelled'); + }); +}); diff --git a/apps/spie-ui-e2e/src/e2e/updater.ts b/apps/spie-ui-e2e/src/e2e/updater.ts deleted file mode 100644 index 726cd24..0000000 --- a/apps/spie-ui-e2e/src/e2e/updater.ts +++ /dev/null @@ -1,3 +0,0 @@ -describe('Update', () => { - // TODO: -}); diff --git a/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts b/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts index c3aa024..6af33c1 100644 --- a/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts +++ b/apps/spie-ui-e2e/src/fixtures/mocks/electron-api.mock.ts @@ -1,12 +1,22 @@ -import { type ElectronAPI, type SerialPortEvent } from '@spie/types'; +import { + type AutoUpdaterEvent, + type DataEvent, + type ElectronAPI, + type SerialPortEvent, +} from '@spie/types'; export const mockSerialPortList = [ { path: '/dev/ttyUSB0', manufacturer: 'Manufacturer1' }, { path: '/dev/ttyUSB1', manufacturer: 'Manufacturer2' }, ]; -export function mockElectronAPI(win: any): ElectronAPI { - const listeners: Array<(serialPortEvent: SerialPortEvent) => void> = []; +export function mockElectronAPI(win: Cypress.AUTWindow): ElectronAPI { + const onSerialPortEventListeners: Array< + (serialPortEvent: SerialPortEvent | DataEvent) => void + > = []; + const onAutoUpdaterEventTriggerListeners: Array< + (autoUpdaterEvent: AutoUpdaterEvent) => void + > = []; const electronAPI: ElectronAPI = { platform: '', @@ -14,7 +24,26 @@ export function mockElectronAPI(win: any): ElectronAPI { getVersion: cy.stub(), downloadUpdate: cy.stub(), installUpdate: cy.stub(), - onUpdateEvent: cy.stub(), + onUpdateEvent: cy + .stub() + .callsFake((callback: (autoUpdaterEvent: AutoUpdaterEvent) => void) => { + onAutoUpdaterEventTriggerListeners.push(callback); + + win.onAutoUpdaterEventTrigger = ( + autoUpdaterEvent: AutoUpdaterEvent + ) => { + onAutoUpdaterEventTriggerListeners.forEach((listener) => + listener(autoUpdaterEvent) + ); + }; + + return () => { + const index = onAutoUpdaterEventTriggerListeners.indexOf(callback); + if (index !== -1) { + onAutoUpdaterEventTriggerListeners.splice(index, 1); + } + }; + }), serialPort: { list: cy.stub().resolves(mockSerialPortList), open: cy.stub(), @@ -26,21 +55,26 @@ export function mockElectronAPI(win: any): ElectronAPI { getOpenOptions: cy.stub().resolves(null), onEvent: cy .stub() - .callsFake((callback: (serialPortEvent: SerialPortEvent) => void) => { - listeners.push(callback); - - // Assign the passed `onEventTrigger` function to trigger the events - win.onEventTrigger = (serialPortEvent: SerialPortEvent) => { - listeners.forEach((listener) => listener(serialPortEvent)); - }; - - return () => { - const index = listeners.indexOf(callback); - if (index !== -1) { - listeners.splice(index, 1); - } - }; - }), + .callsFake( + ( + callback: (serialPortEvent: SerialPortEvent | DataEvent) => void + ) => { + onSerialPortEventListeners.push(callback); + + win.onSerialPortEventTrigger = (serialPortEvent) => { + onSerialPortEventListeners.forEach((listener) => + listener(serialPortEvent) + ); + }; + + return () => { + const index = onSerialPortEventListeners.indexOf(callback); + if (index !== -1) { + onSerialPortEventListeners.splice(index, 1); + } + }; + } + ), }, }; diff --git a/apps/spie-ui-e2e/src/support/commands.ts b/apps/spie-ui-e2e/src/support/commands.ts index dda62e0..50a1ae9 100644 --- a/apps/spie-ui-e2e/src/support/commands.ts +++ b/apps/spie-ui-e2e/src/support/commands.ts @@ -1,4 +1,5 @@ import { + type AutoUpdaterEvent, type DataEvent, type ElectronAPI, type SerialPortEvent, @@ -8,7 +9,10 @@ declare global { namespace Cypress { interface Window { electron: ElectronAPI; - onEventTrigger: (serialPortEvent: SerialPortEvent | DataEvent) => void; + onAutoUpdaterEventTrigger: (autoUpdaterEvent: AutoUpdaterEvent) => void; + onSerialPortEventTrigger: ( + serialPortEvent: SerialPortEvent | DataEvent + ) => void; } // eslint-disable-next-line @typescript-eslint/no-unused-vars interface Chainable { @@ -66,7 +70,7 @@ Cypress.Commands.add('connect', (path: string, baudRate: number) => { cy.get('app-connection-component ion-button').contains('Connect').click(); cy.window().then((win) => { - win.onEventTrigger({ type: 'open' }); + win.onSerialPortEventTrigger({ type: 'open' }); }); }); @@ -74,6 +78,6 @@ Cypress.Commands.add('disconnect', () => { cy.get('app-connection-component ion-button').contains('Disconnect').click(); cy.window().then((win) => { - win.onEventTrigger({ type: 'close' }); + win.onSerialPortEventTrigger({ type: 'close' }); }); }); From 54b0e0329320258d081ced8359c9a1425531d5be Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Mon, 9 Dec 2024 16:57:24 +0930 Subject: [PATCH 08/23] build(repo): fix nx cloud issues --- .github/workflows/cd.yml | 3 +++ .github/workflows/ci.yml | 3 +++ .github/workflows/release.yml | 3 +++ .gitignore | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 5dbb46d..c4ab3d9 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -5,6 +5,9 @@ on: branches: - main +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: cd: runs-on: ubuntu-latest diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f331bc6..6931f44 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,9 @@ on: branches: - dev +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: ci: runs-on: ubuntu-latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 53cc600..b6a5713 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,9 @@ on: release: types: [created] +env: + NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }} + jobs: build: runs-on: ${{ matrix.os }} diff --git a/.gitignore b/.gitignore index 344d7d7..72f360c 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,4 @@ Thumbs.db *.env* # act -.actrc.* +.act* From bc285cfe62b1e3acdd088f5a9e4bd546217c86cd Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 10 Dec 2024 23:49:13 +0930 Subject: [PATCH 09/23] test(spie-ui-e2e): add plotter test --- apps/spie-ui-e2e/src/e2e/plotter.cy.ts | 257 ++++++++++++++++++ .../src/fixtures/plotOneVariable.json | 107 ++++++++ .../src/fixtures/plotThreeVariables.json | 107 ++++++++ apps/spie-ui-e2e/tsconfig.json | 4 +- 4 files changed, 474 insertions(+), 1 deletion(-) create mode 100644 apps/spie-ui-e2e/src/e2e/plotter.cy.ts create mode 100644 apps/spie-ui-e2e/src/fixtures/plotOneVariable.json create mode 100644 apps/spie-ui-e2e/src/fixtures/plotThreeVariables.json diff --git a/apps/spie-ui-e2e/src/e2e/plotter.cy.ts b/apps/spie-ui-e2e/src/e2e/plotter.cy.ts new file mode 100644 index 0000000..e2904db --- /dev/null +++ b/apps/spie-ui-e2e/src/e2e/plotter.cy.ts @@ -0,0 +1,257 @@ +import { + mockElectronAPI, + mockSerialPortList, +} from '../fixtures/mocks/electron-api.mock'; +import plotOneVariable from '../fixtures/plotOneVariable.json'; +import plotThreeVariables from '../fixtures/plotThreeVariables.json'; + +describe('Plotter routine', () => { + before(() => { + cy.fixture('plotOneVariable').then((data) => { + expect(plotOneVariable).to.deep.equal(data); + }); + cy.fixture('plotThreeVariables').then((data) => { + expect(plotThreeVariables).to.deep.equal(data); + }); + }); + + beforeEach(() => { + cy.visit('/'); + + cy.on('window:before:load', (win) => { + win.electron = mockElectronAPI(win); + }); + + // Ensure onSerialPortEventTrigger is loaded + cy.window().should((win) => { + expect(win.onSerialPortEventTrigger).to.be.a('function'); + }); + + // Navigate to plotter tab + cy.get('ion-tab-button').contains('Plotter').parent().click(); + cy.get('app-plotter-component').should('not.have.class', 'ion-page-hidden'); + + // Mock connection + cy.connect(mockSerialPortList[0].path, 9600); + cy.get('ion-tabs ion-accordion').contains('Connection').parent().click(); + }); + + it('should render the chart', () => { + cy.get('apx-chart').should('exist'); + cy.get('.apexcharts-canvas').should('be.visible'); + }); + + it('should render series', () => { + const numberOfPoints = 2; + const mockEventData = plotOneVariable.eventData.slice(0, numberOfPoints); + const numberOfSeries = plotOneVariable.numberOfSeries; + + cy.window() + .then((win) => { + return new Promise((resolve) => { + // Mock data event with numberOfPoints point 50ms apart + mockEventData.forEach((data, index) => { + setTimeout(() => { + win.onSerialPortEventTrigger({ + type: 'data', + data: data, + }); + + if (index === mockEventData.length - 1) { + resolve(); + } + }, index * 50); + }); + }); + }) + .then(() => { + cy.get('apx-chart svg path.apexcharts-line').should( + 'have.length', + numberOfSeries + ); + }); + }); + + it('should render tooltips', () => { + const numberOfPoints = 2; + const mockEventData = plotOneVariable.eventData.slice(0, numberOfPoints); + + cy.window() + .then((win) => { + return new Promise((resolve) => { + // Mock data event with numberOfPoints point 50ms apart + mockEventData.forEach((data, index) => { + setTimeout(() => { + win.onSerialPortEventTrigger({ + type: 'data', + data: data, + }); + + if (index === mockEventData.length - 1) { + resolve(); + } + }, index * 50); + }); + }); + }) + .then(() => { + // Pause data stream (to enable tooltips) + cy.get('app-plotter-component ion-button').contains('Pause').click(); + + // Trigger tooltip + cy.get('.apexcharts-canvas').trigger('mousemove', { + clientX: 100, + clientY: 150, + }); + + // Ensure the tooltip is visible and active + cy.get('.apexcharts-tooltip').and('have.class', 'apexcharts-active'); + }); + }); + + it('should render labels and values for multiple variables', () => { + const numberOfPoints = 2; + const mockEventData = plotThreeVariables.eventData.slice(0, numberOfPoints); + const mockSeries = plotThreeVariables.series.slice(0, numberOfPoints); + + cy.window() + .then((win) => { + return new Promise((resolve) => { + // Mock data event with numberOfPoints point 50ms apart + mockEventData.forEach((data, index) => { + setTimeout(() => { + win.onSerialPortEventTrigger({ + type: 'data', + data: data, + }); + + if (index === mockEventData.length - 1) { + resolve(); + } + }, index * 50); + }); + }); + }) + .then(() => { + // Pause data stream (to enable tooltips) + cy.get('app-plotter-component ion-button').contains('Pause').click(); + + // Test labels and values + mockSeries.forEach((points, pointsIndex) => { + // Move mouse to estimated tooltip position + cy.get('.apexcharts-canvas').trigger('mousemove', { + clientX: 100 + (pointsIndex * 1000) / numberOfPoints, + clientY: 150, + }); + + points.forEach((point, pointIndex) => { + // Ensure the label are correct + cy.get('.apexcharts-tooltip-text-y-label').should( + 'contain', + `Variable ${pointIndex + 1}` + ); + + // Ensure the values are correct + cy.get('.apexcharts-tooltip-text-y-value').should('contain', point); + }); + }); + }); + }); + + it('should render multiple variables and large series', () => { + const mockEventData = plotThreeVariables.eventData; + const mockSeries = plotThreeVariables.series; + + cy.window() + .then((win) => { + return new Promise((resolve) => { + // Mock data event with numberOfPoints point 50ms apart + mockEventData.forEach((data, index) => { + setTimeout(() => { + win.onSerialPortEventTrigger({ + type: 'data', + data: data, + }); + + if (index === mockEventData.length - 1) { + resolve(); + } + }, index * 50); + }); + }); + }) + .then(() => { + // Pause data stream (to enable tooltips) + cy.get('app-plotter-component ion-button').contains('Pause').click(); + + // INFO: hacky way to wait until the canvas has finished updating from stream pause + cy.get('.apexcharts-canvas').invoke('width').should('be.below', 940); + + // Select the first path element and extract X coordinates + cy.get('g.apexcharts-series path.apexcharts-line') + .first() + .then(($path) => { + const pageOffset = 85; + const pathData = $path.attr('d'); + + const xCoordinates = (pathData as string) + .split('L') + .map((segment, index, array) => { + const [x] = segment + .trim() + .replace('M', '') + .split(' ') + .map(Number); + + // If it's the last element in the array, adjust the X coordinate + if (index === array.length - 1) { + return x + pageOffset - 1; + } + + // Otherwise, add the pageOffset to the X value + return x + pageOffset; + }) + .filter((x) => !isNaN(x)); // Filter out NaN values + + // Test labels and values + mockSeries.forEach((points, pointsIndex) => { + // // Helper for debug + // cy.get('body').then(($body) => { + // const refCircle = document.createElement('div'); + // refCircle.style.position = 'absolute'; + // refCircle.style.left = `${xCoordinates[pointsIndex]}px`; + // refCircle.style.top = `${150}px`; + // refCircle.style.width = '5px'; + // refCircle.style.height = '5px'; + // refCircle.style.borderRadius = '50%'; + // refCircle.style.backgroundColor = 'red'; // Red for visibility + // refCircle.style.zIndex = '9999'; // High z-index to appear on top + + // // Append the circle to the body to mark the inferred points + // $body[0].appendChild(refCircle); + // }); + + // Move mouse to estimated tooltip position + cy.get('.apexcharts-canvas').trigger('mousemove', { + clientX: xCoordinates[pointsIndex], + clientY: 150, + }); + + points.forEach((point, pointIndex) => { + // Ensure the label is correct + cy.get('.apexcharts-tooltip-text-y-label').should( + 'contain', + `Variable ${pointIndex + 1}` + ); + + // Ensure the values are correct + cy.get('.apexcharts-tooltip-text-y-value').should( + 'contain', + point + ); + }); + }); + }); + }); + }); +}); diff --git a/apps/spie-ui-e2e/src/fixtures/plotOneVariable.json b/apps/spie-ui-e2e/src/fixtures/plotOneVariable.json new file mode 100644 index 0000000..2e6ef26 --- /dev/null +++ b/apps/spie-ui-e2e/src/fixtures/plotOneVariable.json @@ -0,0 +1,107 @@ +{ + "eventData": [ + "0.00\n", + "1.25\n", + "2.49\n", + "3.68\n", + "4.82\n", + "5.88\n", + "6.85\n", + "7.71\n", + "8.44\n", + "9.05\n", + "9.51\n", + "9.82\n", + "9.98\n", + "9.98\n", + "9.82\n", + "9.51\n", + "9.05\n", + "8.44\n", + "7.71\n", + "6.85\n", + "5.88\n", + "4.82\n", + "3.68\n", + "2.49\n", + "1.25\n", + "0.00\n", + "-1.25\n", + "-2.49\n", + "-3.68\n", + "-4.82\n", + "-5.88\n", + "-6.85\n", + "-7.71\n", + "-8.44\n", + "-9.05\n", + "-9.51\n", + "-9.82\n", + "-9.98\n", + "-9.98\n", + "-9.82\n", + "-9.51\n", + "-9.05\n", + "-8.44\n", + "-7.71\n", + "-6.85\n", + "-5.88\n", + "-4.82\n", + "-3.68\n", + "-2.49\n", + "-1.25\n" + ], + "series": [ + [0.0], + [1.25], + [2.49], + [3.68], + [4.82], + [5.88], + [6.85], + [7.71], + [8.44], + [9.05], + [9.51], + [9.82], + [9.98], + [9.98], + [9.82], + [9.51], + [9.05], + [8.44], + [7.71], + [6.85], + [5.88], + [4.82], + [3.68], + [2.49], + [1.25], + [0.0], + [-1.25], + [-2.49], + [-3.68], + [-4.82], + [-5.88], + [-6.85], + [-7.71], + [-8.44], + [-9.05], + [-9.51], + [-9.82], + [-9.98], + [-9.98], + [-9.82], + [-9.51], + [-9.05], + [-8.44], + [-7.71], + [-6.85], + [-5.88], + [-4.82], + [-3.68], + [-2.49], + [-1.25] + ], + "numberOfSeries": 1 +} diff --git a/apps/spie-ui-e2e/src/fixtures/plotThreeVariables.json b/apps/spie-ui-e2e/src/fixtures/plotThreeVariables.json new file mode 100644 index 0000000..ffa4a57 --- /dev/null +++ b/apps/spie-ui-e2e/src/fixtures/plotThreeVariables.json @@ -0,0 +1,107 @@ +{ + "eventData": [ + "0.00\t8.66\t-8.66\n", + "1.25\t7.97\t-9.22\n", + "2.49\t7.14\t-9.63\n", + "3.68\t6.21\t-9.89\n", + "4.82\t5.18\t-10.00\n", + "5.88\t4.07\t-9.95\n", + "6.85\t2.89\t-9.74\n", + "7.71\t1.67\t-9.37\n", + "8.44\t0.42\t-8.86\n", + "9.05\t-0.84\t-8.21\n", + "9.51\t-2.08\t-7.43\n", + "9.82\t-3.29\t-6.53\n", + "9.98\t-4.45\t-5.53\n", + "9.98\t-5.53\t-4.45\n", + "9.82\t-6.53\t-3.29\n", + "9.51\t-7.43\t-2.08\n", + "9.05\t-8.21\t-0.84\n", + "8.44\t-8.86\t0.42\n", + "7.71\t-9.37\t1.67\n", + "6.85\t-9.74\t2.89\n", + "5.88\t-9.95\t4.07\n", + "4.82\t-10.00\t5.18\n", + "3.68\t-9.89\t6.21\n", + "2.49\t-9.63\t7.14\n", + "1.25\t-9.22\t7.97\n", + "0.00\t-8.66\t8.66\n", + "-1.25\t-7.97\t9.22\n", + "-2.49\t-7.14\t9.63\n", + "-3.68\t-6.21\t9.89\n", + "-4.82\t-5.18\t10.00\n", + "-5.88\t-4.07\t9.95\n", + "-6.85\t-2.89\t9.74\n", + "-7.71\t-1.67\t9.37\n", + "-8.44\t-0.42\t8.86\n", + "-9.05\t0.84\t8.21\n", + "-9.51\t2.08\t7.43\n", + "-9.82\t3.29\t6.53\n", + "-9.98\t4.45\t5.53\n", + "-9.98\t5.53\t4.45\n", + "-9.82\t6.53\t3.29\n", + "-9.51\t7.43\t2.08\n", + "-9.05\t8.21\t0.84\n", + "-8.44\t8.86\t-0.42\n", + "-7.71\t9.37\t-1.67\n", + "-6.85\t9.74\t-2.89\n", + "-5.88\t9.95\t-4.07\n", + "-4.82\t10.00\t-5.18\n", + "-3.68\t9.89\t-6.21\n", + "-2.49\t9.63\t-7.14\n", + "-1.25\t9.22\t-7.97\n" + ], + "series": [ + [0.0, 8.66, -8.66], + [1.25, 7.97, -9.22], + [2.49, 7.14, -9.63], + [3.68, 6.21, -9.89], + [4.82, 5.18, -10.0], + [5.88, 4.07, -9.95], + [6.85, 2.89, -9.74], + [7.71, 1.67, -9.37], + [8.44, 0.42, -8.86], + [9.05, -0.84, -8.21], + [9.51, -2.08, -7.43], + [9.82, -3.29, -6.53], + [9.98, -4.45, -5.53], + [9.98, -5.53, -4.45], + [9.82, -6.53, -3.29], + [9.51, -7.43, -2.08], + [9.05, -8.21, -0.84], + [8.44, -8.86, 0.42], + [7.71, -9.37, 1.67], + [6.85, -9.74, 2.89], + [5.88, -9.95, 4.07], + [4.82, -10.0, 5.18], + [3.68, -9.89, 6.21], + [2.49, -9.63, 7.14], + [1.25, -9.22, 7.97], + [0.0, -8.66, 8.66], + [-1.25, -7.97, 9.22], + [-2.49, -7.14, 9.63], + [-3.68, -6.21, 9.89], + [-4.82, -5.18, 10.0], + [-5.88, -4.07, 9.95], + [-6.85, -2.89, 9.74], + [-7.71, -1.67, 9.37], + [-8.44, -0.42, 8.86], + [-9.05, 0.84, 8.21], + [-9.51, 2.08, 7.43], + [-9.82, 3.29, 6.53], + [-9.98, 4.45, 5.53], + [-9.98, 5.53, 4.45], + [-9.82, 6.53, 3.29], + [-9.51, 7.43, 2.08], + [-9.05, 8.21, 0.84], + [-8.44, 8.86, -0.42], + [-7.71, 9.37, -1.67], + [-6.85, 9.74, -2.89], + [-5.88, 9.95, -4.07], + [-4.82, 10.0, -5.18], + [-3.68, 9.89, -6.21], + [-2.49, 9.63, -7.14], + [-1.25, 9.22, -7.97] + ], + "numberOfSeries": 3 +} diff --git a/apps/spie-ui-e2e/tsconfig.json b/apps/spie-ui-e2e/tsconfig.json index 2a012dc..a62f8e8 100644 --- a/apps/spie-ui-e2e/tsconfig.json +++ b/apps/spie-ui-e2e/tsconfig.json @@ -11,7 +11,9 @@ "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true + "noFallthroughCasesInSwitch": true, + "resolveJsonModule": true, + "esModuleInterop": true }, "include": [ "**/*.ts", From bf7aa53c3122964c1307b085521756fac6ba8a40 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Sat, 14 Dec 2024 11:44:19 +0930 Subject: [PATCH 10/23] test(spie-ui-e2e): fix plotter test --- apps/spie-ui-e2e/src/e2e/plotter.cy.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/spie-ui-e2e/src/e2e/plotter.cy.ts b/apps/spie-ui-e2e/src/e2e/plotter.cy.ts index e2904db..77fabe4 100644 --- a/apps/spie-ui-e2e/src/e2e/plotter.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/plotter.cy.ts @@ -161,6 +161,8 @@ describe('Plotter routine', () => { it('should render multiple variables and large series', () => { const mockEventData = plotThreeVariables.eventData; const mockSeries = plotThreeVariables.series; + const chartStartOffset = 89; // Estimated offset to the first tooltip + const chartEndOffset = 9; // Estimated offset to the last tooltip cy.window() .then((win) => { @@ -185,13 +187,16 @@ describe('Plotter routine', () => { cy.get('app-plotter-component ion-button').contains('Pause').click(); // INFO: hacky way to wait until the canvas has finished updating from stream pause - cy.get('.apexcharts-canvas').invoke('width').should('be.below', 940); + // eslint-disable-next-line cypress/no-unnecessary-waiting + cy.get('.apexcharts-canvas') + .invoke('width') + .should('be.below', 940) + .wait(500); // Select the first path element and extract X coordinates cy.get('g.apexcharts-series path.apexcharts-line') .first() .then(($path) => { - const pageOffset = 85; const pathData = $path.attr('d'); const xCoordinates = (pathData as string) @@ -205,11 +210,11 @@ describe('Plotter routine', () => { // If it's the last element in the array, adjust the X coordinate if (index === array.length - 1) { - return x + pageOffset - 1; + return x + chartStartOffset - chartEndOffset; } // Otherwise, add the pageOffset to the X value - return x + pageOffset; + return x + chartStartOffset; }) .filter((x) => !isNaN(x)); // Filter out NaN values From 0cfe278fc7505429a74ccce6e1a816c5d77afc55 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Sat, 14 Dec 2024 11:44:35 +0930 Subject: [PATCH 11/23] build(repo): fix Nx cache issues --- nx.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nx.json b/nx.json index 7960183..85a6b2d 100644 --- a/nx.json +++ b/nx.json @@ -98,5 +98,6 @@ "createRelease": "github" } } - } + }, + "useLegacyCache": true } From b8700f598d220f0fe1264327aa88aaa72c731101 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Sat, 14 Dec 2024 11:45:48 +0930 Subject: [PATCH 12/23] feat(repo): upgrade to angular 19 --- README.md | 6 +- apps/spie-ui-e2e/src/support/commands.ts | 1 + apps/spie-ui/eslint.config.js | 1 + apps/spie-ui/src/app/app.component.ts | 1 - .../connection-advanced-modal.component.ts | 1 - .../connection/connection.component.ts | 1 - .../components/plotter/plotter.component.ts | 1 - .../send-advanced-modal.component.ts | 1 - .../src/app/components/send/send.component.ts | 1 - .../terminal-advanced-modal.component.ts | 1 - .../components/terminal/terminal.component.ts | 1 - .../update-modal/update-modal.component.ts | 1 - apps/spie-ui/src/app/pages/home/home.page.ts | 1 - .../app/pages/home/plotter/plotter.page.ts | 1 - .../app/pages/home/terminal/terminal.page.ts | 1 - package-lock.json | 7553 ++++++++++------- package.json | 64 +- patches/@nx+eslint-plugin+19.8.10.patch | 28 - 18 files changed, 4576 insertions(+), 3089 deletions(-) delete mode 100644 patches/@nx+eslint-plugin+19.8.10.patch diff --git a/README.md b/README.md index eefaa87..6de37e0 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,10 @@ The repository provides: | Package | version | | -------- | ------- | | nodejs | 22.x.x | -| angular | 18.2.x | +| angular | 19.x.x | | ionic | 8.x.x | -| electron | 31.x.x | -| nx | 19.8.10 | +| electron | 33.3.x | +| nx | 20.2.2 | ## Index diff --git a/apps/spie-ui-e2e/src/support/commands.ts b/apps/spie-ui-e2e/src/support/commands.ts index 50a1ae9..ce85417 100644 --- a/apps/spie-ui-e2e/src/support/commands.ts +++ b/apps/spie-ui-e2e/src/support/commands.ts @@ -6,6 +6,7 @@ import { } from '@spie/types'; declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace namespace Cypress { interface Window { electron: ElectronAPI; diff --git a/apps/spie-ui/eslint.config.js b/apps/spie-ui/eslint.config.js index 4afc7f5..f815729 100644 --- a/apps/spie-ui/eslint.config.js +++ b/apps/spie-ui/eslint.config.js @@ -29,6 +29,7 @@ module.exports = [ 'error', { suffixes: ['Page', 'Component'] }, ], + '@angular-eslint/prefer-standalone': ['error'], }, }, { diff --git a/apps/spie-ui/src/app/app.component.ts b/apps/spie-ui/src/app/app.component.ts index eb568ac..248c2f9 100644 --- a/apps/spie-ui/src/app/app.component.ts +++ b/apps/spie-ui/src/app/app.component.ts @@ -22,7 +22,6 @@ import { selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['./app.component.scss'], - standalone: true, imports: [IonApp, IonRouterOutlet], }) export class AppComponent { diff --git a/apps/spie-ui/src/app/components/connection-advanced-modal/connection-advanced-modal.component.ts b/apps/spie-ui/src/app/components/connection-advanced-modal/connection-advanced-modal.component.ts index 2df966b..a4ef4f8 100644 --- a/apps/spie-ui/src/app/components/connection-advanced-modal/connection-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/components/connection-advanced-modal/connection-advanced-modal.component.ts @@ -25,7 +25,6 @@ import { SerialPortService } from '../../services/serial-port.service'; selector: 'app-connection-advanced-modal-component', templateUrl: 'connection-advanced-modal.component.html', styleUrls: ['./connection-advanced-modal.component.scss'], - standalone: true, imports: [ IonButton, IonButtons, diff --git a/apps/spie-ui/src/app/components/connection/connection.component.ts b/apps/spie-ui/src/app/components/connection/connection.component.ts index 13d312f..359d151 100644 --- a/apps/spie-ui/src/app/components/connection/connection.component.ts +++ b/apps/spie-ui/src/app/components/connection/connection.component.ts @@ -29,7 +29,6 @@ import { ConnectionAdvancedComponent } from '../connection-advanced-modal/connec selector: 'app-connection-component', templateUrl: 'connection.component.html', styleUrls: ['./connection.component.scss'], - standalone: true, imports: [ IonAccordion, IonAccordionGroup, diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts index dd91e13..58c8d8f 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.ts +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -39,7 +39,6 @@ interface ChartOptions { selector: 'app-plotter-component', templateUrl: 'plotter.component.html', styleUrls: ['./plotter.component.scss'], - standalone: true, imports: [ IonButton, IonCard, diff --git a/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts b/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts index 53518d0..3077ed1 100644 --- a/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/components/send-advanced-modal/send-advanced-modal.component.ts @@ -21,7 +21,6 @@ import { SerialPortService } from '../../services/serial-port.service'; selector: 'app-send-advanced-modal-component', templateUrl: 'send-advanced-modal.component.html', styleUrls: ['./send-advanced-modal.component.scss'], - standalone: true, imports: [ IonButton, IonButtons, diff --git a/apps/spie-ui/src/app/components/send/send.component.ts b/apps/spie-ui/src/app/components/send/send.component.ts index 8e81568..fc477d2 100644 --- a/apps/spie-ui/src/app/components/send/send.component.ts +++ b/apps/spie-ui/src/app/components/send/send.component.ts @@ -26,7 +26,6 @@ import { SendAdvancedComponent } from '../send-advanced-modal/send-advanced-moda selector: 'app-send-component', templateUrl: 'send.component.html', styleUrls: ['./send.component.scss'], - standalone: true, imports: [ IonButton, IonCard, diff --git a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts index 8315442..1ca029d 100644 --- a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts @@ -29,7 +29,6 @@ import { SerialPortService } from '../../services/serial-port.service'; selector: 'app-terminal-advanced-modal-component', templateUrl: 'terminal-advanced-modal.component.html', styleUrls: ['./terminal-advanced-modal.component.scss'], - standalone: true, imports: [ IonButton, IonButtons, diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.ts b/apps/spie-ui/src/app/components/terminal/terminal.component.ts index ca74ec8..82af0c5 100644 --- a/apps/spie-ui/src/app/components/terminal/terminal.component.ts +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.ts @@ -24,7 +24,6 @@ import { TerminalAdvancedComponent } from '../terminal-advanced-modal/terminal-a selector: 'app-terminal-component', templateUrl: 'terminal.component.html', styleUrls: ['./terminal.component.scss'], - standalone: true, imports: [ IonButton, IonCard, diff --git a/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts index a510515..6589401 100644 --- a/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts +++ b/apps/spie-ui/src/app/components/update-modal/update-modal.component.ts @@ -27,7 +27,6 @@ import { ToasterService } from '../../services/toaster.service'; selector: 'app-update-modal', templateUrl: 'update-modal.component.html', styleUrls: ['./update-modal.component.scss'], - standalone: true, imports: [ DecimalPipe, IonContent, diff --git a/apps/spie-ui/src/app/pages/home/home.page.ts b/apps/spie-ui/src/app/pages/home/home.page.ts index 2de879f..38c4b5e 100644 --- a/apps/spie-ui/src/app/pages/home/home.page.ts +++ b/apps/spie-ui/src/app/pages/home/home.page.ts @@ -14,7 +14,6 @@ import { UpdateModalComponent } from '../../components/update-modal/update-modal selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['./home.page.scss'], - standalone: true, imports: [ IonIcon, IonLabel, diff --git a/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts index 388af27..96605c8 100644 --- a/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts +++ b/apps/spie-ui/src/app/pages/home/plotter/plotter.page.ts @@ -12,7 +12,6 @@ import { PlotterComponent } from '../../../components/plotter/plotter.component' selector: 'app-plotter', templateUrl: 'plotter.page.html', styleUrls: ['./plotter.page.scss'], - standalone: true, imports: [IonContent, IonHeader, IonTitle, IonToolbar, PlotterComponent], }) export class PlotterPage {} diff --git a/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts index b8e2e16..1c83641 100644 --- a/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts +++ b/apps/spie-ui/src/app/pages/home/terminal/terminal.page.ts @@ -13,7 +13,6 @@ import { TerminalComponent } from '../../../components/terminal/terminal.compone selector: 'app-terminal', templateUrl: 'terminal.page.html', styleUrls: ['./terminal.page.scss'], - standalone: true, imports: [ IonContent, IonHeader, diff --git a/package-lock.json b/package-lock.json index 3bcdb02..c0a3228 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,53 +10,53 @@ "hasInstallScript": true, "license": "MIT", "dependencies": { - "@angular/animations": "~18.2.0", - "@angular/common": "~18.2.0", - "@angular/compiler": "~18.2.0", - "@angular/core": "~18.2.0", - "@angular/forms": "~18.2.0", - "@angular/platform-browser": "~18.2.0", - "@angular/platform-browser-dynamic": "~18.2.0", - "@angular/router": "~18.2.0", + "@angular/animations": "~19.0.0", + "@angular/common": "~19.0.0", + "@angular/compiler": "~19.0.0", + "@angular/core": "~19.0.0", + "@angular/forms": "~19.0.0", + "@angular/platform-browser": "~19.0.0", + "@angular/platform-browser-dynamic": "~19.0.0", + "@angular/router": "~19.0.0", "@ionic/angular": "^8.0.0", "apexcharts": "^4.1.0", "electron-updater": "^6.3.9", "ionicons": "^7.0.0", - "ng-apexcharts": "^1.13.0", + "ng-apexcharts": "^1.15.0", "patch-package": "^8.0.0", "rxjs": "~7.8.0", "serialport": "^12.0.0", - "zone.js": "~0.14.3" + "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "~18.2.0", - "@angular-devkit/core": "~18.2.0", - "@angular-devkit/schematics": "~18.2.0", - "@angular/cli": "~18.2.0", - "@angular/compiler-cli": "~18.2.0", - "@angular/language-service": "~18.2.0", + "@angular-devkit/build-angular": "~19.0.0", + "@angular-devkit/core": "~19.0.0", + "@angular-devkit/schematics": "~19.0.0", + "@angular/cli": "~19.0.0", + "@angular/compiler-cli": "~19.0.0", + "@angular/language-service": "~19.0.0", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", "@eslint/js": "^9.8.0", - "@nx/angular": "19.8.10", - "@nx/cypress": "19.8.10", - "@nx/eslint": "19.8.10", - "@nx/eslint-plugin": "19.8.10", - "@nx/jest": "19.8.10", - "@nx/js": "19.8.10", - "@nx/web": "19.8.10", - "@nx/workspace": "19.8.10", - "@nxext/ionic-angular": "^19.1.2", - "@schematics/angular": "~18.2.0", + "@nx/angular": "20.2.2", + "@nx/cypress": "20.2.2", + "@nx/eslint": "20.2.2", + "@nx/eslint-plugin": "20.2.2", + "@nx/jest": "20.2.2", + "@nx/js": "20.2.2", + "@nx/web": "20.2.2", + "@nx/workspace": "20.2.2", + "@nxext/ionic-angular": "^20.0.5", + "@schematics/angular": "~19.0.0", "@swc-node/register": "~1.9.1", "@swc/core": "~1.5.7", "@swc/helpers": "~0.5.11", "@types/jest": "^29.5.12", "@types/node": "18.16.9", "@typescript-eslint/utils": "^8.0.0", - "angular-eslint": "^18.3.0", + "angular-eslint": "^19.0.0", "cypress": "^13.13.0", - "electron": "^31.0.1", + "electron": "^33.3.0", "electron-icon-builder": "^2.0.1", "eslint": "^9.8.0", "eslint-config-prettier": "^9.0.0", @@ -66,21 +66,21 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jest-environment-node": "^29.7.0", - "jest-preset-angular": "~14.1.0", - "nx": "19.8.10", - "nx-electron": "^19.0.0", + "jest-preset-angular": "~14.4.2", + "nx": "20.2.2", + "nx-electron": "20.0.0-alpha.0", "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tslib": "^2.3.0", - "typescript": "~5.5.2", + "typescript": "~5.6.3", "typescript-eslint": "^8.0.0" } }, "node_modules/@adobe/css-tools": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz", - "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", "dev": true, "license": "MIT" }, @@ -99,13 +99,13 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1802.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1802.11.tgz", - "integrity": "sha512-p+XIc/j51aI83ExNdeZwvkm1F4wkuKMGUUoj0MVUUi5E6NoiMlXYm6uU8+HbRvPBzGy5+3KOiGp3Fks0UmDSAA==", + "version": "0.1900.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1900.4.tgz", + "integrity": "sha512-9XwZ21BPYS2vGOOwVB40fsMyuwJT0H1lWaAMo8Umwi6XbKBVfaWbEhjtR9dlarrySKtFuTz9hmTZkIXHLjXPdA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.11", + "@angular-devkit/core": "19.0.4", "rxjs": "7.8.1" }, "engines": { @@ -115,40 +115,38 @@ } }, "node_modules/@angular-devkit/build-angular": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-18.2.11.tgz", - "integrity": "sha512-09Ln3NAdlMw/wMLgnwYU5VgWV5TPBEHolZUIvE9D8b6SFWBCowk3B3RWeAMgg7Peuf9SKwqQHBz2b1C7RTP/8g==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-19.0.4.tgz", + "integrity": "sha512-n7fcRdNB7ed5j6aZI+qPI/1LylFv1OiRNgBIeJxX3HEmzQxsHHLcxWog2yZK2Fvw3390xFx/VjZaklITj6tBFA==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.11", - "@angular-devkit/build-webpack": "0.1802.11", - "@angular-devkit/core": "18.2.11", - "@angular/build": "18.2.11", - "@babel/core": "7.25.2", - "@babel/generator": "7.25.0", - "@babel/helper-annotate-as-pure": "7.24.7", + "@angular-devkit/architect": "0.1900.4", + "@angular-devkit/build-webpack": "0.1900.4", + "@angular-devkit/core": "19.0.4", + "@angular/build": "19.0.4", + "@babel/core": "7.26.0", + "@babel/generator": "7.26.2", + "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-transform-async-generator-functions": "7.25.0", - "@babel/plugin-transform-async-to-generator": "7.24.7", - "@babel/plugin-transform-runtime": "7.24.7", - "@babel/preset-env": "7.25.3", - "@babel/runtime": "7.25.0", - "@discoveryjs/json-ext": "0.6.1", - "@ngtools/webpack": "18.2.11", + "@babel/plugin-transform-async-generator-functions": "7.25.9", + "@babel/plugin-transform-async-to-generator": "7.25.9", + "@babel/plugin-transform-runtime": "7.25.9", + "@babel/preset-env": "7.26.0", + "@babel/runtime": "7.26.0", + "@discoveryjs/json-ext": "0.6.3", + "@ngtools/webpack": "19.0.4", "@vitejs/plugin-basic-ssl": "1.1.0", "ansi-colors": "4.1.3", "autoprefixer": "10.4.20", - "babel-loader": "9.1.3", + "babel-loader": "9.2.1", "browserslist": "^4.21.5", "copy-webpack-plugin": "12.0.2", - "critters": "0.0.24", "css-loader": "7.1.2", - "esbuild-wasm": "0.23.0", + "esbuild-wasm": "0.24.0", "fast-glob": "3.3.2", "http-proxy-middleware": "3.0.3", - "https-proxy-agent": "7.0.5", "istanbul-lib-instrument": "6.0.3", "jsonc-parser": "3.3.1", "karma-source-map-support": "1.4.0", @@ -156,31 +154,26 @@ "less-loader": "12.2.0", "license-webpack-plugin": "4.0.2", "loader-utils": "3.3.1", - "magic-string": "0.30.11", - "mini-css-extract-plugin": "2.9.0", - "mrmime": "2.0.0", + "mini-css-extract-plugin": "2.9.2", "open": "10.1.0", "ora": "5.4.1", - "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.6.1", - "postcss": "8.4.41", + "piscina": "4.7.0", + "postcss": "8.4.49", "postcss-loader": "8.1.1", "resolve-url-loader": "5.0.0", "rxjs": "7.8.1", - "sass": "1.77.6", - "sass-loader": "16.0.0", + "sass": "1.80.7", + "sass-loader": "16.0.3", "semver": "7.6.3", "source-map-loader": "5.0.0", "source-map-support": "0.5.21", - "terser": "5.31.6", + "terser": "5.36.0", "tree-kill": "1.2.2", - "tslib": "2.6.3", - "vite": "5.4.6", - "watchpack": "2.4.1", - "webpack": "5.94.0", + "tslib": "2.8.1", + "webpack": "5.96.1", "webpack-dev-middleware": "7.4.2", - "webpack-dev-server": "5.0.4", + "webpack-dev-server": "5.1.0", "webpack-merge": "6.0.1", "webpack-subresource-integrity": "5.1.0" }, @@ -190,22 +183,23 @@ "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.23.0" + "esbuild": "0.24.0" }, "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", - "@web/test-runner": "^0.18.0", + "@angular/compiler-cli": "^19.0.0", + "@angular/localize": "^19.0.0", + "@angular/platform-server": "^19.0.0", + "@angular/service-worker": "^19.0.0", + "@angular/ssr": "^19.0.4", + "@web/test-runner": "^0.19.0", "browser-sync": "^3.0.2", "jest": "^29.5.0", "jest-environment-jsdom": "^29.5.0", "karma": "^6.3.0", - "ng-packagr": "^18.0.0", + "ng-packagr": "^19.0.0", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.6" + "typescript": ">=5.5 <5.7" }, "peerDependenciesMeta": { "@angular/localize": { @@ -217,6 +211,9 @@ "@angular/service-worker": { "optional": true }, + "@angular/ssr": { + "optional": true + }, "@web/test-runner": { "optional": true }, @@ -243,21 +240,14 @@ } } }, - "node_modules/@angular-devkit/build-angular/node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", - "dev": true, - "license": "0BSD" - }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1802.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1802.11.tgz", - "integrity": "sha512-G76rNsyn1iQk7qjyr+K4rnDzfalmEswmwXQorypSDGaHYzIDY1SZXMoP4225WMq5fJNBOJrk82FA0PSfnPE+zQ==", + "version": "0.1900.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1900.4.tgz", + "integrity": "sha512-eovr5Am8EwxF7d/y0Hbfz/KYWnOXXVXVwquPUcg8JBI19lLbfctz4+71Vjz2qGroijr2FlZztRpmhd498SLt/A==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.11", + "@angular-devkit/architect": "0.1900.4", "rxjs": "7.8.1" }, "engines": { @@ -271,9 +261,9 @@ } }, "node_modules/@angular-devkit/core": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.2.11.tgz", - "integrity": "sha512-H9P1shRGigORWJHUY2BRa2YurT+DVminrhuaYHsbhXBRsPmgB2Dx/30YLTnC1s5XmR9QIRUCsg/d3kyT1wd5Zg==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-19.0.4.tgz", + "integrity": "sha512-+imxIj1JLr2hbUYQePHgkTUKr0VmlxNSZvIREcCWtXUcdCypiwhJAtGXv6MfpB4hAx+FJZYEpVWeLwYOS/gW0A==", "dev": true, "license": "MIT", "dependencies": { @@ -290,7 +280,7 @@ "yarn": ">= 1.13.0" }, "peerDependencies": { - "chokidar": "^3.5.2" + "chokidar": "^4.0.0" }, "peerDependenciesMeta": { "chokidar": { @@ -299,15 +289,15 @@ } }, "node_modules/@angular-devkit/schematics": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.2.11.tgz", - "integrity": "sha512-efRK3FotTFp4KD5u42jWfXpHUALXB9kJNsWiB4wEImKFH6CN+vjBspJQuLqk2oeBFh/7D2qRMc5P+2tZHM5hdw==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-19.0.4.tgz", + "integrity": "sha512-2r6Qs4N5NSPho+qzegCYS8kIgylXyH4DHaS7HJ5+4XvM1I8V8AII8payLWkUK0i29XufVoD5XfPUFnjxZrBfYQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.11", + "@angular-devkit/core": "19.0.4", "jsonc-parser": "3.3.1", - "magic-string": "0.30.11", + "magic-string": "0.30.12", "ora": "5.4.1", "rxjs": "7.8.1" }, @@ -318,32 +308,36 @@ } }, "node_modules/@angular-eslint/builder": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-18.4.0.tgz", - "integrity": "sha512-FOzGHX/nHSV1wSduSsabsx3aqC1nfde0opEpEDSOJhxExDxKCwoS1XPy1aERGyKip4ZVA6phC3dLtoBH3QMkVQ==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-19.0.2.tgz", + "integrity": "sha512-BdmMSndQt2fSBiTVniskUcUpQaeweUapbsL0IDfQ7a13vL0NVXpc3K89YXuVE/xsb08uHtqphuwxPAAj6kX3OA==", "dev": true, "license": "MIT", + "dependencies": { + "@angular-devkit/architect": ">= 0.1900.0 < 0.2000.0", + "@angular-devkit/core": ">= 19.0.0 < 20.0.0" + }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": "*" } }, "node_modules/@angular-eslint/bundled-angular-compiler": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-18.4.0.tgz", - "integrity": "sha512-HlFHt2qgdd+jqyVIkCXmrjHauXo/XY3Rp0UNabk83ejGi/raM/6lEFI7iFWzHxLyiAKk4OgGI5W26giSQw991A==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-19.0.2.tgz", + "integrity": "sha512-HPmp92r70SNO/0NdIaIhxrgVSpomqryuUk7jszvNRtu+OzYCJGcbLhQD38T3dbBWT/AV0QXzyzExn6/2ai9fEw==", "dev": true, "license": "MIT" }, "node_modules/@angular-eslint/eslint-plugin": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-18.4.0.tgz", - "integrity": "sha512-Saz9lkWPN3da7ZKW17UsOSN7DeY+TPh+wz/6GCNZCh67Uw2wvMC9agb+4hgpZNXYCP5+u7erqzxQmBoWnS/A+A==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-19.0.2.tgz", + "integrity": "sha512-DLuNVVGGFicSThOcMSJyNje+FZSPdG0B3lCBRiqcgKH/16kfM4pV8MobPM7RGK2NhaOmmZ4zzJNwpwWPSgi+Lw==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.0", - "@angular-eslint/utils": "18.4.0" + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", @@ -352,14 +346,14 @@ } }, "node_modules/@angular-eslint/eslint-plugin-template": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-18.4.0.tgz", - "integrity": "sha512-n3uZFCy76DnggPqjSVFV3gYD1ik7jCG28o2/HO4kobcMNKnwW8XAlFUagQ4TipNQh7fQiAefsEqvv2quMsYDVw==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-19.0.2.tgz", + "integrity": "sha512-f/OCF9ThnxQ8m0eNYPwnCrySQPhYfCOF6STL7F9LnS8Bs3ZeW3/oT1yLaMIZ1Eg0ogIkgxksMAJZjrJPUPBD1Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.0", - "@angular-eslint/utils": "18.4.0", + "@angular-eslint/bundled-angular-compiler": "19.0.2", + "@angular-eslint/utils": "19.0.2", "aria-query": "5.3.2", "axobject-query": "4.1.0" }, @@ -371,31 +365,39 @@ } }, "node_modules/@angular-eslint/schematics": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-18.4.0.tgz", - "integrity": "sha512-ssqe+0YCfekbWIXNdCrHfoPK/bPZAWybs0Bn/b99dfd8h8uyXkERo9AzIOx4Uyj/08SkP9aPL/0uOOEHDsRGwQ==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-19.0.2.tgz", + "integrity": "sha512-wI4SyiAnUCrpigtK6PHRlVWMC9vWljqmlLhbsJV5O5yDajlmRdvgXvSHDefhJm0hSfvZYRXuiAARYv2+QVfnGA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/eslint-plugin": "18.4.0", - "@angular-eslint/eslint-plugin-template": "18.4.0", - "ignore": "5.3.2", + "@angular-devkit/core": ">= 19.0.0 < 20.0.0", + "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", + "ignore": "6.0.2", "semver": "7.6.3", "strip-json-comments": "3.1.1" - }, - "peerDependencies": { - "@angular-devkit/core": ">= 18.0.0 < 19.0.0", - "@angular-devkit/schematics": ">= 18.0.0 < 19.0.0" + } + }, + "node_modules/@angular-eslint/schematics/node_modules/ignore": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-6.0.2.tgz", + "integrity": "sha512-InwqeHHN2XpumIkMvpl/DCJVrAHgCsG5+cn1XlnLWGwtZBm8QJfSusItfrwx81CTp5agNZqpKU2J/ccC5nGT4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@angular-eslint/template-parser": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-18.4.0.tgz", - "integrity": "sha512-VTep3Xd3IOaRIPL+JN/TV4/2DqUPbjtF3TNY15diD/llnrEhqFnmsvMihexbQyTqzOG+zU554oK44YfvAtHOrw==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-19.0.2.tgz", + "integrity": "sha512-z3rZd2sBfuYcFf9rGDsB2zz2fbGX8kkF+0ftg9eocyQmzWrlZHFmuw9ha7oP/Mz8gpblyCS/aa1U/Srs6gz0UQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.0", + "@angular-eslint/bundled-angular-compiler": "19.0.2", "eslint-scope": "^8.0.2" }, "peerDependencies": { @@ -404,13 +406,13 @@ } }, "node_modules/@angular-eslint/utils": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-18.4.0.tgz", - "integrity": "sha512-At1yS8GRviGBoaupiQwEOL4/IcZJCE/+2vpXdItMWPGB1HWetxlKAUZTMmIBX/r5Z7CoXxl+LbqpGhrhyzIQAg==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-19.0.2.tgz", + "integrity": "sha512-HotBT8OKr7zCaX1S9k27JuhRiTVIbbYVl6whlb3uwdMIPIWY8iOcEh1tjI4qDPUafpLfR72Dhwi5bO1E17F3/Q==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/bundled-angular-compiler": "18.4.0" + "@angular-eslint/bundled-angular-compiler": "19.0.2" }, "peerDependencies": { "@typescript-eslint/utils": "^7.11.0 || ^8.0.0", @@ -419,9 +421,9 @@ } }, "node_modules/@angular/animations": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-18.2.11.tgz", - "integrity": "sha512-ghgXa2VhtyJJnTMuH2NYxCMsveQbZno44AZGygPqrcW8UQMQe9GulFaTXCH5s6/so2CLy2ZviIwSZQRgK0ZlDw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-19.0.3.tgz", + "integrity": "sha512-YWoXM2S5p+Eq6cX1xjtFaai23oVNnbf3u34pEQCyKDjZpqI5lMu8e63lQT0tf7fZttEWlNUYRTwQ9+MpZ0sjzQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -430,56 +432,61 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.11" + "@angular/core": "19.0.3" } }, "node_modules/@angular/build": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/build/-/build-18.2.11.tgz", - "integrity": "sha512-AgirvSCmqUKiDE3C0rl3JA68OkOqQWDKUvjqRHXCkhxldLVOVoeIl87+jBYK/v9gcmk+K+ju+5wbGEfu1FjhiQ==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular/build/-/build-19.0.4.tgz", + "integrity": "sha512-ubsNjLb54VkZwcPQ21Ke8aAHiIrRIcv7gG3R6/6XOoWeK1K2+tsv8bnO4mz5cHgzWOspLOT7FDC83NJjrKX3Nw==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "2.3.0", - "@angular-devkit/architect": "0.1802.11", - "@babel/core": "7.25.2", - "@babel/helper-annotate-as-pure": "7.24.7", + "@angular-devkit/architect": "0.1900.4", + "@babel/core": "7.26.0", + "@babel/helper-annotate-as-pure": "7.25.9", "@babel/helper-split-export-declaration": "7.24.7", - "@babel/plugin-syntax-import-attributes": "7.24.7", - "@inquirer/confirm": "3.1.22", + "@babel/plugin-syntax-import-attributes": "7.26.0", + "@inquirer/confirm": "5.0.2", "@vitejs/plugin-basic-ssl": "1.1.0", + "beasties": "0.1.0", "browserslist": "^4.23.0", - "critters": "0.0.24", - "esbuild": "0.23.0", + "esbuild": "0.24.0", "fast-glob": "3.3.2", "https-proxy-agent": "7.0.5", - "listr2": "8.2.4", - "lmdb": "3.0.13", - "magic-string": "0.30.11", + "istanbul-lib-instrument": "6.0.3", + "listr2": "8.2.5", + "magic-string": "0.30.12", "mrmime": "2.0.0", "parse5-html-rewriting-stream": "7.0.0", "picomatch": "4.0.2", - "piscina": "4.6.1", - "rollup": "4.22.4", - "sass": "1.77.6", + "piscina": "4.7.0", + "rollup": "4.26.0", + "sass": "1.80.7", "semver": "7.6.3", - "vite": "5.4.6", - "watchpack": "2.4.1" + "vite": "5.4.11", + "watchpack": "2.4.2" }, "engines": { "node": "^18.19.1 || ^20.11.1 || >=22.0.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, + "optionalDependencies": { + "lmdb": "3.1.5" + }, "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "@angular/localize": "^18.0.0", - "@angular/platform-server": "^18.0.0", - "@angular/service-worker": "^18.0.0", + "@angular/compiler": "^19.0.0", + "@angular/compiler-cli": "^19.0.0", + "@angular/localize": "^19.0.0", + "@angular/platform-server": "^19.0.0", + "@angular/service-worker": "^19.0.0", + "@angular/ssr": "^19.0.4", "less": "^4.2.0", "postcss": "^8.4.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=5.4 <5.6" + "typescript": ">=5.5 <5.7" }, "peerDependenciesMeta": { "@angular/localize": { @@ -491,6 +498,9 @@ "@angular/service-worker": { "optional": true }, + "@angular/ssr": { + "optional": true + }, "less": { "optional": true }, @@ -503,25 +513,25 @@ } }, "node_modules/@angular/cli": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-18.2.11.tgz", - "integrity": "sha512-0JI1xjOLRemBPjdT/yVlabxc3Zkjqa/lhvVxxVC1XhKoW7yGxIGwNrQ4pka4CcQtCuktO6KPMmTGIu8YgC3cpw==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.0.4.tgz", + "integrity": "sha512-jxnD9qkhelcRMCrHDCxNsWgn6HQCvMIj8uI0T2eB9Vy93q2YWUo/fWl2Sy4gFlR+VNeF+1hYhPLb/vqLLzjWuA==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/architect": "0.1802.11", - "@angular-devkit/core": "18.2.11", - "@angular-devkit/schematics": "18.2.11", - "@inquirer/prompts": "5.3.8", - "@listr2/prompt-adapter-inquirer": "2.0.15", - "@schematics/angular": "18.2.11", + "@angular-devkit/architect": "0.1900.4", + "@angular-devkit/core": "19.0.4", + "@angular-devkit/schematics": "19.0.4", + "@inquirer/prompts": "7.1.0", + "@listr2/prompt-adapter-inquirer": "2.0.18", + "@schematics/angular": "19.0.4", "@yarnpkg/lockfile": "1.1.0", - "ini": "4.1.3", + "ini": "5.0.0", "jsonc-parser": "3.3.1", - "listr2": "8.2.4", - "npm-package-arg": "11.0.3", - "npm-pick-manifest": "9.1.0", - "pacote": "18.0.6", + "listr2": "8.2.5", + "npm-package-arg": "12.0.0", + "npm-pick-manifest": "10.0.0", + "pacote": "20.0.0", "resolve": "1.22.8", "semver": "7.6.3", "symbol-observable": "4.0.0", @@ -537,9 +547,9 @@ } }, "node_modules/@angular/common": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-18.2.11.tgz", - "integrity": "sha512-bamJeISl2zUlvjPYebQWazUjhjXU9nrot42cQJng94SkvNENT9LTWfPYgc+Bd972Kg+31jG4H41rgFNs7zySmw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-19.0.3.tgz", + "integrity": "sha512-YyBVZU+LQ38R+/U5vF/b1T3muROKpR0kkupMw7VKnGhQfgrRX5Dk3H2nr9ritt0zPc7TOUuQSlHMf3QWah2GDg==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -548,14 +558,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.11", + "@angular/core": "19.0.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-18.2.11.tgz", - "integrity": "sha512-PSVL1YXUhTzkgJNYXiWk9eAZxNV6laQJRGdj9++C1q9m2S9/GlehZGzkt5GtC5rlUweJucCNvBC1+2D5FAt9vA==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-19.0.3.tgz", + "integrity": "sha512-cxtK4SlHAPstcXfjwOaoR1dAszrzo2iDF8ZiihbZPgKUG3m27qIU3Lp5XBgxfZPlO4jh6TXkWznY7f6Tyxkb0Q==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -564,7 +574,7 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/core": "18.2.11" + "@angular/core": "19.0.3" }, "peerDependenciesMeta": { "@angular/core": { @@ -573,13 +583,13 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-18.2.11.tgz", - "integrity": "sha512-YJlAOiXZUYP6/RK9isu5AOucmNZhFB9lpY/beMzkkWgDku+va8szm4BZbLJFz176IUteyLWF3IP4aE7P9OBlXw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-19.0.3.tgz", + "integrity": "sha512-nayLcC3hSHoGKXCZInMdFcIZJEHYkEGNsdAutgCMuSj+lXCGuRUysuGC0rGzJc2R6nhgfaLJnO8T/O5acqaqdA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "7.25.2", + "@babel/core": "7.26.0", "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^4.0.0", "convert-source-map": "^1.5.1", @@ -597,44 +607,14 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/compiler": "18.2.11", - "typescript": ">=5.4 <5.6" - } - }, - "node_modules/@angular/compiler-cli/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@angular/compiler-cli/node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" + "@angular/compiler": "19.0.3", + "typescript": ">=5.5 <5.7" } }, "node_modules/@angular/core": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-18.2.11.tgz", - "integrity": "sha512-/AGAFyZN8KR+kW5FUFCCBCj3qHyDDum7G0lJe5otrT9AqF6+g7PjF8yLha/6wPkJG7ri5xGLhini1sEivVeq/g==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-19.0.3.tgz", + "integrity": "sha512-WM844gDzrbHtcM2TJB9DmfCmenUYyNSI6h924CeppDW5oG8ShinQGiWNjF5oI6EZ4tG60uK3QvCm3kjr1dmbOA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -644,13 +624,13 @@ }, "peerDependencies": { "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.14.10" + "zone.js": "~0.15.0" } }, "node_modules/@angular/forms": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-18.2.11.tgz", - "integrity": "sha512-QjxayOxDTqsTJGBzfWd3nms1LZIXj2f1+wIPxxUNXyNS5ZaM7hBWkz2BTFYeewlD/HdNj0alNVCYK3M8ElLWYw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-19.0.3.tgz", + "integrity": "sha512-8wf8yDR6cW+lOhpzhmxUOiI5Wjr1Kf7o8NuJ2P5K6b7IMNRzRyR5q/6R4NUwtF6aaJ1wNqmSof+goQmtn1HOcw==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -659,16 +639,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.11", - "@angular/core": "18.2.11", - "@angular/platform-browser": "18.2.11", + "@angular/common": "19.0.3", + "@angular/core": "19.0.3", + "@angular/platform-browser": "19.0.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/language-service": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-18.2.11.tgz", - "integrity": "sha512-kI36Wfvw3E01Xox/H535/rrSTiDfzQeXATFR5i5vqc94XWUdQG67e4X6ybnqFUrezXoLPTULHp+5Di896YFPzw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-19.0.3.tgz", + "integrity": "sha512-SkUFggQayulgMWW4rwslLVCD7woZ1m7dCB87NCQdlZv9NIrHbNkaPfxHzaX3YrdKhw+u65XcttzD7cworcMcVQ==", "dev": true, "license": "MIT", "engines": { @@ -676,9 +656,9 @@ } }, "node_modules/@angular/platform-browser": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-18.2.11.tgz", - "integrity": "sha512-bzcP0QdPT/ncTxOx0t7901z5m0wDmkraTo/es4g8reV6VK9Ptv0QDuD8aDvrHh7sLCX5VgwDF9ohc6S2TpYUCA==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.0.3.tgz", + "integrity": "sha512-vggWHSzOsCpYqnGq5IIN+n7xdEvXfgUGaMdgzPhFMTsnlMTUs5+VEFl9tX9FANHkXKB5S1RttVyvEXRqJM9ncQ==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -687,9 +667,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/animations": "18.2.11", - "@angular/common": "18.2.11", - "@angular/core": "18.2.11" + "@angular/animations": "19.0.3", + "@angular/common": "19.0.3", + "@angular/core": "19.0.3" }, "peerDependenciesMeta": { "@angular/animations": { @@ -698,9 +678,9 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-18.2.11.tgz", - "integrity": "sha512-a30U4ZdTZSvL17xWwOq6xh9ToCDP2K7/j1HTJFREObbuAtZTa/6IVgBUM6oOMNQ43kHkT6Mr9Emkgf9iGtWwfw==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-19.0.3.tgz", + "integrity": "sha512-gFh+QN7JvepnD3mS0XmOtDmfY8h5sSkk2/guesE2A68Na8q+M3fGZlz7I37tCXToLth5us1X0Gi0UPCSESc4SA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -709,16 +689,16 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.11", - "@angular/compiler": "18.2.11", - "@angular/core": "18.2.11", - "@angular/platform-browser": "18.2.11" + "@angular/common": "19.0.3", + "@angular/compiler": "19.0.3", + "@angular/core": "19.0.3", + "@angular/platform-browser": "19.0.3" } }, "node_modules/@angular/router": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-18.2.11.tgz", - "integrity": "sha512-xh4+t4pNBWxeH1a6GIoEGVSRZO4NDKK8q6b+AzB5GBgKsYgOz2lc74RXIPA//pK3aHrS9qD4sJLlodwgE/1+bA==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-19.0.3.tgz", + "integrity": "sha512-L/s8crRC6nj5knmHsnPeOXMNdC7vUOSOvTQonXhmT0FdlP9bPnnRrNeVDnLnd8AzjPSBfIFE2eQw6T8jCwdxMA==", "license": "MIT", "dependencies": { "tslib": "^2.3.0" @@ -727,9 +707,9 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" }, "peerDependencies": { - "@angular/common": "18.2.11", - "@angular/core": "18.2.11", - "@angular/platform-browser": "18.2.11", + "@angular/common": "19.0.3", + "@angular/core": "19.0.3", + "@angular/platform-browser": "19.0.3", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -749,9 +729,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", + "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", "dev": true, "license": "MIT", "engines": { @@ -759,22 +739,22 @@ } }, "node_modules/@babel/core": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", - "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-module-transforms": "^7.25.2", - "@babel/helpers": "^7.25.0", - "@babel/parser": "^7.25.0", - "@babel/template": "^7.25.0", - "@babel/traverse": "^7.25.2", - "@babel/types": "^7.25.2", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -807,42 +787,29 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.0", + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", - "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", - "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" }, "engines": { @@ -898,19 +865,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -922,14 +876,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz", - "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", + "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.1.1", + "regexpu-core": "^6.2.0", "semver": "^6.3.1" }, "engines": { @@ -939,19 +893,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1066,19 +1007,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-remap-async-to-generator/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-replace-supers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", @@ -1097,20 +1025,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", - "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", @@ -1198,13 +1112,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", + "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.0" + "@babel/types": "^7.26.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -1399,32 +1313,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", @@ -1442,13 +1330,13 @@ } }, "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", - "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.7" + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1659,16 +1547,15 @@ } }, "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.0.tgz", - "integrity": "sha512-uaIi2FdqzjpAMvVqvB51S42oC2JEVgh0LDsGfZVDysWE8LrJtQC2jvKmOqEYThKyB7bDEb7BP1GYWDm7tABA0Q==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", + "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-remap-async-to-generator": "^7.25.0", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/traverse": "^7.25.0" + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1678,15 +1565,15 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", - "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", - "@babel/helper-remap-async-to-generator": "^7.24.7" + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1782,19 +1669,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", @@ -1895,13 +1769,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", - "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { @@ -2044,15 +1917,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", - "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-simple-access": "^7.25.9" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -2281,19 +2153,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-private-property-in-object/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", @@ -2327,6 +2186,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", @@ -2344,16 +2220,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", - "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz", + "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.24.7", - "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", "semver": "^6.3.1" }, @@ -2456,9 +2332,9 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", - "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.3.tgz", + "integrity": "sha512-6+5hpdr6mETwSKjmJUdYw0EIkATiQhnELWlE3kJFBwSg/BGIVwVaVbX+gOXBCdc7Ln1RXZxyWGecIXhUfnl7oA==", "dev": true, "license": "MIT", "dependencies": { @@ -2475,19 +2351,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-typescript/node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", @@ -2556,94 +2419,80 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.3.tgz", - "integrity": "sha512-QsYW7UeAaXvLPX9tdVliMJE7MD7M6MLYVTovRTIwhoYQVFHR1rM4wO8wqAezYi3/BpSD+NzVCZ69R6smWiIi8g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", + "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.2", - "@babel/helper-compilation-targets": "^7.25.2", - "@babel/helper-plugin-utils": "^7.24.8", - "@babel/helper-validator-option": "^7.24.8", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/compat-data": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.7", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.0", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoped-functions": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.24.7", - "@babel/plugin-transform-class-static-block": "^7.24.7", - "@babel/plugin-transform-classes": "^7.25.0", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-dotall-regex": "^7.24.7", - "@babel/plugin-transform-duplicate-keys": "^7.24.7", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", - "@babel/plugin-transform-dynamic-import": "^7.24.7", - "@babel/plugin-transform-exponentiation-operator": "^7.24.7", - "@babel/plugin-transform-export-namespace-from": "^7.24.7", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-json-strings": "^7.24.7", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-member-expression-literals": "^7.24.7", - "@babel/plugin-transform-modules-amd": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-modules-systemjs": "^7.25.0", - "@babel/plugin-transform-modules-umd": "^7.24.7", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-new-target": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-object-super": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-property-literals": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-reserved-words": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-template-literals": "^7.24.7", - "@babel/plugin-transform-typeof-symbol": "^7.24.8", - "@babel/plugin-transform-unicode-escapes": "^7.24.7", - "@babel/plugin-transform-unicode-property-regex": "^7.24.7", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.25.9", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.25.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.37.1", + "core-js-compat": "^3.38.1", "semver": "^6.3.1" }, "engines": { @@ -2699,9 +2548,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", - "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "dev": true, "license": "MIT", "dependencies": { @@ -2727,17 +2576,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "version": "7.26.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", + "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.3", + "@babel/parser": "^7.26.3", "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", + "@babel/types": "^7.26.3", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2746,14 +2595,14 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", + "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", + "@babel/parser": "^7.26.3", + "@babel/types": "^7.26.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -2762,31 +2611,18 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "node_modules/@babel/types": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", + "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "node": ">=6.9.0" } }, "node_modules/@bcoe/v8-coverage": { @@ -2808,14 +2644,14 @@ } }, "node_modules/@commitlint/cli": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.5.0.tgz", - "integrity": "sha512-gaGqSliGwB86MDmAAKAtV9SV1SHdmN8pnGq4EJU4+hLisQ7IFfx4jvU4s+pk6tl0+9bv6yT+CaZkufOinkSJIQ==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.6.0.tgz", + "integrity": "sha512-v17BgGD9w5KnthaKxXnEg6KLq6DYiAxyiN44TpiRtqyW8NSq+Kx99mkEG8Qo6uu6cI5eMzMojW2muJxjmPnF8w==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/format": "^19.5.0", - "@commitlint/lint": "^19.5.0", + "@commitlint/lint": "^19.6.0", "@commitlint/load": "^19.5.0", "@commitlint/read": "^19.5.0", "@commitlint/types": "^19.5.0", @@ -2830,9 +2666,9 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.5.0.tgz", - "integrity": "sha512-OBhdtJyHNPryZKg0fFpZNOBM1ZDbntMvqMuSmpfyP86XSfwzGw4CaoYRG4RutUPg0BTK07VMRIkNJT6wi2zthg==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.6.0.tgz", + "integrity": "sha512-DJT40iMnTYtBtUfw9ApbsLZFke1zKh6llITVJ+x9mtpHD08gsNXaIRqHTmwTZL3dNX5+WoyK7pCN/5zswvkBCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2900,9 +2736,9 @@ } }, "node_modules/@commitlint/is-ignored": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.5.0.tgz", - "integrity": "sha512-0XQ7Llsf9iL/ANtwyZ6G0NGp5Y3EQ8eDQSxv/SRcfJ0awlBY4tHFAvwWbw66FVUaWICH7iE5en+FD9TQsokZ5w==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.6.0.tgz", + "integrity": "sha512-Ov6iBgxJQFR9koOupDPHvcHU9keFupDgtB3lObdEZDroiG4jj1rzky60fbQozFKVYRTUdrBGICHG0YVmRuAJmw==", "dev": true, "license": "MIT", "dependencies": { @@ -2914,15 +2750,15 @@ } }, "node_modules/@commitlint/lint": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.5.0.tgz", - "integrity": "sha512-cAAQwJcRtiBxQWO0eprrAbOurtJz8U6MgYqLz+p9kLElirzSCc0vGMcyCaA1O7AqBuxo11l1XsY3FhOFowLAAg==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.6.0.tgz", + "integrity": "sha512-LRo7zDkXtcIrpco9RnfhOKeg8PAnE3oDDoalnrVU/EVaKHYBWYL1DlRR7+3AWn0JiBqD8yKOfetVxJGdEtZ0tg==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/is-ignored": "^19.5.0", + "@commitlint/is-ignored": "^19.6.0", "@commitlint/parse": "^19.5.0", - "@commitlint/rules": "^19.5.0", + "@commitlint/rules": "^19.6.0", "@commitlint/types": "^19.5.0" }, "engines": { @@ -3012,9 +2848,9 @@ } }, "node_modules/@commitlint/rules": { - "version": "19.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.5.0.tgz", - "integrity": "sha512-hDW5TPyf/h1/EufSHEKSp6Hs+YVsDMHazfJ2azIk9tHPXS6UqSz1dIRs1gpqS3eMXgtkT7JH6TW4IShdqOwhAw==", + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.6.0.tgz", + "integrity": "sha512-1f2reW7lbrI0X0ozZMesS/WZxgPa4/wi56vFuJENBmed6mWq5KsheN/nxqnl/C23ioxpPO/PL6tXpiiFy5Bhjw==", "dev": true, "license": "MIT", "dependencies": { @@ -3089,9 +2925,9 @@ } }, "node_modules/@cypress/request": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", - "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", + "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -3108,7 +2944,7 @@ "json-stringify-safe": "~5.0.1", "mime-types": "~2.1.19", "performance-now": "^2.1.0", - "qs": "6.13.0", + "qs": "6.13.1", "safe-buffer": "^5.1.2", "tough-cookie": "^5.0.0", "tunnel-agent": "^0.6.0", @@ -3192,9 +3028,9 @@ "license": "MIT" }, "node_modules/@discoveryjs/json-ext": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz", - "integrity": "sha512-boghen8F0Q8D+0/Q1/1r6DUEieUJ8w2a1gIknExMSHBsJFOr2+0KUfHiVYBvucPwl3+RU5PFBK833FjFCh3BhA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", + "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", "dev": true, "license": "MIT", "engines": { @@ -3541,9 +3377,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz", + "integrity": "sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==", "cpu": [ "ppc64" ], @@ -3558,9 +3394,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.0.tgz", + "integrity": "sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==", "cpu": [ "arm" ], @@ -3575,9 +3411,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz", + "integrity": "sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==", "cpu": [ "arm64" ], @@ -3592,9 +3428,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.0.tgz", + "integrity": "sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==", "cpu": [ "x64" ], @@ -3609,9 +3445,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz", + "integrity": "sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==", "cpu": [ "arm64" ], @@ -3626,9 +3462,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz", + "integrity": "sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==", "cpu": [ "x64" ], @@ -3643,9 +3479,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz", + "integrity": "sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==", "cpu": [ "arm64" ], @@ -3660,9 +3496,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz", + "integrity": "sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==", "cpu": [ "x64" ], @@ -3677,9 +3513,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz", + "integrity": "sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==", "cpu": [ "arm" ], @@ -3694,9 +3530,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz", + "integrity": "sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==", "cpu": [ "arm64" ], @@ -3711,9 +3547,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz", + "integrity": "sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==", "cpu": [ "ia32" ], @@ -3728,9 +3564,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz", + "integrity": "sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==", "cpu": [ "loong64" ], @@ -3745,9 +3581,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz", + "integrity": "sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==", "cpu": [ "mips64el" ], @@ -3762,9 +3598,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz", + "integrity": "sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==", "cpu": [ "ppc64" ], @@ -3779,9 +3615,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz", + "integrity": "sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==", "cpu": [ "riscv64" ], @@ -3796,9 +3632,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz", + "integrity": "sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==", "cpu": [ "s390x" ], @@ -3813,9 +3649,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", "cpu": [ "x64" ], @@ -3830,9 +3666,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz", + "integrity": "sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==", "cpu": [ "x64" ], @@ -3847,9 +3683,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz", + "integrity": "sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==", "cpu": [ "arm64" ], @@ -3864,9 +3700,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz", + "integrity": "sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==", "cpu": [ "x64" ], @@ -3881,9 +3717,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz", + "integrity": "sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==", "cpu": [ "x64" ], @@ -3898,9 +3734,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz", + "integrity": "sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==", "cpu": [ "arm64" ], @@ -3915,9 +3751,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz", + "integrity": "sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==", "cpu": [ "ia32" ], @@ -3932,9 +3768,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz", + "integrity": "sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==", "cpu": [ "x64" ], @@ -3977,32 +3813,14 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@eslint/compat": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.2.tgz", - "integrity": "sha512-jhgiIrsw+tRfcBQ4BFl2C3vCrIUw2trCY0cnDvGZpwTtKCEDmZhAtMfrEUP/KpnwM6PrO0T+Ltm+ccW74olG3Q==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": "^9.10.0" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, "node_modules/@eslint/config-array": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", - "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.4", + "@eslint/object-schema": "^2.1.5", "debug": "^4.3.1", "minimatch": "^3.1.2" }, @@ -4035,19 +3853,22 @@ } }, "node_modules/@eslint/core": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz", - "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", "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/@eslint/eslintrc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", - "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz", + "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==", "dev": true, "license": "MIT", "dependencies": { @@ -4085,13 +3906,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "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", @@ -4150,9 +3964,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", - "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.16.0.tgz", + "integrity": "sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==", "dev": true, "license": "MIT", "engines": { @@ -4160,9 +3974,9 @@ } }, "node_modules/@eslint/object-schema": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", - "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -4170,9 +3984,9 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz", - "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4256,51 +4070,54 @@ } }, "node_modules/@inquirer/checkbox": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-2.5.0.tgz", - "integrity": "sha512-sMgdETOfi2dUHT8r7TT1BTKOwNvdDGFDXYWtQ2J69SvlYNntk9I/gJe7r5yvMwwsuKnYbuRs3pNhx4tgNck5aA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.0.3.tgz", + "integrity": "sha512-CEt9B4e8zFOGtc/LYeQx5m8nfqQeG/4oNNv0PUvXGG0mys+wR/WbJ3B4KfSQ4Fcr3AQfpiuFOi3fVvmPfvNbxw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/confirm": { - "version": "3.1.22", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-3.1.22.tgz", - "integrity": "sha512-gsAKIOWBm2Q87CDfs9fEo7wJT3fwWIJfnDGMn9Qy74gBnNFOACDNfhUzovubbJjWnKLGBln7/NcSmZwj5DuEXg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.0.2.tgz", + "integrity": "sha512-KJLUHOaKnNCYzwVbryj3TNBxyZIrr56fR5N45v6K9IPrbT6B7DcudBMfylkV1A8PUdJE15mybkEQyp2/ZUpxUA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.0.10", - "@inquirer/type": "^1.5.2" + "@inquirer/core": "^10.1.0", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/core": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-9.2.1.tgz", - "integrity": "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==", + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.1.tgz", + "integrity": "sha512-rmZVXy9iZvO3ZStEe/ayuuwIJ23LSF13aPMlLMTQARX6lGUBDHGV8UB5i9MRrfy0+mZwt5/9bdy8llszSD3NQA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "@types/mute-stream": "^0.0.4", - "@types/node": "^22.5.5", - "@types/wrap-ansi": "^3.0.0", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", - "mute-stream": "^1.0.0", + "mute-stream": "^2.0.0", "signal-exit": "^4.1.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0", @@ -4310,57 +4127,40 @@ "node": ">=18" } }, - "node_modules/@inquirer/core/node_modules/@inquirer/type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-2.0.0.tgz", - "integrity": "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/core/node_modules/@types/node": { - "version": "22.9.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz", - "integrity": "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.8" - } - }, "node_modules/@inquirer/editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-2.2.0.tgz", - "integrity": "sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.0.tgz", + "integrity": "sha512-Z3LeGsD3WlItDqLxTPciZDbGtm0wrz7iJGS/uUxSiQxef33ZrBq7LhsXg30P7xrWz1kZX4iGzxxj5SKZmJ8W+w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", "external-editor": "^3.1.0" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/expand": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-2.3.0.tgz", - "integrity": "sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.3.tgz", + "integrity": "sha512-MDszqW4HYBpVMmAoy/FA9laLrgo899UAga0itEjsYrBthKieDZNc0e16gdn7N3cQ0DSf/6zsTBZMuDYDQU4ktg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/figures": { @@ -4374,138 +4174,159 @@ } }, "node_modules/@inquirer/input": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-2.3.0.tgz", - "integrity": "sha512-XfnpCStx2xgh1LIRqPXrTNEEByqQWoxsWYzNRSEUxJ5c6EQlhMogJ3vHKu8aXuTacebtaZzMAHwEL0kAflKOBw==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.0.tgz", + "integrity": "sha512-16B8A9hY741yGXzd8UJ9R8su/fuuyO2e+idd7oVLYjP23wKJ6ILRIIHcnXe8/6AoYgwRS2zp4PNsW/u/iZ24yg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/number": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-1.1.0.tgz", - "integrity": "sha512-ilUnia/GZUtfSZy3YEErXLJ2Sljo/mf9fiKc08n18DdwdmDbOzRcTv65H1jjDvlsAuvdFXf4Sa/aL7iw/NanVA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.3.tgz", + "integrity": "sha512-HA/W4YV+5deKCehIutfGBzNxWH1nhvUC67O4fC9ufSijn72yrYnRmzvC61dwFvlXIG1fQaYWi+cqNE9PaB9n6Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3" + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/password": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-2.2.0.tgz", - "integrity": "sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.3.tgz", + "integrity": "sha512-3qWjk6hS0iabG9xx0U1plwQLDBc/HA/hWzLFFatADpR6XfE62LqPr9GpFXBkLU0KQUaIXZ996bNG+2yUvocH8w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/prompts": { - "version": "5.3.8", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-5.3.8.tgz", - "integrity": "sha512-b2BudQY/Si4Y2a0PdZZL6BeJtl8llgeZa7U2j47aaJSCeAl1e4UI7y8a9bSkO3o/ZbZrgT5muy/34JbsjfIWxA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.1.0.tgz", + "integrity": "sha512-5U/XiVRH2pp1X6gpNAjWOglMf38/Ys522ncEHIKT1voRUvSj/DQnR22OVxHnwu5S+rCFaUiPQ57JOtMFQayqYA==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/checkbox": "^2.4.7", - "@inquirer/confirm": "^3.1.22", - "@inquirer/editor": "^2.1.22", - "@inquirer/expand": "^2.1.22", - "@inquirer/input": "^2.2.9", - "@inquirer/number": "^1.0.10", - "@inquirer/password": "^2.1.22", - "@inquirer/rawlist": "^2.2.4", - "@inquirer/search": "^1.0.7", - "@inquirer/select": "^2.4.7" + "@inquirer/checkbox": "^4.0.2", + "@inquirer/confirm": "^5.0.2", + "@inquirer/editor": "^4.1.0", + "@inquirer/expand": "^4.0.2", + "@inquirer/input": "^4.0.2", + "@inquirer/number": "^3.0.2", + "@inquirer/password": "^4.0.2", + "@inquirer/rawlist": "^4.0.2", + "@inquirer/search": "^3.0.2", + "@inquirer/select": "^4.0.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/rawlist": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-2.3.0.tgz", - "integrity": "sha512-zzfNuINhFF7OLAtGHfhwOW2TlYJyli7lOUoJUXw/uyklcwalV6WRXBXtFIicN8rTRK1XTiPWB4UY+YuW8dsnLQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.3.tgz", + "integrity": "sha512-5MhinSzfmOiZlRoPezfbJdfVCZikZs38ja3IOoWe7H1dxL0l3Z2jAUgbBldeyhhOkELdGvPlBfQaNbeLslib1w==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/type": "^3.0.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-1.1.0.tgz", - "integrity": "sha512-h+/5LSj51dx7hp5xOn4QFnUaKeARwUCLs6mIhtkJ0JYPBLmEYjdHSYh7I6GrLg9LwpJ3xeX0FZgAG1q0QdCpVQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.3.tgz", + "integrity": "sha512-mQTCbdNolTGvGGVCJSI6afDwiSGTV+fMLPEIMDJgIV6L/s3+RYRpxt6t0DYnqMQmemnZ/Zq0vTIRwoHT1RgcTg==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/select": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-2.5.0.tgz", - "integrity": "sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.0.3.tgz", + "integrity": "sha512-OZfKDtDE8+J54JYAFTUGZwvKNfC7W/gFCjDkcsO7HnTH/wljsZo9y/FJquOxMy++DY0+9l9o/MOZ8s5s1j5wmw==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/core": "^9.1.0", - "@inquirer/figures": "^1.0.5", - "@inquirer/type": "^1.5.3", + "@inquirer/core": "^10.1.1", + "@inquirer/figures": "^1.0.8", + "@inquirer/type": "^3.0.1", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@inquirer/type": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", - "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.1.tgz", + "integrity": "sha512-+ksJMIy92sOAiAccGpcKZUc3bYO07cADnscIxHBknEm3uNts3movSmBofc1908BNy5edKscxYeAdaX1NXkHS6A==", "dev": true, "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, "engines": { "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" } }, "node_modules/@ionic/angular": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.4.0.tgz", - "integrity": "sha512-ivgHk76zpu6EZZlxXj5+FUqGwFKotWhDDA9YRltd2QCnQN+7kwacQk7KFInQ5Sd8RJT98mKFG3oOpyx5gFrBdA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-8.4.1.tgz", + "integrity": "sha512-22ghlHeIJjHDizns/huYp1sQ3Y9qYyUY9hEueIB0e8jsNhCOwhRijMIoOCZ/sfMKTbNaKX7EJ25NpVetF7mZXQ==", "license": "MIT", "dependencies": { - "@ionic/core": "8.4.0", + "@ionic/core": "8.4.1", "ionicons": "^7.0.0", "jsonc-parser": "^3.0.0", "tslib": "^2.3.0" @@ -4519,9 +4340,9 @@ } }, "node_modules/@ionic/core": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.4.0.tgz", - "integrity": "sha512-mZ2Ni9QByFGWBNr5W/F/nyPV+cXLhK+6W5BRziy7QPX6YIS57KH8FpY+CjE7BEcpE78anyY49bZt3eOWcES02g==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.4.1.tgz", + "integrity": "sha512-D5xpw5TF2wldpAWE0rHq3L+5T79EjR6d++QFpprjp+q+cFjjhOnfGD+2k7gLlWepAod9LUUigeL0JF02C2wgRQ==", "license": "MIT", "dependencies": { "@stencil/core": "4.20.0", @@ -4632,6 +4453,29 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/fs-minipass/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -5865,9 +5709,9 @@ } }, "node_modules/@jsonjoy.com/json-pack": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz", - "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.1.tgz", + "integrity": "sha512-osjeBqMJ2lb/j/M8NCPjs1ylqWIcTRTycIhVB5pt6LgzgeRSb0YRZ7j9RfA8wIUrsr/medIuhVyonXRZWLyfdw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5912,25 +5756,48 @@ "license": "MIT" }, "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.15.tgz", - "integrity": "sha512-MZrGem/Ujjd4cPTLYDfCZK2iKKeiO/8OX13S6jqxldLs0Prf2aGqVlJ77nMBqMv7fzqgXEgjrNHLXcKR8l9lOg==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.18.tgz", + "integrity": "sha512-0hz44rAcrphyXcA8IS7EJ2SCoaBZD2u5goE8S/e+q/DL+dOGpqpcLidVOFeLG3VgML62SXmfRLAhWt0zL1oW4Q==", "dev": true, "license": "MIT", "dependencies": { - "@inquirer/type": "^1.5.1" + "@inquirer/type": "^1.5.5" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@inquirer/prompts": ">= 3 < 6" + "@inquirer/prompts": ">= 3 < 8" + } + }, + "node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-1.5.5.tgz", + "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mute-stream": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@listr2/prompt-adapter-inquirer/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@lmdb/lmdb-darwin-arm64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.0.13.tgz", - "integrity": "sha512-uiKPB0Fv6WEEOZjruu9a6wnW/8jrjzlZbxXscMB8kuCJ1k6kHpcBnuvaAWcqhbI7rqX5GKziwWEdD+wi2gNLfA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-arm64/-/lmdb-darwin-arm64-3.1.5.tgz", + "integrity": "sha512-ue5PSOzHMCIYrfvPP/MRS6hsKKLzqqhcdAvJCO8uFlDdj598EhgnacuOTuqA6uBK5rgiZXfDWyb7DVZSiBKxBA==", "cpu": [ "arm64" ], @@ -5942,9 +5809,9 @@ ] }, "node_modules/@lmdb/lmdb-darwin-x64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.0.13.tgz", - "integrity": "sha512-bEVIIfK5mSQoG1R19qA+fJOvCB+0wVGGnXHT3smchBVahYBdlPn2OsZZKzlHWfb1E+PhLBmYfqB5zQXFP7hJig==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-darwin-x64/-/lmdb-darwin-x64-3.1.5.tgz", + "integrity": "sha512-CGhsb0R5vE6mMNCoSfxHFD8QTvBHM51gs4DBeigTYHWnYv2V5YpJkC4rMo5qAAFifuUcc0+a8a3SIU0c9NrfNw==", "cpu": [ "x64" ], @@ -5956,9 +5823,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.0.13.tgz", - "integrity": "sha512-Yml1KlMzOnXj/tnW7yX8U78iAzTk39aILYvCPbqeewAq1kSzl+w59k/fiVkTBfvDi/oW/5YRxL+Fq+Y1Fr1r2Q==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm/-/lmdb-linux-arm-3.1.5.tgz", + "integrity": "sha512-3WeW328DN+xB5PZdhSWmqE+t3+44xWXEbqQ+caWJEZfOFdLp9yklBZEbVqVdqzznkoaXJYxTCp996KD6HmANeg==", "cpu": [ "arm" ], @@ -5970,9 +5837,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-arm64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.0.13.tgz", - "integrity": "sha512-afbVrsMgZ9dUTNUchFpj5VkmJRxvht/u335jUJ7o23YTbNbnpmXif3VKQGCtnjSh+CZaqm6N3CPG8KO3zwyZ1Q==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-arm64/-/lmdb-linux-arm64-3.1.5.tgz", + "integrity": "sha512-LAjaoOcBHGj6fiYB8ureiqPoph4eygbXu4vcOF+hsxiY74n8ilA7rJMmGUT0K0JOB5lmRQHSmor3mytRjS4qeQ==", "cpu": [ "arm64" ], @@ -5984,9 +5851,9 @@ ] }, "node_modules/@lmdb/lmdb-linux-x64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.0.13.tgz", - "integrity": "sha512-vOtxu0xC0SLdQ2WRXg8Qgd8T32ak4SPqk5zjItRszrJk2BdeXqfGxBJbP7o4aOvSPSmSSv46Lr1EP4HXU8v7Kg==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-linux-x64/-/lmdb-linux-x64-3.1.5.tgz", + "integrity": "sha512-k/IklElP70qdCXOQixclSl2GPLFiopynGoKX1FqDd1/H0E3Fo1oPwjY2rEVu+0nS3AOw1sryStdXk8CW3cVIsw==", "cpu": [ "x64" ], @@ -5998,9 +5865,9 @@ ] }, "node_modules/@lmdb/lmdb-win32-x64": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.0.13.tgz", - "integrity": "sha512-UCrMJQY/gJnOl3XgbWRZZUvGGBuKy6i0YNSptgMzHBjs+QYDYR1Mt/RLTOPy4fzzves65O1EDmlL//OzEqoLlA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@lmdb/lmdb-win32-x64/-/lmdb-win32-x64-3.1.5.tgz", + "integrity": "sha512-KYar6W8nraZfSJspcK7Kp7hdj238X/FNauYbZyrqPBrtsXI1hvI4/KcRcRGP50aQoV7fkKDyJERlrQGMGTZUsA==", "cpu": [ "x64" ], @@ -6051,25 +5918,26 @@ } }, "node_modules/@module-federation/bridge-react-webpack-plugin": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.6.16.tgz", - "integrity": "sha512-AQj20lUL5fmdz4un56W3VF8naZaRDmztczl+/j4Qa69JAaUbbZK6zZJ3NEjx0cNzpiq/mGmG9Vik3V4rI/4BUA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/bridge-react-webpack-plugin/-/bridge-react-webpack-plugin-0.7.6.tgz", + "integrity": "sha512-eD1JZDQ+h5WLdA58MmAE1DzLwvFaGJeeam3Tswc/sEUb4QGT86X4Fme+dMTBRYRoAq/tRYql3DlVTFhdmrUVzg==", "dev": true, + "license": "MIT", "dependencies": { - "@module-federation/sdk": "0.6.16", + "@module-federation/sdk": "0.7.6", "@types/semver": "7.5.8", "semver": "7.6.3" } }, "node_modules/@module-federation/data-prefetch": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-0.6.16.tgz", - "integrity": "sha512-m5SNKlAkB2FFCs2cl6LWqo6s2NZ7HuCrp6QrrMzuKjB6EddvKojVQxOzrWdcMLs1vESy6fyU4M4U7PxSojw6Ww==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/data-prefetch/-/data-prefetch-0.7.6.tgz", + "integrity": "sha512-AMpfnuIAK/Y5M682BUsnc13ARCEKhEvb0tXF4S+l7jfL08oE9gyo+G/nk0LIzZBO2mLDz5g2AydAERanM6gswQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.6.16", - "@module-federation/sdk": "0.6.16", + "@module-federation/runtime": "0.7.6", + "@module-federation/sdk": "0.7.6", "fs-extra": "9.1.0" }, "peerDependencies": { @@ -6078,16 +5946,16 @@ } }, "node_modules/@module-federation/dts-plugin": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.6.16.tgz", - "integrity": "sha512-XM6+EYVrS2Q/ZW0u9cH0sJT5t5SQHRjzmW7JWdPv0+wKGCA15WtRMc55boM4Wan7jXJZf+JeD5QLXWiSjaJdnw==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/dts-plugin/-/dts-plugin-0.7.6.tgz", + "integrity": "sha512-K8T8+Ip+fCQkTOxAQbAW47drphN36+WcvcOusn/fsIT+1exdhyvqxSCj8V7MLCtjA9kGDi0jHIGN6MN4p2cV0Q==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "0.6.14", - "@module-federation/managers": "0.6.16", - "@module-federation/sdk": "0.6.16", - "@module-federation/third-party-dts-extractor": "0.6.16", + "@module-federation/error-codes": "0.7.6", + "@module-federation/managers": "0.7.6", + "@module-federation/sdk": "0.7.6", + "@module-federation/third-party-dts-extractor": "0.7.6", "adm-zip": "^0.5.10", "ansi-colors": "^4.1.3", "axios": "^1.7.4", @@ -6155,20 +6023,20 @@ } }, "node_modules/@module-federation/enhanced": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.6.16.tgz", - "integrity": "sha512-5MqA35WGvPmCScT/xNnheR4RBa2oYHkLpeVjOA0xg0PeUTC7aSfGRLsntzFeyzLITSjbVTupK2YwmjiZr3Z0LQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/enhanced/-/enhanced-0.7.6.tgz", + "integrity": "sha512-ivTVuRKhew/25fiblAW22RybYzyacQsvnQG3y9zSNsYbwcj+0u7THWMmsK8vNKxDUpjxuQulCK07BEycDjoB5Q==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.6.16", - "@module-federation/data-prefetch": "0.6.16", - "@module-federation/dts-plugin": "0.6.16", - "@module-federation/managers": "0.6.16", - "@module-federation/manifest": "0.6.16", - "@module-federation/rspack": "0.6.16", - "@module-federation/runtime-tools": "0.6.16", - "@module-federation/sdk": "0.6.16", + "@module-federation/bridge-react-webpack-plugin": "0.7.6", + "@module-federation/data-prefetch": "0.7.6", + "@module-federation/dts-plugin": "0.7.6", + "@module-federation/managers": "0.7.6", + "@module-federation/manifest": "0.7.6", + "@module-federation/rspack": "0.7.6", + "@module-federation/runtime-tools": "0.7.6", + "@module-federation/sdk": "0.7.6", "btoa": "^1.2.1", "upath": "2.0.1" }, @@ -6190,34 +6058,34 @@ } }, "node_modules/@module-federation/error-codes": { - "version": "0.6.14", - "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.6.14.tgz", - "integrity": "sha512-ik+ezloFkxmE5atqTUG9lRr9xV5EcKDjH+MZba2IJQT5cZIM6o2ThTC45E013N4SCleaGxBtIGoPLZJzT4xa0Q==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/error-codes/-/error-codes-0.7.6.tgz", + "integrity": "sha512-XVzX/sRFj1h5JvOOVMoFppxq0t1t3o/AlEICHgWX+dybIwJgz9g4gihZOWVZfz5/xsKGcUwdH5X7Z2nkuYhJEw==", "dev": true, "license": "MIT" }, "node_modules/@module-federation/managers": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.6.16.tgz", - "integrity": "sha512-9oqJT0F61GhaFE4EFgJjVyQlD8ohXxMJBS9UGCKC6nHd3+PI4NBWGN2D+alBOwvwtt3LhtssbVH8H8HZEM1GnQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/managers/-/managers-0.7.6.tgz", + "integrity": "sha512-NW0LJ6TL13oN004D9e50EalcGZyTYHHgyaeKOc90Omb/HMeHxjyhHx7wl1TLRwVN2E5Rk+IO0JrwgrdlNMfAzg==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/sdk": "0.6.16", + "@module-federation/sdk": "0.7.6", "find-pkg": "2.0.0", "fs-extra": "9.1.0" } }, "node_modules/@module-federation/manifest": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.6.16.tgz", - "integrity": "sha512-YjOk+1uR6E5qIEWiy35IrMyEy+rDGI5nJd+6MQobkXG40DK94mdPxJ7TSCozj/bpZ9SadCxXRCkMiE/gTkryAQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/manifest/-/manifest-0.7.6.tgz", + "integrity": "sha512-xBrFwLjDMUjKRnp+P4X29ZNyhgXSsp+SfrBxVsKJpEESOHalDoNClbo6gXvZAvkBZyo9sY3SJhAwduDwNkg04w==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/dts-plugin": "0.6.16", - "@module-federation/managers": "0.6.16", - "@module-federation/sdk": "0.6.16", + "@module-federation/dts-plugin": "0.7.6", + "@module-federation/managers": "0.7.6", + "@module-federation/sdk": "0.7.6", "chalk": "3.0.0", "find-pkg": "2.0.0" } @@ -6265,19 +6133,51 @@ "node": ">=8" } }, + "node_modules/@module-federation/node": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@module-federation/node/-/node-2.6.11.tgz", + "integrity": "sha512-ytCNML9Q9dQ7Xi/pTYp4Y+yP/YUiFyyCa8BEKnSt5Ipiqtu4QMxj46EkOIgvLv0nSlK+xOVgAzqtXLI89SfhCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/enhanced": "0.7.6", + "@module-federation/runtime": "0.7.6", + "@module-federation/sdk": "0.7.6", + "@module-federation/utilities": "3.1.29", + "btoa": "1.2.1", + "encoding": "^0.1.13", + "node-fetch": "2.7.0" + }, + "peerDependencies": { + "react": "^16||^17||^18", + "react-dom": "^16||^17||^18", + "webpack": "^5.40.0" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@module-federation/rspack": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.6.16.tgz", - "integrity": "sha512-9nQAyw7QvgXJYPTQseyQ31qQtSlo0VsppQOyFLstLITzgWWugN7cN8cGAriUKYBI78THuX+lp1mdgsNTBvxJPA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/rspack/-/rspack-0.7.6.tgz", + "integrity": "sha512-alfX85C+2AQLXGrtpa08ImwhHIGwFIkJ/6i/XhxpYL5iFu0mC0xRIJPJUw0tiBWdFpP4p+Ykij3hP3FqfvaiKg==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/bridge-react-webpack-plugin": "0.6.16", - "@module-federation/dts-plugin": "0.6.16", - "@module-federation/managers": "0.6.16", - "@module-federation/manifest": "0.6.16", - "@module-federation/runtime-tools": "0.6.16", - "@module-federation/sdk": "0.6.16" + "@module-federation/bridge-react-webpack-plugin": "0.7.6", + "@module-federation/dts-plugin": "0.7.6", + "@module-federation/managers": "0.7.6", + "@module-federation/manifest": "0.7.6", + "@module-federation/runtime-tools": "0.7.6", + "@module-federation/sdk": "0.7.6" }, "peerDependencies": { "typescript": "^4.9.0 || ^5.0.0", @@ -6293,41 +6193,41 @@ } }, "node_modules/@module-federation/runtime": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.6.16.tgz", - "integrity": "sha512-3oFDRkolGwiXuQz+wzX3YzBWI9so0+K05YRf0TEdJguj3W/v/AMrBCz7W4c4O/wSK45Kuqd4lHKhCyKWRPyhOw==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.7.6.tgz", + "integrity": "sha512-TEEDbGwaohZ2dMa+Sk/Igq8XpcyfjqJfbL20mdAZeifSFVZYRSCaTd/xIXP7pEw8+5BaCMc4YfCf/XcjFAUrVA==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/error-codes": "0.6.14", - "@module-federation/sdk": "0.6.16" + "@module-federation/error-codes": "0.7.6", + "@module-federation/sdk": "0.7.6" } }, "node_modules/@module-federation/runtime-tools": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.6.16.tgz", - "integrity": "sha512-AIaxnx99tVYppYCgdJQz43mrGZ2pPJtC7YEIjuQV+UnSORj+d/GOIqF88MDx3i7siFcQ4zrT5BVtEWhXcJdv0g==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.7.6.tgz", + "integrity": "sha512-SvokF6gn2sNrTEPG51H0LrowHnf3iNfznO2PzKpxAhZOBdb1pm0wJPwWSMHYrjMdDpjr7bzaqAywnkHdA6lqeQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.6.16", - "@module-federation/webpack-bundler-runtime": "0.6.16" + "@module-federation/runtime": "0.7.6", + "@module-federation/webpack-bundler-runtime": "0.7.6" } }, "node_modules/@module-federation/sdk": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.6.16.tgz", - "integrity": "sha512-rzQH/v9bVc032lzV4j1IGYRc5gszwzBevYBBDJf3oNLwkY2kIDUJ99OWvq3aaPJoE0jEWPVe3K5iNc+dZe4tMQ==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.7.6.tgz", + "integrity": "sha512-MFE+RtsHnutZOCp2eKpa3A/yzZ8tOPmjX7QRdVnB2qqR9JA2SH3ZP5+cYq76tzFQZvU1BCWAQVNMvqGOW2yVZQ==", "dev": true, "license": "MIT", "dependencies": { - "isomorphic-rslog": "0.0.5" + "isomorphic-rslog": "0.0.6" } }, "node_modules/@module-federation/third-party-dts-extractor": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.6.16.tgz", - "integrity": "sha512-F4W8QBlPLNY22TGjUWA+FyFYN6wVgGKhefd170A8BOqv2gB1yhm6OIEmDnO6TwfDfQQebVCcAu23AzLzgS5eCg==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/third-party-dts-extractor/-/third-party-dts-extractor-0.7.6.tgz", + "integrity": "sha512-JME76/rgr41AKXG6kUTQXdQJiMCypN3qHOgPv4VuIag10UdLo/0gdeN6PYronvYmvPOQMfYev80GcEwl4l531A==", "dev": true, "license": "MIT", "dependencies": { @@ -6336,15 +6236,41 @@ "resolve": "1.22.8" } }, + "node_modules/@module-federation/utilities": { + "version": "3.1.29", + "resolved": "https://registry.npmjs.org/@module-federation/utilities/-/utilities-3.1.29.tgz", + "integrity": "sha512-yhHOgm3mkZBvQzT4HoBJAVhGIa7Nfhpd4Zdc11g0vYEMapU6lfN5HHipUFdj6bLUzHhDyrY6CaF3syqTuabAfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/sdk": "0.7.6" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18", + "webpack": "^5.40.0" + }, + "peerDependenciesMeta": { + "next": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/@module-federation/webpack-bundler-runtime": { - "version": "0.6.16", - "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.6.16.tgz", - "integrity": "sha512-Tpi251DApEaQ62KCaJCh1RU1SZTUcVh8lx2zotn/YOMZdw83IzYu3PYYA1V0Eg5jVe6I2GmGH52pJPCtwbgjqA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.7.6.tgz", + "integrity": "sha512-kB9hQ0BfwNAcQWGskDEOxYP2z2bB/1ABXKr8MDomCFl2mbW3vvfYMQrb8UhJmJvE3rbGI/iXhJUdgBLNREnjUg==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/runtime": "0.6.16", - "@module-federation/sdk": "0.6.16" + "@module-federation/runtime": "0.7.6", + "@module-federation/sdk": "0.7.6" } }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { @@ -6431,57 +6357,362 @@ "win32" ] }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", - "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@emnapi/core": "^1.1.0", - "@emnapi/runtime": "^1.1.0", - "@tybys/wasm-util": "^0.9.0" - } - }, - "node_modules/@ngtools/webpack": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-18.2.11.tgz", - "integrity": "sha512-iTdUGJ5O7yMm1DyCzyoMDMxBJ68emUSSXPWbQzEEdcqmtifRebn+VAq4vHN8OmtGM1mtuKeLEsbiZP8ywrw7Ug==", + "node_modules/@napi-rs/nice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.0.1.tgz", + "integrity": "sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ==", "dev": true, "license": "MIT", + "optional": true, "engines": { - "node": "^18.19.1 || ^20.11.1 || >=22.0.0", - "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", - "yarn": ">= 1.13.0" + "node": ">= 10" }, - "peerDependencies": { - "@angular/compiler-cli": "^18.0.0", - "typescript": ">=5.4 <5.6", - "webpack": "^5.54.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.0.1", + "@napi-rs/nice-android-arm64": "1.0.1", + "@napi-rs/nice-darwin-arm64": "1.0.1", + "@napi-rs/nice-darwin-x64": "1.0.1", + "@napi-rs/nice-freebsd-x64": "1.0.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.0.1", + "@napi-rs/nice-linux-arm64-gnu": "1.0.1", + "@napi-rs/nice-linux-arm64-musl": "1.0.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.0.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.0.1", + "@napi-rs/nice-linux-s390x-gnu": "1.0.1", + "@napi-rs/nice-linux-x64-gnu": "1.0.1", + "@napi-rs/nice-linux-x64-musl": "1.0.1", + "@napi-rs/nice-win32-arm64-msvc": "1.0.1", + "@napi-rs/nice-win32-ia32-msvc": "1.0.1", + "@napi-rs/nice-win32-x64-msvc": "1.0.1" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.0.1.tgz", + "integrity": "sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 8" + "node": ">= 10" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.0.1.tgz", + "integrity": "sha512-GqvXL0P8fZ+mQqG1g0o4AO9hJjQaeYG84FRfZaYjyJtZZZcMjXW5TwkL8Y8UApheJgyE13TQ4YNUssQaTgTyvA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">= 8" + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.0.1.tgz", + "integrity": "sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.0.1.tgz", + "integrity": "sha512-jXnMleYSIR/+TAN/p5u+NkCA7yidgswx5ftqzXdD5wgy/hNR92oerTXHc0jrlBisbd7DpzoaGY4cFD7Sm5GlgQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.0.1.tgz", + "integrity": "sha512-j+iJ/ezONXRQsVIB/FJfwjeQXX7A2tf3gEXs4WUGFrJjpe/z2KB7sOv6zpkm08PofF36C9S7wTNuzHZ/Iiccfw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.0.1.tgz", + "integrity": "sha512-G8RgJ8FYXYkkSGQwywAUh84m946UTn6l03/vmEXBYNJxQJcD+I3B3k5jmjFG/OPiU8DfvxutOP8bi+F89MCV7Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.0.1.tgz", + "integrity": "sha512-IMDak59/W5JSab1oZvmNbrms3mHqcreaCeClUjwlwDr0m3BoR09ZiN8cKFBzuSlXgRdZ4PNqCYNeGQv7YMTjuA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.0.1.tgz", + "integrity": "sha512-wG8fa2VKuWM4CfjOjjRX9YLIbysSVV1S3Kgm2Fnc67ap/soHBeYZa6AGMeR5BJAylYRjnoVOzV19Cmkco3QEPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.0.1.tgz", + "integrity": "sha512-lxQ9WrBf0IlNTCA9oS2jg/iAjQyTI6JHzABV664LLrLA/SIdD+I1i3Mjf7TsnoUbgopBcCuDztVLfJ0q9ubf6Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.0.1.tgz", + "integrity": "sha512-3xs69dO8WSWBb13KBVex+yvxmUeEsdWexxibqskzoKaWx9AIqkMbWmE2npkazJoopPKX2ULKd8Fm9veEn0g4Ig==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.0.1.tgz", + "integrity": "sha512-lMFI3i9rlW7hgToyAzTaEybQYGbQHDrpRkg+1gJWEpH0PLAQoZ8jiY0IzakLfNWnVda1eTYYlxxFYzW8Rqczkg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.0.1.tgz", + "integrity": "sha512-XQAJs7DRN2GpLN6Fb+ZdGFeYZDdGl2Fn3TmFlqEL5JorgWKrQGRUrpGKbgZ25UeZPILuTKJ+OowG2avN8mThBA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.0.1.tgz", + "integrity": "sha512-/rodHpRSgiI9o1faq9SZOp/o2QkKQg7T+DK0R5AkbnI/YxvAIEHf2cngjYzLMQSQgUhxym+LFr+UGZx4vK4QdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.0.1.tgz", + "integrity": "sha512-rEcz9vZymaCB3OqEXoHnp9YViLct8ugF+6uO5McifTedjq4QMQs3DHz35xBEGhH3gJWEsXMUbzazkz5KNM5YUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.0.1.tgz", + "integrity": "sha512-t7eBAyPUrWL8su3gDxw9xxxqNwZzAqKo0Szv3IjVQd1GpXXVkb6vBBQUuxfIYaXMzZLwlxRQ7uzM2vdUE9ULGw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.0.1.tgz", + "integrity": "sha512-JlF+uDcatt3St2ntBG8H02F1mM45i5SF9W+bIKiReVE6wiy3o16oBP/yxt+RZ+N6LbCImJXJ6bXNO2kn9AXicg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.4.tgz", + "integrity": "sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@emnapi/core": "^1.1.0", + "@emnapi/runtime": "^1.1.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@ngtools/webpack": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-19.0.4.tgz", + "integrity": "sha512-N3WCbQz5ipdAZoSWHNf81RLET6+isq35+GZu9u0StpFtJCpXAmRRAv4vdMUYL7DLOzRmvEgwww6Rd5AwGeLFSw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.19.1 || ^20.11.1 || >=22.0.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^19.0.0", + "typescript": ">=5.5 <5.7", + "webpack": "^5.54.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { @@ -6499,9 +6730,9 @@ } }, "node_modules/@npmcli/agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.2.tgz", - "integrity": "sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-3.0.0.tgz", + "integrity": "sha512-S79NdEgDQd/NGCay6TCoVzXSj74skRZIKJcpJjC5lOq34SZzyI6MqtiiWoiVWoVrTcGjNeC4ipbh1VIHlpfF5Q==", "dev": true, "license": "ISC", "dependencies": { @@ -6512,7 +6743,7 @@ "socks-proxy-agent": "^8.0.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { @@ -6537,13 +6768,13 @@ "license": "ISC" }, "node_modules/@npmcli/agent/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.4.tgz", - "integrity": "sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", "dependencies": { - "agent-base": "^7.1.1", + "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" }, @@ -6566,24 +6797,24 @@ } }, "node_modules/@npmcli/git": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.8.tgz", - "integrity": "sha512-liASfw5cqhjNW9UFd+ruwwdEf/lbOAQjLL2XY2dFW/bkJheXDYZgOyul/4gVvEV4BWkTXjYGmDqMw9uegdbJNQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-6.0.1.tgz", + "integrity": "sha512-BBWMMxeQzalmKadyimwb2/VVQyJB01PH0HhVSNLHNBDZN/M/h/02P6f8fxedIiFhpMj11SO9Ep5tKTBE7zL2nw==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/promise-spawn": "^7.0.0", - "ini": "^4.1.3", + "@npmcli/promise-spawn": "^8.0.0", + "ini": "^5.0.0", "lru-cache": "^10.0.1", - "npm-pick-manifest": "^9.0.0", - "proc-log": "^4.0.0", + "npm-pick-manifest": "^10.0.0", + "proc-log": "^5.0.0", "promise-inflight": "^1.0.1", "promise-retry": "^2.0.1", "semver": "^7.3.5", - "which": "^4.0.0" + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/git/node_modules/isexe": { @@ -6604,9 +6835,9 @@ "license": "ISC" }, "node_modules/@npmcli/git/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6616,24 +6847,24 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/installed-package-contents": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", - "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", + "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", "dev": true, "license": "ISC", "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" }, "bin": { "installed-package-contents": "bin/index.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/move-file": { @@ -6652,32 +6883,32 @@ } }, "node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-4.0.0.tgz", + "integrity": "sha512-+t5DZ6mO/QFh78PByMq1fGSAub/agLJZDRfJRMeOSNCt8s9YVlTjmGpIPwPhvXTGUIJk+WszlT0rQa1W33yzNA==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/package-json": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-5.2.1.tgz", - "integrity": "sha512-f7zYC6kQautXHvNbLEWgD/uGu1+xCn9izgqBfgItWSx22U0ZDekxN08A1vM8cTxj/cRVe0Q94Ode+tdoYmIOOQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/package-json/-/package-json-6.1.0.tgz", + "integrity": "sha512-t6G+6ZInT4X+tqj2i+wlLIeCKnKOTuz9/VFYDtj+TGTur5q7sp/OYrQA19LdBbWfXDOi0Y4jtedV6xtB8zQ9ug==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^5.0.0", + "@npmcli/git": "^6.0.0", "glob": "^10.2.2", - "hosted-git-info": "^7.0.0", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^6.0.0", - "proc-log": "^4.0.0", + "hosted-git-info": "^8.0.0", + "json-parse-even-better-errors": "^4.0.0", + "normalize-package-data": "^7.0.0", + "proc-log": "^5.0.0", "semver": "^7.5.3" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/package-json/node_modules/glob": { @@ -6728,16 +6959,16 @@ } }, "node_modules/@npmcli/promise-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.2.tgz", - "integrity": "sha512-xhfYPXoV5Dy4UkY0D+v2KkwvnDfiA/8Mt3sWCGI/hM03NsYIH8ZaG6QzS9x7pje5vHZBZJ2v6VRFVTWACnqcmQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-8.0.2.tgz", + "integrity": "sha512-/bNJhjc+o6qL+Dwz/bqfTQClkEO5nTQ1ZEcdCkAQjhkZMHIh22LPG7fNh1enJP1NKWDqYiiABnjFCY7E0zHYtQ==", "dev": true, "license": "ISC", "dependencies": { - "which": "^4.0.0" + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/promise-spawn/node_modules/isexe": { @@ -6751,9 +6982,9 @@ } }, "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6763,48 +6994,48 @@ "node-which": "bin/which.js" }, "engines": { - "node": "^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/redact": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-2.0.1.tgz", - "integrity": "sha512-YgsR5jCQZhVmTJvjduTOIHph0L73pK8xwMVaDY0PatySqVM9AZj93jpoXYSJqfHFxFkN9dmqTw6OiqExsS3LPw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/redact/-/redact-3.0.0.tgz", + "integrity": "sha512-/1uFzjVcfzqrgCeGW7+SZ4hv0qLWmKXVzFahZGJ6QuJBj6Myt9s17+JL86i76NV9YSnJRcGXJYQbAU0rn1YTCQ==", "dev": true, "license": "ISC", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-8.1.0.tgz", - "integrity": "sha512-y7efHHwghQfk28G2z3tlZ67pLG0XdfYbcVG26r7YIXALRsrVQcTq4/tdenSmdOrEsNahIYA/eh8aEVROWGFUDg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-9.0.2.tgz", + "integrity": "sha512-cJXiUlycdizQwvqE1iaAb4VRUM3RX09/8q46zjvy+ct9GhfZRWd7jXYVc1tn/CfRlGPVkX/u4sstRlepsm7hfw==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/package-json": "^5.0.0", - "@npmcli/promise-spawn": "^7.0.0", - "node-gyp": "^10.0.0", - "proc-log": "^4.0.0", - "which": "^4.0.0" + "@npmcli/node-gyp": "^4.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "node-gyp": "^11.0.0", + "proc-log": "^5.0.0", + "which": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script/node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script/node_modules/abbrev": { @@ -6818,13 +7049,13 @@ } }, "node_modules/@npmcli/run-script/node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", - "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -6832,13 +7063,23 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/@npmcli/run-script/node_modules/fs-minipass": { @@ -6893,27 +7134,26 @@ "license": "ISC" }, "node_modules/@npmcli/run-script/node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script/node_modules/minimatch": { @@ -6956,27 +7196,67 @@ } }, "node_modules/@npmcli/run-script/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", + "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, + "node_modules/@npmcli/run-script/node_modules/minizlib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@npmcli/run-script/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/run-script/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@npmcli/run-script/node_modules/node-gyp": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz", - "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-11.0.0.tgz", + "integrity": "sha512-zQS+9MTTeCMgY0F3cWPyJyRFAkVltQ1uXm+xXu/ES6KFgC6Czo1Seb9vQW2wNxSX2OrDTiqL0ojtkFxBQ0ypIw==", "dev": true, "license": "MIT", "dependencies": { @@ -6984,24 +7264,24 @@ "exponential-backoff": "^3.1.1", "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^13.0.0", - "nopt": "^7.0.0", - "proc-log": "^4.1.0", + "make-fetch-happen": "^14.0.3", + "nopt": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^4.0.0" + "tar": "^7.4.3", + "which": "^5.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@npmcli/run-script/node_modules/nopt": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz", - "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.0.0.tgz", + "integrity": "sha512-1L/fTJ4UmV/lUxT2Uf006pfZKTvAgCF+chz+0OgBHO8u2Z67pE7AaAUUj7CJy0lXqHmymUvGFt6NE9R3HER0yw==", "dev": true, "license": "ISC", "dependencies": { @@ -7011,201 +7291,150 @@ "nopt": "bin/nopt.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/run-script/node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "node_modules/@npmcli/run-script/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, + "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@npmcli/run-script/node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "node_modules/@npmcli/run-script/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "glob": "^10.3.7" }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@npmcli/run-script/node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "node_modules/@npmcli/run-script/node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4" + "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@npmcli/run-script/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "node_modules/@npmcli/run-script/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, "license": "ISC", "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/angular": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/angular/-/angular-19.8.10.tgz", - "integrity": "sha512-a9AIrD31ISq/+ta6+qe91Ds0KnWDzAVgAy6LWef6CWGXOupDkC53NozG93EcMsDhahLAMyxq5k431sHeRIKGDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/angular": "19.8.10", - "tslib": "^2.3.0" - } - }, - "node_modules/@nrwl/cypress": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/cypress/-/cypress-19.8.10.tgz", - "integrity": "sha512-54q/f2M75Q6r8u90O7HUt3LtX2vgw1kapnZ+sGN2Ky4+RvhgfwgKUDnnSw4+Zsx8DMJqCG4bOPZFryJs/oBX/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/cypress": "19.8.10" - } - }, - "node_modules/@nrwl/devkit": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.8.10.tgz", - "integrity": "sha512-voDKQcf5v7HvjDeF8x21kULJK6OqOdeRS9lPCSnbF2cKwKGfdEPszLxw7j/SPV5R6TYKs5rDHt8Yj72RhXfteQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "19.8.10" - } - }, - "node_modules/@nrwl/eslint-plugin-nx": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.8.10.tgz", - "integrity": "sha512-S9hRhxmDGPrXb/je67Oks1yCW1mXqxUOajj+G03Rag5qnSuy8hNNNgvJLpRILIyrG8W4CWkQFOj0B3QcOjESSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/eslint-plugin": "19.8.10" + "node": ">=18" } }, - "node_modules/@nrwl/jest": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/jest/-/jest-19.8.10.tgz", - "integrity": "sha512-QUumecjdMsBeZ0ubRNZi4vW9G38KZ3qqOJEF7YbOVxwtjxss19wI53rTXc6AEuu2wHNPW+V5Y+fwaN2DeijfBg==", + "node_modules/@npmcli/run-script/node_modules/unique-filename": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@nx/jest": "19.8.10" + "unique-slug": "^5.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nrwl/js": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.8.10.tgz", - "integrity": "sha512-3mVljFIlizoBDeyVBHsRuq7LMbij4NSL0zOJoEILsBcNjmZ4UZQhkztH/jbWN9JCSyWxDmo991d9KkCA5zxAKQ==", + "node_modules/@npmcli/run-script/node_modules/unique-slug": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@nx/js": "19.8.10" + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nrwl/tao": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.8.10.tgz", - "integrity": "sha512-fY/g5r4mqDrxcyHeg2ggi1U4B+24y8JZISmn4l6pXDXr13hdTuBv6nNxJhogrb/RW24IkweqYtAsHjh1d5CoYw==", + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "nx": "19.8.10", - "tslib": "^2.3.0" + "isexe": "^3.1.1" }, "bin": { - "tao": "index.js" - } - }, - "node_modules/@nrwl/web": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/web/-/web-19.8.10.tgz", - "integrity": "sha512-ReDe4SmHQ4mjHqnnWKSBeZIKj0bJ2a4BN9gwfLrcMLNdXFfpbau4OX9rMRgkETbiHVA5j8NIQYSCEjsp1lYQsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/web": "19.8.10" - } - }, - "node_modules/@nrwl/webpack": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/webpack/-/webpack-19.8.10.tgz", - "integrity": "sha512-mxTnM5hgMrfJSsUvk1ioFqykOLcJyo+2FSgJAaxn6xzq+UI5W+KzDC9ktzv4+b6I4bx/OS2LD0iDCrugegipnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/webpack": "19.8.10" + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/@nrwl/workspace": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.8.10.tgz", - "integrity": "sha512-W90BBVVTaDxlHtATQ9RQdKA8YIxziCL3p7NZcdqWMqa2o21Q0eer2QpvUGRrY5VxcthsnPJNW9kjitv1nnD7EQ==", + "node_modules/@npmcli/run-script/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", "dev": true, - "license": "MIT", - "dependencies": { - "@nx/workspace": "19.8.10" + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/@nx/angular": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/angular/-/angular-19.8.10.tgz", - "integrity": "sha512-I0hyaqMUJ/kDjHBO2klMT+SrcS5XOmhwhZCcBnEfYpw3QgKprTXJW1lzHG1mw7/hSRsPYq9Q4QowVUKI6GGPwA==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/angular/-/angular-20.2.2.tgz", + "integrity": "sha512-MVPc1Aywwg3axV1/O+nlbpVQXFc6TDadr/WkvUFGJJJ/Kf1KUeiyvAckY8b8H5Y9oS8ojI78UTsrB3HOko91bQ==", "dev": true, "license": "MIT", "dependencies": { - "@module-federation/enhanced": "~0.6.0", - "@nrwl/angular": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/eslint": "19.8.10", - "@nx/js": "19.8.10", - "@nx/web": "19.8.10", - "@nx/webpack": "19.8.10", - "@nx/workspace": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/eslint": "20.2.2", + "@nx/js": "20.2.2", + "@nx/module-federation": "20.2.2", + "@nx/web": "20.2.2", + "@nx/webpack": "20.2.2", + "@nx/workspace": "20.2.2", "@phenomnomnominal/tsquery": "~5.0.1", "@typescript-eslint/type-utils": "^8.0.0", "chalk": "^4.1.0", - "find-cache-dir": "^3.3.2", "magic-string": "~0.30.2", "minimatch": "9.0.3", "piscina": "^4.4.0", "semver": "^7.5.3", "tslib": "^2.3.0", - "webpack": "^5.88.0", "webpack-merge": "^5.8.0" }, "peerDependencies": { - "@angular-devkit/build-angular": ">= 16.0.0 < 19.0.0", - "@angular-devkit/core": ">= 16.0.0 < 19.0.0", - "@angular-devkit/schematics": ">= 16.0.0 < 19.0.0", - "@schematics/angular": ">= 16.0.0 < 19.0.0", + "@angular-devkit/build-angular": ">= 17.0.0 < 20.0.0", + "@angular-devkit/core": ">= 17.0.0 < 20.0.0", + "@angular-devkit/schematics": ">= 17.0.0 < 20.0.0", + "@schematics/angular": ">= 17.0.0 < 20.0.0", "rxjs": "^6.5.3 || ^7.5.0" } }, @@ -7271,16 +7500,15 @@ } }, "node_modules/@nx/cypress": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-19.8.10.tgz", - "integrity": "sha512-OTdjV8P3wAeXV8vOPaTV4CrnKoKI67ub/8a8VoeV0nkzPchlccsIS6Q6zkyy2BDe8qtwOSBHcAeYODoNj41q2Q==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-20.2.2.tgz", + "integrity": "sha512-Y0V5b8N0J0Ofd8JQK21DPE+MB3SwqiarF0fKMB56P7HIuV9RucLqmwqTqnfVOpnFfKrMMs96Qy1vXsaAlHQLgg==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/cypress": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/eslint": "19.8.10", - "@nx/js": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/eslint": "20.2.2", + "@nx/js": "20.2.2", "@phenomnomnominal/tsquery": "~5.0.1", "detect-port": "^1.5.1", "tslib": "^2.3.0" @@ -7295,13 +7523,12 @@ } }, "node_modules/@nx/devkit": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.10.tgz", - "integrity": "sha512-i5gWrxtniGOryiPU9df4quzrZuvuzqs8gL+GlLBaoFLqA9UNsTLShPWwHblmTK0FZZxlZYNthJR19nVweVO2ag==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-20.2.2.tgz", + "integrity": "sha512-uqs0LVvuRRVAfFdn0ewvmr1vsNV9Ztugw36emcLJxskqhBZb10K+vzdTDAZpg5aVE2ISg1BmPidoOyk1tP+Omg==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/devkit": "19.8.10", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", @@ -7316,18 +7543,17 @@ } }, "node_modules/@nx/eslint": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-19.8.10.tgz", - "integrity": "sha512-Naz/bsITv4R+GFYRx6ktNmBeUdzktrAGkKp3K+16An5dHSH3IOpzkuXbszU2lw5GXpRAfPQS5zkCAm2kESxANA==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-20.2.2.tgz", + "integrity": "sha512-GID3r539okSIdqqaLJxOttjbC8xaAbyrGJfSo/jyFLVASN4ZYuwFwWU94Vdn1NsOPHc2kiDa/qQj5mv0gbBfUw==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "19.8.10", - "@nx/js": "19.8.10", - "@nx/linter": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/js": "20.2.2", "semver": "^7.5.3", "tslib": "^2.3.0", - "typescript": "~5.4.2" + "typescript": "~5.6.2" }, "peerDependencies": { "@zkochan/js-yaml": "0.0.7", @@ -7340,16 +7566,14 @@ } }, "node_modules/@nx/eslint-plugin": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-19.8.10.tgz", - "integrity": "sha512-rV6ctG3EbGmsTmCegXuQ18/bXpoVXEZbUzP90WIkX7RMt8e0RziwfNTkItSP5B449LQQtqEon4Ju+AfbItqHAg==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-20.2.2.tgz", + "integrity": "sha512-LfRPu6QWPRQgsJ51WtsMyoK7FhvUGO5G5l/m+PyN2FecnZJcrrRCcExt3Sj0btzc0CqCW2gtgSTa1eyC16U0rQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint/compat": "^1.1.1", - "@nrwl/eslint-plugin-nx": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/js": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/js": "20.2.2", "@typescript-eslint/type-utils": "^8.0.0", "@typescript-eslint/utils": "^8.0.0", "chalk": "^4.1.0", @@ -7403,9 +7627,9 @@ } }, "node_modules/@nx/eslint-plugin/node_modules/globals": { - "version": "15.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", - "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", + "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==", "dev": true, "license": "MIT", "engines": { @@ -7428,32 +7652,17 @@ "node": ">=8" } }, - "node_modules/@nx/eslint/node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/@nx/jest": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-19.8.10.tgz", - "integrity": "sha512-QhGwV++PvaMAkhgVqwXVbksUoW4GDCvwgpJHM2NcyL5RGIRGV8c2Lw/28Lj42sDgcFzeAh7+BPy0OxDQQErzXw==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.2.2.tgz", + "integrity": "sha512-czZprpiVAZQKixpib1Vphi3Aoh5qBr7KATgP7+P0ogDTrxd7sivCFDM8wZeilhdTfx85wsR0viOtLVm6D3RTLA==", "dev": true, "license": "MIT", "dependencies": { "@jest/reporters": "^29.4.1", "@jest/test-result": "^29.4.1", - "@nrwl/jest": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/js": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/js": "20.2.2", "@phenomnomnominal/tsquery": "~5.0.1", "chalk": "^4.1.0", "identity-obj-proxy": "3.0.0", @@ -7514,9 +7723,9 @@ } }, "node_modules/@nx/js": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.10.tgz", - "integrity": "sha512-gAt3XnXyYJiLyeXIAwHjHwZ34irLCvpINSAQoD2xY+1ZHU3RXJG8QgqlgUIfGUVhbCr8IovK9gwUCwLm4uAsag==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-20.2.2.tgz", + "integrity": "sha512-y/L+GMS8pIE1rQTQ28Lb1YeWpEnDj2v3T/7QpWvICc78NZXuMrO6N1ZRTPRSQNXKL6Bs9S9bRuivsvSIiNlULw==", "dev": true, "license": "MIT", "dependencies": { @@ -7527,9 +7736,9 @@ "@babel/preset-env": "^7.23.2", "@babel/preset-typescript": "^7.22.5", "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/workspace": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/workspace": "20.2.2", + "@zkochan/js-yaml": "0.0.7", "babel-plugin-const-enum": "^1.0.1", "babel-plugin-macros": "^2.8.0", "babel-plugin-transform-typescript-metadata": "^0.3.1", @@ -7537,7 +7746,6 @@ "columnify": "^1.6.0", "detect-port": "^1.5.1", "enquirer": "~2.3.6", - "fast-glob": "3.2.7", "ignore": "^5.0.4", "js-tokens": "^4.0.0", "jsonc-parser": "3.2.0", @@ -7547,6 +7755,7 @@ "ora": "5.3.0", "semver": "^7.5.3", "source-map-support": "0.5.19", + "tinyglobby": "^0.2.10", "ts-node": "10.9.1", "tsconfig-paths": "^4.1.2", "tslib": "^2.3.0" @@ -7593,34 +7802,17 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@nx/js/node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nx/js/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@nx/js/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", "dev": true, "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "lru-cache": "^10.0.1" }, "engines": { - "node": ">= 6" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/@nx/js/node_modules/jsonc-parser": { @@ -7630,6 +7822,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@nx/js/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/@nx/js/node_modules/npm-package-arg": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", @@ -7713,56 +7912,209 @@ "node": ">=8" } }, - "node_modules/@nx/linter": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/linter/-/linter-19.8.10.tgz", - "integrity": "sha512-WEDMLiaLT+JLCVtQF7058I/hRkgR5B7k7oGJ2zxk0iISJfJW2/mkfxW+kEQmQ935F5IjJ/KEiDeIQcTAzuqUdw==", + "node_modules/@nx/js/node_modules/validate-npm-package-name": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", + "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@nx/eslint": "19.8.10" + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.10.tgz", - "integrity": "sha512-zZ0EI1DjFLb5aebjZZuR89irSWZMse9E13QymZLsC8+WE2PMvcwkwUfbMEIhIze88zsThcF1R5U1qZKmrgcD9w==", - "cpu": [ - "arm64" - ], + "node_modules/@nx/module-federation": { + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/module-federation/-/module-federation-20.2.2.tgz", + "integrity": "sha512-KwxFV/ecRnMIplCJVdC3P7rhhP6pj2eoYvqUuEFjRkGeYRZhArlOT2dHHOgdRz427RAbLsOhZzFAdPI+LF7cxA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "@module-federation/enhanced": "0.7.6", + "@module-federation/node": "2.6.11", + "@module-federation/sdk": "0.7.6", + "@nx/devkit": "20.2.2", + "@nx/js": "20.2.2", + "@nx/web": "20.2.2", + "@rspack/core": "^1.1.5", + "express": "^4.19.2", + "http-proxy-middleware": "^3.0.3", + "picocolors": "^1.1.0", + "tslib": "^2.3.0", + "webpack": "5.88.0" } }, - "node_modules/@nx/nx-darwin-x64": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.10.tgz", - "integrity": "sha512-8vypmuiwIe3t0aaE1b3G34tx6mIUW6a4nbbhMOISWO2ehaX/bnMMbIbrkp/sAP1fYhydbXIqcgixWsN/h3qu1A==", - "cpu": [ - "x64" - ], + "node_modules/@nx/module-federation/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@nx/nx-freebsd-x64": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.10.tgz", - "integrity": "sha512-onwAPBoK6nMqniDuHMb4loGuXazodiql23VOlFxe4oIKZKa1A1/l8Z7BW12rW7dpIuL44T+Z83ZTSYZOR84cag==", - "cpu": [ - "x64" + "node_modules/@nx/module-federation/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@nx/module-federation/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@nx/module-federation/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@nx/module-federation/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/module-federation/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nx/module-federation/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@nx/module-federation/node_modules/webpack": { + "version": "5.88.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.0.tgz", + "integrity": "sha512-O3jDhG5e44qIBSi/P6KpcCcH7HD+nYIHVBhdWFxcLOcIGN8zGo5nqF3BjyNCxIh4p1vFdNnreZv2h2KkoAw3lw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-20.2.2.tgz", + "integrity": "sha512-gnS5mtbaBAO5TJkl4T68rQaN/79MMWePavw2SOcFyFnIdAriGEZ+ZFDUE0B/xYJSs9CPWLaGHf+n7oqyxaGd9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-darwin-x64": { + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-20.2.2.tgz", + "integrity": "sha512-IctvdQon+K8mlhl06zIq1xTPwf5L4OuS7crzCmK26p5F/lV6iz/UXSPCcgn+bYKOL/q3QCLNR7UasQMjzgCNkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-20.2.2.tgz", + "integrity": "sha512-4/Blg9Y6LVU8tS8yoa2BEXPHWsorpvCuZRH0gXPh96i6b71o4ORPafyLOHp08o3WjtUZb4jl5TfDryE+8y62ZA==", + "cpu": [ + "x64" ], "dev": true, "license": "MIT", @@ -7775,9 +8127,9 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.10.tgz", - "integrity": "sha512-DqDIxe+i8y34srvI5tO09aSai71a620bQvv3dJTfon2Vbr4i4wUsqA99hXFEwEeI2Sjva3vM2eGnEIMEhLAiXQ==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-20.2.2.tgz", + "integrity": "sha512-AVAxbUXi6q+inmp8re3OV7HzH6fbkKnnMKvjDLnkzK8dA2Mv4JFl/gz++rgkYfEsBk20lcB1i3unqNrtOvzS7Q==", "cpu": [ "arm" ], @@ -7792,9 +8144,9 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.10.tgz", - "integrity": "sha512-JEFOtH6vIJB8f2aOg7ZxbPLjLdh04jpVbycE8F4l3W0DjaW7j+sb0vFlsRNsZPq9ZlP9aLXsx/o8ebyEZqCzmQ==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-20.2.2.tgz", + "integrity": "sha512-h04SLH464Oh/k/1mpAfsMhTVlnc1NJItx4N5DLZb2VuOOY+Tquhrp7HBJLyAhU0Q74JG0LevGFO6wdxliHupmA==", "cpu": [ "arm64" ], @@ -7809,9 +8161,9 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.10.tgz", - "integrity": "sha512-KWj7Z/dtwwbQDQi/zA3jBCd1UJ9o8BUGzsLZn0+6fG1ztHw+wy6hzBNvjW6IAabAfMZSozFb3pTFr6gr2UdfZQ==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-20.2.2.tgz", + "integrity": "sha512-rnRXDLvHHj66rCslD4ShDq6KBOVsQ+X63GWTGKM0pnTIIDje9+ltZCoAByieCUm4BvFfCWMUf9y0mGfZvLVKSw==", "cpu": [ "arm64" ], @@ -7826,9 +8178,9 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.10.tgz", - "integrity": "sha512-Soxogm5eql+bj4SIY8uFQGJAh/ODsFhiztaA+NxkYnRJOrLIWw+gprHDpyTUi2y4erSj1lHu+DiIZQ43cHq2fw==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-20.2.2.tgz", + "integrity": "sha512-K1Z2DVTnyCGl4nolhZ8fvHEixoe1pZOY256LD6D0lGca4Fsi3mHQ7lDU237Pzyc91+cfLva/OAvrivRPeU+DMA==", "cpu": [ "x64" ], @@ -7843,9 +8195,9 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.10.tgz", - "integrity": "sha512-IDEgKqlY0XMNkiZIcKmvhClRRi/6z2fFHvjsLDOmghqzUS8vyRSeEaHiTiKAh5yzNL2gkK96Mcx6OLi4Lrrc4Q==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-20.2.2.tgz", + "integrity": "sha512-pyWe+d2Y2pJVgPZf27KkDBufhFPq+Xhs3/zAQdJbicMvym7uhw0qMTV+lmoMXgfx52WZzhqTfG8JQcDqHjExJw==", "cpu": [ "x64" ], @@ -7860,9 +8212,9 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.10.tgz", - "integrity": "sha512-o9YhREK0ogXxKDwE4ci6HtWJX3DGigpvQFK9U8VxzHZQb/sOOVgAU8lNpneH50o1BsPsfPFZFmpt9oYw61ps3Q==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-20.2.2.tgz", + "integrity": "sha512-zqSoVrV34tx6qhQo/PwD9IMGhzoNSaFQxjTjNCY61sE7iwi5Qt4dDs3Rlh1ZFCBFnrjziymRPY2RryArgeK8Bw==", "cpu": [ "arm64" ], @@ -7877,9 +8229,9 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.10.tgz", - "integrity": "sha512-gayjQyHU18Jglt+95f4DsnTOETW8+pX6zNbd9wPFyf6PQCmoc62kl07/NxJMzRNkzwK7p3CzS7aQlCe4wJf+Xg==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-20.2.2.tgz", + "integrity": "sha512-IfQf2axmCuSArhFGaocIDt8ajWDHXoVut5NOQH4eV2q9whP1j/LVB8EehEaolF5UenM7rhL4V25PXPuuBaUq4A==", "cpu": [ "x64" ], @@ -7894,15 +8246,14 @@ } }, "node_modules/@nx/web": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/web/-/web-19.8.10.tgz", - "integrity": "sha512-kbh5lWUrbLIVSo93PLFCd3l2vzR3uL0+8hSX1rya8/tFZJn3ChPphf9gE6RvUOVoJ0FiwtayJxtjATFUXvsXwQ==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-20.2.2.tgz", + "integrity": "sha512-Z1MEKv3rEvs4W0h1Ltvh66VtJ29YZ+RWuLWzPebf8K1z9818RbXR3FpMiM1edkHyaykeQeJcK6D5aIHPwti/Bg==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/web": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/js": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/js": "20.2.2", "detect-port": "^1.5.1", "http-server": "^14.1.0", "picocolors": "^1.1.0", @@ -7910,36 +8261,31 @@ } }, "node_modules/@nx/webpack": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-19.8.10.tgz", - "integrity": "sha512-+zGJz3w7QWwhpyr9idSH4YpUpqAmGHHeXc+iJENRfLN6BaxwpjyOJTy8A56bfbKzzty3YW0CUASUoMZEoBgJaQ==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/webpack/-/webpack-20.2.2.tgz", + "integrity": "sha512-hlt9L24rvk7xrgD2BnLxMqOWeoV5DsF0ZJc05EbIMuM8yg03agsC79Rq1gaRoM3uIhCb+CxW0mlQpcVKnPXMUw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.23.2", - "@module-federation/enhanced": "^0.6.0", - "@module-federation/sdk": "^0.6.0", - "@nrwl/webpack": "19.8.10", - "@nx/devkit": "19.8.10", - "@nx/js": "19.8.10", + "@nx/devkit": "20.2.2", + "@nx/js": "20.2.2", "@phenomnomnominal/tsquery": "~5.0.1", "ajv": "^8.12.0", "autoprefixer": "^10.4.9", "babel-loader": "^9.1.2", "browserslist": "^4.21.4", - "chalk": "^4.1.0", "copy-webpack-plugin": "^10.2.4", "css-loader": "^6.4.0", "css-minimizer-webpack-plugin": "^5.0.0", - "express": "^4.19.2", "fork-ts-checker-webpack-plugin": "7.2.13", - "http-proxy-middleware": "^3.0.0", "less": "4.1.3", "less-loader": "11.1.0", "license-webpack-plugin": "^4.0.2", "loader-utils": "^2.0.3", "mini-css-extract-plugin": "~2.4.7", "parse5": "4.0.0", + "picocolors": "^1.1.0", "postcss": "^8.4.38", "postcss-import": "~14.1.0", "postcss-loader": "^6.1.1", @@ -7948,7 +8294,7 @@ "sass-loader": "^12.2.0", "source-map-loader": "^5.0.0", "style-loader": "^3.3.0", - "stylus": "^0.59.0", + "stylus": "^0.64.0", "stylus-loader": "^7.1.0", "terser-webpack-plugin": "^5.3.3", "ts-loader": "^9.3.1", @@ -7960,39 +8306,6 @@ "webpack-subresource-integrity": "^5.1.0" } }, - "node_modules/@nx/webpack/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nx/webpack/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@nx/webpack/node_modules/copy-webpack-plugin": { "version": "10.2.4", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-10.2.4.tgz", @@ -8308,31 +8621,27 @@ "node": ">=0.10.0" } }, - "node_modules/@nx/webpack/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==", + "node_modules/@nx/webpack/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "ISC", "engines": { - "node": ">=8" + "node": ">= 6" } }, "node_modules/@nx/workspace": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.10.tgz", - "integrity": "sha512-oqopf4pbuKE5Qs2FG/Hdl/5ln5Seo6LPiW6XVI4FPs6Wi7eiXAb5Umc6MOqpg9dZTlmWeAWm6wt13yXzNGs8YA==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-20.2.2.tgz", + "integrity": "sha512-VC22d5EG9f8sLD+gvq9Nbau0u8cV0gy5aYyRcleecqs9bBvOiVxAvv7HaDCRcHezHQhKwxcIOZvmuCjYF/oKxg==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/workspace": "19.8.10", - "@nx/devkit": "19.8.10", + "@nx/devkit": "20.2.2", "chalk": "^4.1.0", "enquirer": "~2.3.6", - "nx": "19.8.10", + "nx": "20.2.2", "tslib": "^2.3.0", "yargs-parser": "21.1.1" } @@ -8347,73 +8656,420 @@ "color-convert": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@nx/workspace/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@nx/workspace/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/@nxext/capacitor": { + "version": "20.1.0", + "resolved": "https://registry.npmjs.org/@nxext/capacitor/-/capacitor-20.1.0.tgz", + "integrity": "sha512-dIXjyw5318rxuKNcXWlJgF8cfxvFl4wI48It80/w09tNq6fjYjhtoeYNwRzkDg2qTPyKAmsgFwXsESRwXTZs3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nxext/common": "20.0.1", + "ignore": "^5.3.1", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@nx/devkit": "^20.0.0", + "@nx/js": "^20.0.0", + "nx": "^20.0.0" + } + }, + "node_modules/@nxext/common": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@nxext/common/-/common-20.0.1.tgz", + "integrity": "sha512-CoEuN6tABHzkIYXnBfLixTvxQkFpPH1t3hgbZEQJmwo11sx3SbIbcL+npr+UuBuUhUz/DctDaH3ZFGg0hHH7jA==", + "dev": true, + "dependencies": { + "@nx/devkit": "^20.0.0", + "@nx/js": "^20.0.0", + "tslib": "^2.3.0", + "typescript": "^5.4.2" + } + }, + "node_modules/@nxext/ionic-angular": { + "version": "20.0.5", + "resolved": "https://registry.npmjs.org/@nxext/ionic-angular/-/ionic-angular-20.0.5.tgz", + "integrity": "sha512-YpUGHmDEDsvMr3Cn1Xqc68xEMj79SzsBuvG5fgenN970yl0z+PArdF0MVff8XzejHAE8a4jONDOgFdggDDEpEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nxext/capacitor": "^20.1.0", + "@phenomnomnominal/tsquery": "~5.0.1", + "tslib": "^2.3.0", + "typescript": "^5.4.2" + }, + "peerDependencies": { + "@nx/angular": "^20.0.0", + "@nx/devkit": "^20.0.0", + "@nx/js": "^20.0.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz", + "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.0", + "@parcel/watcher-darwin-arm64": "2.5.0", + "@parcel/watcher-darwin-x64": "2.5.0", + "@parcel/watcher-freebsd-x64": "2.5.0", + "@parcel/watcher-linux-arm-glibc": "2.5.0", + "@parcel/watcher-linux-arm-musl": "2.5.0", + "@parcel/watcher-linux-arm64-glibc": "2.5.0", + "@parcel/watcher-linux-arm64-musl": "2.5.0", + "@parcel/watcher-linux-x64-glibc": "2.5.0", + "@parcel/watcher-linux-x64-musl": "2.5.0", + "@parcel/watcher-win32-arm64": "2.5.0", + "@parcel/watcher-win32-ia32": "2.5.0", + "@parcel/watcher-win32-x64": "2.5.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz", + "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz", + "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz", + "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz", + "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz", + "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz", + "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz", + "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz", + "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz", + "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz", + "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz", + "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz", + "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@nx/workspace/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz", + "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10" + "node": ">= 10.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/@nx/workspace/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==", + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" }, "engines": { - "node": ">=8" - } - }, - "node_modules/@nxext/capacitor": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@nxext/capacitor/-/capacitor-19.1.2.tgz", - "integrity": "sha512-iKrSsQc4QyTWT0NIlbMo65oWHVgGTqRXoH1dlQ+8Yo1pOytItdQD7TLCsvl/lUH8UWcVqfsSUumb8CZUpfMc2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ignore": "^5.3.1", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@nx/devkit": "^19.0.0", - "nx": "^19.0.0" + "node": ">=0.10" } }, - "node_modules/@nxext/ionic-angular": { - "version": "19.1.2", - "resolved": "https://registry.npmjs.org/@nxext/ionic-angular/-/ionic-angular-19.1.2.tgz", - "integrity": "sha512-OiRjsNWTLSgUNpneIgenKrEer9s8jWgLPfxGkSZQnjdnq+IhP5DYipAgXSbfGAPdDnvhPSIZJEtuWeALbnM/1Q==", + "node_modules/@parcel/watcher/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==", "dev": true, "license": "MIT", - "dependencies": { - "@nxext/capacitor": "^19.1.2", - "@phenomnomnominal/tsquery": "~5.0.1", - "tslib": "^2.3.0", - "typescript": "5.5.4" - }, - "peerDependencies": { - "@nx/angular": "^19.0.0", - "@nx/devkit": "^19.0.0" - } + "optional": true }, "node_modules/@phenomnomnominal/tsquery": { "version": "5.0.1", @@ -8440,9 +9096,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.26.0.tgz", + "integrity": "sha512-gJNwtPDGEaOEgejbaseY6xMFu+CPltsc8/T+diUTTbOQLqD+bnrJq9ulH6WD69TqwqWmrfRAtUv30cCFZlbGTQ==", "cpu": [ "arm" ], @@ -8454,9 +9110,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.26.0.tgz", + "integrity": "sha512-YJa5Gy8mEZgz5JquFruhJODMq3lTHWLm1fOy+HIANquLzfIOzE9RA5ie3JjCdVb9r46qfAQY/l947V0zfGJ0OQ==", "cpu": [ "arm64" ], @@ -8468,9 +9124,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.26.0.tgz", + "integrity": "sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==", "cpu": [ "arm64" ], @@ -8482,9 +9138,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.26.0.tgz", + "integrity": "sha512-wbgkYDHcdWW+NqP2mnf2NOuEbOLzDblalrOWcPyY6+BRbVhliavon15UploG7PpBRQ2bZJnbmh8o3yLoBvDIHA==", "cpu": [ "x64" ], @@ -8495,10 +9151,38 @@ "darwin" ] }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.26.0.tgz", + "integrity": "sha512-Y9vpjfp9CDkAG4q/uwuhZk96LP11fBz/bYdyg9oaHYhtGZp7NrbkQrj/66DYMMP2Yo/QPAsVHkV891KyO52fhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.26.0.tgz", + "integrity": "sha512-A/jvfCZ55EYPsqeaAt/yDAG4q5tt1ZboWMHEvKAH9Zl92DWvMIbnZe/f/eOXze65aJaaKbL+YeM0Hz4kLQvdwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.26.0.tgz", + "integrity": "sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==", "cpu": [ "arm" ], @@ -8510,9 +9194,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.26.0.tgz", + "integrity": "sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==", "cpu": [ "arm" ], @@ -8524,9 +9208,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.26.0.tgz", + "integrity": "sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==", "cpu": [ "arm64" ], @@ -8538,9 +9222,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.26.0.tgz", + "integrity": "sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==", "cpu": [ "arm64" ], @@ -8552,9 +9236,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.26.0.tgz", + "integrity": "sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==", "cpu": [ "ppc64" ], @@ -8566,9 +9250,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.26.0.tgz", + "integrity": "sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==", "cpu": [ "riscv64" ], @@ -8580,9 +9264,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.26.0.tgz", + "integrity": "sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==", "cpu": [ "s390x" ], @@ -8594,9 +9278,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", - "integrity": "sha512-87v0ol2sH9GE3cLQLNEy0K/R0pz1nvg76o8M5nhMR0+Q+BBGLnb35P0fVz4CQxHYXaAOhE8HhlkaZfsdUOlHwg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.26.0.tgz", + "integrity": "sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==", "cpu": [ "x64" ], @@ -8608,9 +9292,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.22.4.tgz", - "integrity": "sha512-UV6FZMUgePDZrFjrNGIWzDo/vABebuXBhJEqrHxrGiU6HikPy0Z3LfdtciIttEUQfuDdCn8fqh7wiFJjCNwO+g==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.26.0.tgz", + "integrity": "sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==", "cpu": [ "x64" ], @@ -8622,9 +9306,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.26.0.tgz", + "integrity": "sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==", "cpu": [ "arm64" ], @@ -8636,9 +9320,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.26.0.tgz", + "integrity": "sha512-D4CxkazFKBfN1akAIY6ieyOqzoOoBV1OICxgUblWxff/pSjCA2khXlASUx7mK6W1oP4McqhgcCsu6QaLj3WMWg==", "cpu": [ "ia32" ], @@ -8650,9 +9334,153 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.26.0.tgz", + "integrity": "sha512-2x8MO1rm4PGEP0xWbubJW5RtbNLk3puzAMaLQd3B3JHVw4KcHlmXcO+Wewx9zCoo7EUFiMlu/aZbCJ7VjMzAag==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.1.6.tgz", + "integrity": "sha512-vfeBEgGOYVwqj5cQjGyvdfrr/BEihAHlyIsobL98FZjTF0uig+bj2yJUH5Ib5F0BpIUKVG3Pw0IjlUBqcVpZsQ==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "@rspack/binding-darwin-arm64": "1.1.6", + "@rspack/binding-darwin-x64": "1.1.6", + "@rspack/binding-linux-arm64-gnu": "1.1.6", + "@rspack/binding-linux-arm64-musl": "1.1.6", + "@rspack/binding-linux-x64-gnu": "1.1.6", + "@rspack/binding-linux-x64-musl": "1.1.6", + "@rspack/binding-win32-arm64-msvc": "1.1.6", + "@rspack/binding-win32-ia32-msvc": "1.1.6", + "@rspack/binding-win32-x64-msvc": "1.1.6" + } + }, + "node_modules/@rspack/binding-darwin-arm64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.1.6.tgz", + "integrity": "sha512-x9dxm2yyiMuL1FBwvWNNMs2/mEUJmRoSRgYb8pblR7HDaTRORrjBFCqhaYlGyAqtQaeUy7o2VAQlE0BavIiFYA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-darwin-x64": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.1.6.tgz", + "integrity": "sha512-o0seilveftGiDjy3VPxug20HmAgYyQbNEuagR3i93/t/PT/eWXHnik+C1jjwqcivZL1Zllqvy4tbZw393aROEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rspack/binding-linux-arm64-gnu": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.6.tgz", + "integrity": "sha512-4atnoknJx/c3KaQElsMIxHMpPf2jcRRdWsH/SdqJIRSrkWWakMK9Yv4TFwH680I4HDTMf1XLboMVScHzW8e+Mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-arm64-musl": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.6.tgz", + "integrity": "sha512-7QMtwUtgFpt3/Y3/X18fSyN+kk4H8ZnZ8tDzQskVWc/j2AQYShZq56XQYqrhClzwujcCVAHauIQ2eiuJ2ASGag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-gnu": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.6.tgz", + "integrity": "sha512-MTjDEfPn4TwHoqs5d5Fck06kmXiTHZctGIcRVfrpg0RK0r1NLEHN+oosavRZ9c9H70f34+NmcHk+/qvV4c8lWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-linux-x64-musl": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.6.tgz", + "integrity": "sha512-LqDw7PTVr/4ZuGA0izgDQfamfr72USFHltR1Qhy2YVC3JmDmhG/pQi13LHcOLVaGH1xoeyCmEPNJpVizzDxSjg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rspack/binding-win32-arm64-msvc": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.6.tgz", + "integrity": "sha512-RHApLM93YN0WdHpS35u2cm7VCqZ8Yg3CrNRL16VJtyT9e6MBqeScoe4XIgIWKPm7edFyedYAjLX0wQOApwfjkg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-ia32-msvc": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.1.6.tgz", + "integrity": "sha512-Y6lx4q0eJawRfMPBo/AclTJAPTZ325DSPFBQJB3TnWh9Z2X7P7pQcYc8PHDmfDuYRIdg5WRsQRvVxihSvF7v8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rspack/binding-win32-x64-msvc": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.6.tgz", + "integrity": "sha512-UuCsfhC/yNuU7xLASOxNXcmsXi2ZvBX14GkxvcdChw6q7IIGNYUKXo1zgR8C1PE/6qDSxmLxbRMS+71d0H3HQg==", "cpu": [ "x64" ], @@ -8663,6 +9491,79 @@ "win32" ] }, + "node_modules/@rspack/core": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.1.6.tgz", + "integrity": "sha512-q0VLphOF5VW2FEG7Vbdq3Ke4I74FbELE/8xmKghSalFtULLZ44SoSz8lyotfMim9GXIRFhDokAaH8WICmPxG+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime-tools": "0.5.1", + "@rspack/binding": "1.1.6", + "@rspack/lite-tapable": "1.0.1", + "caniuse-lite": "^1.0.30001616" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.1" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/runtime": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime/-/runtime-0.5.1.tgz", + "integrity": "sha512-xgiMUWwGLWDrvZc9JibuEbXIbhXg6z2oUkemogSvQ4LKvrl/n0kbqP1Blk669mXzyWbqtSp6PpvNdwaE1aN5xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/sdk": "0.5.1" + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/runtime-tools": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@module-federation/runtime-tools/-/runtime-tools-0.5.1.tgz", + "integrity": "sha512-nfBedkoZ3/SWyO0hnmaxuz0R0iGPSikHZOAZ0N/dVSQaIzlffUo35B5nlC2wgWIc0JdMZfkwkjZRrnuuDIJbzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.5.1", + "@module-federation/webpack-bundler-runtime": "0.5.1" + } + }, + "node_modules/@rspack/core/node_modules/@module-federation/sdk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@module-federation/sdk/-/sdk-0.5.1.tgz", + "integrity": "sha512-exvchtjNURJJkpqjQ3/opdbfeT2wPKvrbnGnyRkrwW5o3FH1LaST1tkiNviT6OXTexGaVc2DahbdniQHVtQ7pA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rspack/core/node_modules/@module-federation/webpack-bundler-runtime": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@module-federation/webpack-bundler-runtime/-/webpack-bundler-runtime-0.5.1.tgz", + "integrity": "sha512-mMhRFH0k2VjwHt3Jol9JkUsmI/4XlrAoBG3E0o7HoyoPYv1UFOWyqAflfANcUPgbYpvqmyLzDcO+3IT36LXnrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@module-federation/runtime": "0.5.1", + "@module-federation/sdk": "0.5.1" + } + }, + "node_modules/@rspack/lite-tapable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rspack/lite-tapable/-/lite-tapable-1.0.1.tgz", + "integrity": "sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -8671,14 +9572,14 @@ "license": "MIT" }, "node_modules/@schematics/angular": { - "version": "18.2.11", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-18.2.11.tgz", - "integrity": "sha512-jT54mc9+hPOwie9bji/g2krVuK1kkNh2PNFGwfgCg3Ofmt3hcyOBai1DKuot5uLTX4VCCbvfwiVR/hJniQl2SA==", + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-19.0.4.tgz", + "integrity": "sha512-1fXBtkA/AjgMPxHLpGlw7NuT/wggCqAwBAmDnSiRnBBV7Pgs/tHorLgh7A9eoUi3c8CYCuAh8zqWNyjBGGigOQ==", "dev": true, "license": "MIT", "dependencies": { - "@angular-devkit/core": "18.2.11", - "@angular-devkit/schematics": "18.2.11", + "@angular-devkit/core": "19.0.4", + "@angular-devkit/schematics": "19.0.4", "jsonc-parser": "3.3.1" }, "engines": { @@ -8776,17 +9677,6 @@ "integrity": "sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==", "license": "MIT" }, - "node_modules/@serialport/bindings-cpp/node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/@serialport/bindings-interface": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@serialport/bindings-interface/-/bindings-interface-1.2.2.tgz", @@ -8956,26 +9846,26 @@ "license": "MIT" }, "node_modules/@sigstore/bundle": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", - "integrity": "sha512-wueKWDk70QixNLB363yHc2D2ItTgYiMTdPwK8D9dKQMR3ZQ0c35IxP5xnwQ8cNLoCgCRcHf14kE+CLIvNX1zmA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-3.0.0.tgz", + "integrity": "sha512-XDUYX56iMPAn/cdgh/DTJxz5RWmqKV4pwvUAEKEWJl+HzKdCd/24wUa9JYNMlDSCb7SUHAdtksxYX779Nne/Zg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/core": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.1.0.tgz", - "integrity": "sha512-JzBqdVIyqm2FRQCulY6nbQzMpJJpSiJ8XXWMhtOX9eKgaXXpfNOF53lzQEjIydlStnd/eFtuC1dW4VYdD93oRg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-2.0.0.tgz", + "integrity": "sha512-nYxaSb/MtlSI+JWcwTHQxyNmWeWrUXJJ/G4liLrGG7+tS4vAz6LF3xRXqLH6wPIVUoZQel2Fs4ddLx4NCpiIYg==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/protobuf-specs": { @@ -8989,44 +9879,44 @@ } }, "node_modules/@sigstore/sign": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.3.2.tgz", - "integrity": "sha512-5Vz5dPVuunIIvC5vBb0APwo7qKA4G9yM48kPWJT+OEERs40md5GoUR1yedwpekWZ4m0Hhw44m6zU+ObsON+iDA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-3.0.0.tgz", + "integrity": "sha512-UjhDMQOkyDoktpXoc5YPJpJK6IooF2gayAr5LvXI4EL7O0vd58okgfRcxuaH+YTdhvb5aa1Q9f+WJ0c2sVuYIw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^13.0.1", - "proc-log": "^4.2.0", + "make-fetch-happen": "^14.0.1", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/sign/node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/sign/node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", - "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -9034,13 +9924,23 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/@sigstore/sign/node_modules/fs-minipass": { @@ -9085,27 +9985,26 @@ "license": "ISC" }, "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/sign/node_modules/minimatch": { @@ -9148,89 +10047,186 @@ } }, "node_modules/@sigstore/sign/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", + "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, + "node_modules/@sigstore/sign/node_modules/minizlib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@sigstore/sign/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sigstore/sign/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@sigstore/sign/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sigstore/sign/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@sigstore/sign/node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/@sigstore/sign/node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/sign/node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/@sigstore/sign/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/@sigstore/tuf": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.4.tgz", - "integrity": "sha512-44vtsveTPUpqhm9NCrbU8CWLe3Vck2HO1PNLw7RIajbB7xhtn5RBPm1VNSCMwqGYHhDsBJG8gDF0q4lgydsJvw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-3.0.0.tgz", + "integrity": "sha512-9Xxy/8U5OFJu7s+OsHzI96IX/OzjF/zj0BSSaWhgJgTqtlBhQIV2xdrQI5qxLD7+CWWDepadnXAxzaZ3u9cvRw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^2.2.1" + "tuf-js": "^3.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sigstore/verify": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.2.1.tgz", - "integrity": "sha512-8iKx79/F73DKbGfRf7+t4dqrc0bRr0thdPrxAtCKWRm/F0tG71i6O1rvlnScncJLLBZHn3h8M3c1BSUAb9yu8g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-2.0.0.tgz", + "integrity": "sha512-Ggtq2GsJuxFNUvQzLoXqRwS4ceRfLAJnrIHUDrzAD0GgnOhwujJkKkxM/s5Bako07c3WtAs/sZo5PJq7VHjeDg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.1.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@sinclair/typebox": { @@ -9634,9 +10630,9 @@ } }, "node_modules/@swc/types": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.12.tgz", - "integrity": "sha512-wBJA+SdtkbFhHjTMYH+dEH1y4VpfGdAc2Kw/LK09i9bXd/K6j6PkDcFCEzb6iVfZMkPRrl/q0e3toqTAJdkIVA==", + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.17.tgz", + "integrity": "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -9722,17 +10718,17 @@ } }, "node_modules/@tufjs/models": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.1.tgz", - "integrity": "sha512-92F7/SFyufn4DXsha9+QfKnN03JGqtMFMXgSHbZOo8JG59WkTni7UzAouNQDf7AuP9OAMxVOPQcqG3sB7w+kkg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-3.0.1.tgz", + "integrity": "sha512-UUYHISyhCU3ZgN8yaear3cGATHb3SMuKHsQ/nVbHXcmnBf+LzQ/cQfhNG+rfaSHgqGKNEm2cOCLVLELStUQ1JA==", "dev": true, "license": "MIT", "dependencies": { "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.4" + "minimatch": "^9.0.5" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/@tufjs/models/node_modules/minimatch": { @@ -9862,9 +10858,9 @@ } }, "node_modules/@types/conventional-commits-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", - "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.1.tgz", + "integrity": "sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==", "dev": true, "license": "MIT", "dependencies": { @@ -9881,6 +10877,28 @@ "@types/ms": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -9902,9 +10920,9 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz", - "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.2.tgz", + "integrity": "sha512-vluaspfvWEtE4vcSDlKRNer52DvOGrB2xv6diXy6UKyKW0lqZiWHGNApSyxOv+8DE5Z27IzVvE7hNkxg7EXIcg==", "dev": true, "license": "MIT", "dependencies": { @@ -10072,16 +11090,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@types/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/node": { "version": "18.16.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.9.tgz", @@ -10235,13 +11243,6 @@ "license": "MIT", "optional": true }, - "node_modules/@types/wrap-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", - "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -10281,17 +11282,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", - "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz", + "integrity": "sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/type-utils": "8.14.0", - "@typescript-eslint/utils": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/type-utils": "8.18.0", + "@typescript-eslint/utils": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -10306,25 +11307,21 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", - "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.0.tgz", + "integrity": "sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q==", "dev": true, - "license": "BSD-2-Clause", + "license": "MITClause", "dependencies": { - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", "debug": "^4.3.4" }, "engines": { @@ -10335,23 +11332,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", - "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz", + "integrity": "sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0" + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10362,14 +11355,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", - "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz", + "integrity": "sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.14.0", - "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/typescript-estree": "8.18.0", + "@typescript-eslint/utils": "8.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -10380,16 +11373,15 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", - "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.0.tgz", + "integrity": "sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA==", "dev": true, "license": "MIT", "engines": { @@ -10401,14 +11393,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", - "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz", + "integrity": "sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/visitor-keys": "8.14.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/visitor-keys": "8.18.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -10423,10 +11415,8 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { @@ -10446,16 +11436,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", - "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.0.tgz", + "integrity": "sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.14.0", - "@typescript-eslint/types": "8.14.0", - "@typescript-eslint/typescript-estree": "8.14.0" + "@typescript-eslint/scope-manager": "8.18.0", + "@typescript-eslint/types": "8.18.0", + "@typescript-eslint/typescript-estree": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10465,18 +11455,19 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", - "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz", + "integrity": "sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.14.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.18.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10486,6 +11477,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@vitejs/plugin-basic-ssl": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz", @@ -10691,9 +11695,9 @@ "license": "BSD-2-Clause" }, "node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.2.tgz", + "integrity": "sha512-/HcYgtUSiJiot/XWGLOlGxPYUG65+/31V8oqk17vZLW1xlCoR4PampyePljOxY2n8/3jz9+tIFzICsyGujJZoA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -10701,7 +11705,7 @@ "tslib": "^2.4.0" }, "engines": { - "node": ">=14.15.0" + "node": ">=18.12.0" } }, "node_modules/@yr/monotone-cubic-spline": { @@ -10723,13 +11727,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@zkochan/js-yaml/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/7zip-bin": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", @@ -10790,10 +11787,11 @@ "acorn-walk": "^8.0.2" } }, - "node_modules/acorn-import-attributes": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", - "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "deprecated": "package has been renamed to acorn-import-attributes", "dev": true, "license": "MIT", "peerDependencies": { @@ -10873,14 +11871,11 @@ } }, "node_modules/agent-base": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", - "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", "dev": true, "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, "engines": { "node": ">= 14" } @@ -10961,17 +11956,21 @@ } }, "node_modules/angular-eslint": { - "version": "18.4.0", - "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-18.4.0.tgz", - "integrity": "sha512-fEayKOZlux9YhnZfWN8zNU0VlBRB+G2m/2T+R2njWlGpD1+XhieCVZPB9dh5Jv/wEvcfPypEWE3DgH4MqIRxKA==", + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/angular-eslint/-/angular-eslint-19.0.2.tgz", + "integrity": "sha512-d8P/Y5+QXOOko1x5W3Pp/p4cr7arXKGHdMAv6jtrqHjsIrlBqZSZY18apKRdTysFjYuKa5G9M3hejtzwXXHNhg==", "dev": true, "license": "MIT", "dependencies": { - "@angular-eslint/builder": "18.4.0", - "@angular-eslint/eslint-plugin": "18.4.0", - "@angular-eslint/eslint-plugin-template": "18.4.0", - "@angular-eslint/schematics": "18.4.0", - "@angular-eslint/template-parser": "18.4.0" + "@angular-devkit/core": ">= 19.0.0 < 20.0.0", + "@angular-devkit/schematics": ">= 19.0.0 < 20.0.0", + "@angular-eslint/builder": "19.0.2", + "@angular-eslint/eslint-plugin": "19.0.2", + "@angular-eslint/eslint-plugin-template": "19.0.2", + "@angular-eslint/schematics": "19.0.2", + "@angular-eslint/template-parser": "19.0.2", + "@typescript-eslint/types": "^8.0.0", + "@typescript-eslint/utils": "^8.0.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", @@ -11076,9 +12075,9 @@ } }, "node_modules/apexcharts": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.1.0.tgz", - "integrity": "sha512-TE0q0cXeS5k/AByLqlZAQ/aRQfdD3z0Ajd1uQWWZEjxiIC5qcBpMrTaG+aT+c3golqkvLH3u6kxDW8HBrggpLw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.2.0.tgz", + "integrity": "sha512-MQ5o8KnwMGcAlo+LhXlAjWGk8wBNBK2O1gFv+JiB6w3oJeuDJUFqa6FLTDlXvdhtObNQ3vIfAtv0AbMSkDv0DQ==", "license": "MIT", "dependencies": { "@svgdotjs/svg.draggable.js": "^3.0.4", @@ -11144,13 +12143,6 @@ "electron-builder-squirrel-windows": "25.1.8" } }, - "node_modules/app-builder-lib/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/app-builder-lib/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -11366,14 +12358,10 @@ "license": "MIT" }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/args": { "version": "5.0.3", @@ -11771,9 +12759,9 @@ "license": "MIT" }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dev": true, "license": "MIT", "dependencies": { @@ -11861,9 +12849,9 @@ } }, "node_modules/babel-loader": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", - "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", "dev": true, "license": "MIT", "dependencies": { @@ -11875,57 +12863,7 @@ }, "peerDependencies": { "@babel/core": "^7.12.0", - "webpack": ">=5" - } - }, - "node_modules/babel-loader/node_modules/find-cache-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", - "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "common-path-prefix": "^3.0.0", - "pkg-dir": "^7.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/babel-loader/node_modules/pkg-dir": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", - "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^6.3.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "webpack": ">=5" } }, "node_modules/babel-plugin-const-enum": { @@ -12042,6 +12980,16 @@ "node": ">=8" } }, + "node_modules/babel-plugin-macros/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.12", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", @@ -12212,6 +13160,23 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/beasties": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/beasties/-/beasties-0.1.0.tgz", + "integrity": "sha512-+Ssscd2gVG24qRNC+E2g88D+xsQW4xwakWtKAiGEQ3Pw54/FGdyo9RrfxhGhEv6ilFVbB7r3Lgx+QnAxnSpECw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "htmlparser2": "^9.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-media-query-parser": "^0.2.3" + } + }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -12313,6 +13278,19 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -12320,10 +13298,26 @@ "dev": true, "license": "MIT" }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bonjour-service": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", - "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", "dev": true, "license": "MIT", "dependencies": { @@ -12544,13 +13538,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/builder-util/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/builder-util/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -12777,16 +13764,15 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" }, "engines": { "node": ">= 0.4" @@ -12795,6 +13781,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -12829,9 +13828,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "version": "1.0.30001687", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001687.tgz", + "integrity": "sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==", "dev": true, "funding": [ { @@ -12907,41 +13906,19 @@ } }, "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", + "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, "funding": { "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" } }, "node_modules/chownr": { @@ -13351,13 +14328,6 @@ "node": ">=4.0.0" } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, - "license": "MIT" - }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -13819,13 +14789,6 @@ "typescript": ">=4" } }, - "node_modules/cosmiconfig/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/cosmiconfig/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -13954,69 +14917,6 @@ "dev": true, "license": "MIT" }, - "node_modules/critters": { - "version": "0.0.24", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.24.tgz", - "integrity": "sha512-Oyqew0FGM0wYUSNqR0L6AteO5MpMoUU0rhKRieXeiKs+PmRTxiJMyaunYB2KF6fQ3dzChXKCpbFOEJx3OQ1v/Q==", - "deprecated": "Ownership of Critters has moved to the Nuxt team, who will be maintaining the project going forward. If you'd like to keep using Critters, please switch to the actively-maintained fork at https://github.com/danielroe/beasties", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "chalk": "^4.1.0", - "css-select": "^5.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.2", - "htmlparser2": "^8.0.2", - "postcss": "^8.4.23", - "postcss-media-query-parser": "^0.2.3" - } - }, - "node_modules/critters/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/critters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/critters/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/cron-parser": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", @@ -14031,9 +14931,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -14338,9 +15238,9 @@ "license": "MIT" }, "node_modules/cypress": { - "version": "13.15.2", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.15.2.tgz", - "integrity": "sha512-ARbnUorjcCM3XiPwgHKuqsyr5W9Qn+pIIBPaoilnoBkLdSC2oLQjV1BUpnmc7KR+b7Avah3Ly2RMFnfxr96E/A==", + "version": "13.16.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.1.tgz", + "integrity": "sha512-17FtCaz0cx7ssWYKXzGB0Vub8xHwpVPr+iPt2fHhLMDhVAPVrplD+rTQsZUsfb19LVBn5iwkEUFjQ1yVVJXsLA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -14687,9 +15587,9 @@ "license": "MIT" }, "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -14803,73 +15703,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/default-gateway/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-gateway/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-gateway/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/default-gateway/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -15174,13 +16007,6 @@ "dmg-license": "^1.0.11" } }, - "node_modules/dmg-builder/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/dmg-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -15196,19 +16022,6 @@ "node": ">=12" } }, - "node_modules/dmg-builder/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/dmg-builder/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -15394,9 +16207,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "dev": true, "license": "BSD-2-Clause", "engines": { @@ -15407,28 +16220,35 @@ } }, "node_modules/dotenv-expand": { - "version": "11.0.6", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", - "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "dotenv": "^16.4.4" + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", + "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" + "node": ">= 0.4" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true, - "license": "MIT" - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -15478,9 +16298,9 @@ } }, "node_modules/electron": { - "version": "31.7.4", - "resolved": "https://registry.npmjs.org/electron/-/electron-31.7.4.tgz", - "integrity": "sha512-uvSxcYq349bbCp60vmsTJGviI0pBfrvZK+YQHs3L0nzhZeBin0+o7bC1j3vmK+CeTxAZlWWjtgtc3z7XYrHm5w==", + "version": "33.3.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-33.3.0.tgz", + "integrity": "sha512-316ZlFUHJmzGrhRj87tVStxyYvknDqVR9eYSsGKAHY7auhVWFLIcPPGxcnbD/H1mez8CpDjXvEjcz76zpWxsXw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -15722,9 +16542,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.57", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.57.tgz", - "integrity": "sha512-xS65H/tqgOwUBa5UmOuNSLuslDo7zho0y/lgQw35pnrqiZh7UOWHCeL/Bt6noJATbA6tpQJGCifsFsIRZj1Fqg==", + "version": "1.5.72", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.72.tgz", + "integrity": "sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==", "dev": true, "license": "ISC" }, @@ -15744,12 +16564,6 @@ "tiny-typed-emitter": "^2.1.0" } }, - "node_modules/electron-updater/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, "node_modules/electron-updater/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -15777,9 +16591,9 @@ } }, "node_modules/electron/node_modules/@types/node": { - "version": "20.17.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.6.tgz", - "integrity": "sha512-VEI7OdvK2wP7XHnsuXbAJnEpEkF6NjSN45QJlL4VGqZSXsnicpesdTWsg9RISeSdYd3yeRj/y3k5KGjUXYnFwQ==", + "version": "20.17.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.9.tgz", + "integrity": "sha512-0JOXkRyLanfGPE2QRCwgxhzlBAvaRdCNMcvbd7jFfpmD4eEXll7LRwy5ymJmyeZqk7Nh7eD2LeUyQ68BbndmXw==", "dev": true, "license": "MIT", "dependencies": { @@ -15832,25 +16646,10 @@ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "iconv-lite": "^0.6.2" } }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -15956,9 +16755,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.4.tgz", - "integrity": "sha512-HR1gxH5OaiN7XH7uiWH0RLw0RcFySiSoW1ctxmD1ahTw3uGBtkmm/ng0tDU1OtYx5OK6EOL5Y6O21cDflG3Jcg==", + "version": "1.23.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", + "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", "dev": true, "license": "MIT", "dependencies": { @@ -16017,13 +16816,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -16083,15 +16879,15 @@ } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -16116,9 +16912,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -16129,36 +16925,36 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" } }, "node_modules/esbuild-wasm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.23.0.tgz", - "integrity": "sha512-6jP8UmWy6R6TUUV8bMuC3ZyZ6lZKI56x0tkxyCIqWwRRJ/DgeQKneh/Oid5EoGoPFLrGNkz47ZEtWAYuiY/u9g==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.24.0.tgz", + "integrity": "sha512-xhNn5tL1AhkPg4ft59yXT6FkwKXiPSYyz1IeinJHUJpjvOHOIPvdmFQc0pGdjxlKSbzZc2mNmtVOWAR1EF/JAg==", "dev": true, "license": "MIT", "bin": { @@ -16232,27 +17028,27 @@ } }, "node_modules/eslint": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", - "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", + "version": "9.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.16.0.tgz", + "integrity": "sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.18.0", - "@eslint/core": "^0.7.0", - "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.14.0", - "@eslint/plugin-kit": "^0.2.0", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.16.0", + "@eslint/plugin-kit": "^0.2.3", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.0", + "@humanwhocodes/retry": "^0.4.1", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.5", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.2.0", @@ -16271,8 +17067,7 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" @@ -16929,9 +17724,9 @@ "license": "Apache-2.0" }, "node_modules/express": { - "version": "4.21.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", - "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dev": true, "license": "MIT", "dependencies": { @@ -16954,7 +17749,7 @@ "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.10", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", "qs": "6.13.0", "range-parser": "~1.2.1", @@ -16969,6 +17764,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/debug": { @@ -16988,6 +17787,22 @@ "dev": true, "license": "MIT" }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -17010,6 +17825,19 @@ "node": ">=4" } }, + "node_modules/external-editor/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/external-editor/node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -17155,6 +17983,21 @@ "pend": "~1.2.0" } }, + "node_modules/fdir": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", + "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -17294,21 +18137,20 @@ "license": "MIT" }, "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", "dev": true, "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/find-file-up": { @@ -17389,9 +18231,9 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", "dev": true, "license": "ISC" }, @@ -17559,6 +18401,31 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", @@ -17591,6 +18458,19 @@ "node": ">=12" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -17621,6 +18501,32 @@ "node": ">=8" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -17653,6 +18559,16 @@ "node": ">=8" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/form-data": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", @@ -17875,16 +18791,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.5.tgz", + "integrity": "sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "dunder-proto": "^1.0.0", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -18245,12 +19164,12 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -18390,10 +19309,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -18402,9 +19325,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -18496,16 +19419,16 @@ } }, "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.2.tgz", + "integrity": "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==", "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/hosted-git-info/node_modules/lru-cache": { @@ -18606,9 +19529,9 @@ "license": "MIT" }, "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", @@ -18621,8 +19544,8 @@ "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "domutils": "^3.1.0", + "entities": "^4.5.0" } }, "node_modules/http-assert": { @@ -18913,9 +19836,9 @@ } }, "node_modules/husky": { - "version": "9.1.6", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz", - "integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==", + "version": "9.1.7", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", + "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { @@ -19048,13 +19971,13 @@ } }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" @@ -19118,16 +20041,16 @@ } }, "node_modules/ignore-walk": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", - "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-7.0.0.tgz", + "integrity": "sha512-T4gbf83A4NH95zvhVYZc+qWocBBGlpzUXLPGurJggw/WIOwicfXJChLDP/iBZnN5WqROSu5Bm3hhle4z8a8YGQ==", "dev": true, "license": "ISC", "dependencies": { "minimatch": "^9.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/image-q": { @@ -19153,30 +20076,103 @@ "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", "dev": true, "license": "MIT", - "optional": true, - "bin": { - "image-size": "bin/image-size.js" + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immutable": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "node_modules/import-local/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/import-local/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "p-try": "^2.0.0" }, "engines": { "node": ">=6" @@ -19185,34 +20181,40 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/import-fresh/node_modules/resolve-from": { + "node_modules/import-local/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-local/node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" + "find-up": "^4.0.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/import-meta-resolve": { @@ -19271,13 +20273,13 @@ "license": "ISC" }, "node_modules/ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-5.0.0.tgz", + "integrity": "sha512-+N0ngpO3e7cRUWOJAS7qw0IZIVc6XPrW4MlFBdD066F2L4k1L6ker3hLqSq7iXxU5tgS4WGkIUElWn5vogAEnw==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/internal-slot": { @@ -19328,13 +20330,6 @@ "node": ">= 12" } }, - "node_modules/ip-address/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -19369,14 +20364,33 @@ "dev": true, "license": "MIT" }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -19396,14 +20410,14 @@ } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.0.tgz", + "integrity": "sha512-kR5g0+dXf/+kXnqI+lu0URKYPKgICtHGGNCDSB10AaUFj3o/HkB3u7WfpRBJGFopxxY0oH3ux7ZsDjLtK7xqvw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bind": "^1.0.7", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -19528,6 +20542,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", + "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", @@ -19640,6 +20670,19 @@ "dev": true, "license": "MIT" }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -19676,13 +20719,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.0.tgz", + "integrity": "sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bind": "^1.0.7", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -19752,14 +20796,16 @@ "license": "MIT" }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.0.tgz", + "integrity": "sha512-B6ohK4ZmoftlUe+uvenXSbPJFo6U37BH7oO1B3nQH8f/7h27N56s85MhUtbFJAziz5dcmuR3i8ovUl35zp8pFA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bind": "^1.0.7", + "gopd": "^1.1.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -19768,6 +20814,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", @@ -19798,13 +20857,14 @@ } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.0.tgz", + "integrity": "sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bind": "^1.0.7", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -19814,13 +20874,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.0.tgz", + "integrity": "sha512-qS8KkNNXUZ/I+nX6QT8ZS1/Yx0A444yhzdTKxCzKkNjQ9sHErBxJnJAgh+f5YhusYECEcjo4XcyH87hn6+ks0A==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bind": "^1.0.7", + "has-symbols": "^1.0.3", + "safe-regex-test": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -19885,6 +20947,19 @@ "dev": true, "license": "MIT" }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -19898,6 +20973,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-what": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", @@ -19967,10 +21059,11 @@ } }, "node_modules/isomorphic-rslog": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/isomorphic-rslog/-/isomorphic-rslog-0.0.5.tgz", - "integrity": "sha512-pkU3vvajRJ0LKLaMFy8Cj7ElbFUdkQKVhUk+DQsVCYsLW4uulU65C2s3l+Sm5OtiOwprzkYYcAIJa/COwCYHWA==", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/isomorphic-rslog/-/isomorphic-rslog-0.0.6.tgz", + "integrity": "sha512-HM0q6XqQ93psDlqvuViNs/Ea3hAyGDkIdVAHlrEocjjAwGrs1fZ+EdQjS9eUPacnYB7Y8SoDdSY3H8p3ce205A==", "dev": true, + "license": "MIT", "engines": { "node": ">=14.17.6" } @@ -20034,22 +21127,6 @@ "node": ">=10" } }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "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", @@ -20445,6 +21522,18 @@ "node": ">=8" } }, + "node_modules/jest-circus/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "optional": true, + "peer": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/jest-cli": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", @@ -21030,9 +22119,9 @@ } }, "node_modules/jest-preset-angular": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.1.1.tgz", - "integrity": "sha512-mWW2WlndHetTp4PQov05v7JE6HZQB5uTzGd+oW2RPH1OOTCLUKI8mSIU4DXCBJ4LDg5gIMMfqHsxT/Qmpu2dQQ==", + "version": "14.4.2", + "resolved": "https://registry.npmjs.org/jest-preset-angular/-/jest-preset-angular-14.4.2.tgz", + "integrity": "sha512-BYYv0FaTDfBNh8WyA9mpOV3krfw20kurBGK8INZUnv7KZDAWZuQtCET4TwTWxSNQ9jS1OX1+a5weCm/bTDDM1A==", "dev": true, "license": "MIT", "dependencies": { @@ -21050,10 +22139,9 @@ "esbuild": ">=0.15.13" }, "peerDependencies": { - "@angular-devkit/build-angular": ">=15.0.0 <19.0.0", - "@angular/compiler-cli": ">=15.0.0 <19.0.0", - "@angular/core": ">=15.0.0 <19.0.0", - "@angular/platform-browser-dynamic": ">=15.0.0 <19.0.0", + "@angular/compiler-cli": ">=15.0.0 <20.0.0", + "@angular/core": ">=15.0.0 <20.0.0", + "@angular/platform-browser-dynamic": ">=15.0.0 <20.0.0", "jest": "^29.0.0", "typescript": ">=4.8" } @@ -21137,9 +22225,9 @@ } }, "node_modules/jest-resolve/node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "license": "MIT", "engines": { @@ -21738,6 +22826,23 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/js-yaml/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", @@ -21858,16 +22963,16 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-buffer": { @@ -21878,13 +22983,13 @@ "license": "MIT" }, "node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", "dev": true, "license": "MIT", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/json-schema": { @@ -22488,9 +23593,9 @@ } }, "node_modules/lilconfig": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", - "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", "dev": true, "license": "MIT", "engines": { @@ -22511,9 +23616,9 @@ } }, "node_modules/listr2": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.4.tgz", - "integrity": "sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==", + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", + "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", "dev": true, "license": "MIT", "dependencies": { @@ -22621,29 +23726,30 @@ } }, "node_modules/lmdb": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.0.13.tgz", - "integrity": "sha512-UGe+BbaSUQtAMZobTb4nHvFMrmvuAQKSeaqAX2meTEQjfsbpl5sxdHD8T72OnwD4GU9uwNhYXIVe4QGs8N9Zyw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/lmdb/-/lmdb-3.1.5.tgz", + "integrity": "sha512-46Mch5Drq+A93Ss3gtbg+Xuvf5BOgIuvhKDWoGa3HcPHI6BL2NCOkRdSx1D4VfzwrxhnsjbyIVsLRlQHu6URvw==", "dev": true, "hasInstallScript": true, "license": "MIT", + "optional": true, "dependencies": { - "msgpackr": "^1.10.2", + "msgpackr": "^1.11.2", "node-addon-api": "^6.1.0", "node-gyp-build-optional-packages": "5.2.2", - "ordered-binary": "^1.4.1", + "ordered-binary": "^1.5.3", "weak-lru-cache": "^1.2.2" }, "bin": { "download-lmdb-prebuilds": "bin/download-prebuilds.js" }, "optionalDependencies": { - "@lmdb/lmdb-darwin-arm64": "3.0.13", - "@lmdb/lmdb-darwin-x64": "3.0.13", - "@lmdb/lmdb-linux-arm": "3.0.13", - "@lmdb/lmdb-linux-arm64": "3.0.13", - "@lmdb/lmdb-linux-x64": "3.0.13", - "@lmdb/lmdb-win32-x64": "3.0.13" + "@lmdb/lmdb-darwin-arm64": "3.1.5", + "@lmdb/lmdb-darwin-x64": "3.1.5", + "@lmdb/lmdb-linux-arm": "3.1.5", + "@lmdb/lmdb-linux-arm64": "3.1.5", + "@lmdb/lmdb-linux-x64": "3.1.5", + "@lmdb/lmdb-win32-x64": "3.1.5" } }, "node_modules/load-bmfont": { @@ -23232,9 +24338,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.11", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", - "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, "license": "MIT", "dependencies": { @@ -23242,29 +24348,19 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-error": { @@ -23547,9 +24643,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", - "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", + "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", "dev": true, "license": "MIT", "dependencies": { @@ -23755,6 +24851,7 @@ "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==", "dev": true, "license": "MIT", + "optional": true, "optionalDependencies": { "msgpackr-extract": "^3.0.2" } @@ -23797,19 +24894,19 @@ } }, "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", "dev": true, "funding": [ { @@ -23850,20 +24947,6 @@ "node": ">= 4.4.x" } }, - "node_modules/needle/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -23882,44 +24965,20 @@ "license": "MIT" }, "node_modules/ng-apexcharts": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/ng-apexcharts/-/ng-apexcharts-1.13.0.tgz", - "integrity": "sha512-YftYLsYTabbGYZZTceXRnliLaQ1/uAp4yx/kanRP5VJtNl4hObRv9hV5WLTXoQnYY0fzfseotgf7Uz0bUMLvAw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/ng-apexcharts/-/ng-apexcharts-1.15.0.tgz", + "integrity": "sha512-CNJMStzS+NxLvxRLrybPCy67n1z53WqsGvD9qdepWMo3xgZRDzpX8NiNOvwWDsZGSi7Y/nS5qaUmiM84gi3x7Q==", "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { - "@angular/common": "^18.0.4", - "@angular/core": "^18.0.4", - "apexcharts": "^4.0.0", + "@angular/common": "^19.0.0", + "@angular/core": "^19.0.0", + "apexcharts": ">=4.0.0", "rxjs": "^6.5.5 || ^7.4.0" } }, - "node_modules/nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "!win32" - ], - "dependencies": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "node_modules/nice-napi/node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "license": "MIT", - "optional": true - }, "node_modules/node-abi": { "version": "3.71.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", @@ -23945,7 +25004,8 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/node-api-version": { "version": "0.2.0", @@ -23957,6 +25017,52 @@ "semver": "^7.3.5" } }, + "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==", + "dev": true, + "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-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch/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==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -23994,12 +25100,10 @@ } }, "node_modules/node-gyp-build": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.3.tgz", - "integrity": "sha512-EMS95CMJzdoSKoIiXo8pxKoL8DYxwIZXYlLmgPb8KUv794abpnLK6ynsCAWNliOjREKruYKdzbh76HHYUHX7nw==", - "dev": true, + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", "license": "MIT", - "optional": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -24012,6 +25116,7 @@ "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==", "dev": true, "license": "MIT", + "optional": true, "dependencies": { "detect-libc": "^2.0.1" }, @@ -24036,9 +25141,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, "license": "MIT" }, @@ -24074,18 +25179,18 @@ } }, "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-7.0.0.tgz", + "integrity": "sha512-k6U0gKRIuNCTkwHGZqblCfLfBRh+w1vI6tBo+IeJwq2M8FUiOqhX7GH+GArQGScA7azd1WfyRCvxoXDO3hQDIA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "hosted-git-info": "^7.0.0", + "hosted-git-info": "^8.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/normalize-path": { @@ -24122,127 +25227,127 @@ } }, "node_modules/npm-bundled": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", - "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", + "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", "dev": true, "license": "ISC", "dependencies": { - "npm-normalize-package-bin": "^3.0.0" + "npm-normalize-package-bin": "^4.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-7.1.1.tgz", + "integrity": "sha512-u6DCwbow5ynAX5BdiHQ9qvexme4U3qHW3MWe5NqH+NeBm0LbiH6zvGjNNew1fY+AZZUtVHbOPF3j7mJxbUzpXg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "semver": "^7.1.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-package-arg": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.3.tgz", - "integrity": "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-12.0.0.tgz", + "integrity": "sha512-ZTE0hbwSdTNL+Stx2zxSqdu2KZfNDcrtrLdIk7XGnQFYBWYDho/ORvXtn5XEePcL3tFpGjHCV3X3xrtDh7eZ+A==", "dev": true, "license": "ISC", "dependencies": { - "hosted-git-info": "^7.0.0", - "proc-log": "^4.0.0", + "hosted-git-info": "^8.0.0", + "proc-log": "^5.0.0", "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" + "validate-npm-package-name": "^6.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-packlist": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", - "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-9.0.0.tgz", + "integrity": "sha512-8qSayfmHJQTx3nJWYbbUmflpyarbLMBc6LCAjYsiGtXxDB68HaZpb8re6zeaLGxZzDuMdhsg70jryJe+RrItVQ==", "dev": true, "license": "ISC", "dependencies": { - "ignore-walk": "^6.0.4" + "ignore-walk": "^7.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-pick-manifest": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.1.0.tgz", - "integrity": "sha512-nkc+3pIIhqHVQr085X9d2JzPzLyjzQS96zbruppqC9aZRm/x8xx6xhI98gHtsfELP2bE+loHq8ZaHFHhe+NauA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-10.0.0.tgz", + "integrity": "sha512-r4fFa4FqYY8xaM7fHecQ9Z2nE9hgNfJR+EmoKv0+chvzWkBcORX3r0FpTByP+CbOVJDladMXnPQGVN8PBLGuTQ==", "dev": true, "license": "ISC", "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^11.0.0", + "npm-install-checks": "^7.1.0", + "npm-normalize-package-bin": "^4.0.0", + "npm-package-arg": "^12.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-registry-fetch": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-17.1.0.tgz", - "integrity": "sha512-5+bKQRH0J1xG1uZ1zMNvxW0VEyoNWgJpY9UDuluPFLKDfJ9u2JmmjmTJV1srBGQOROfdBMiVvnH2Zvpbm+xkVA==", + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-18.0.2.tgz", + "integrity": "sha512-LeVMZBBVy+oQb5R6FDV9OlJCcWDU+al10oKpe+nsvcHnG24Z3uM3SvJYKfGJlfGjVU8v9liejCrUR/M5HO5NEQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/redact": "^2.0.0", + "@npmcli/redact": "^3.0.0", "jsonparse": "^1.3.1", - "make-fetch-happen": "^13.0.0", + "make-fetch-happen": "^14.0.0", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", - "minizlib": "^2.1.2", - "npm-package-arg": "^11.0.0", - "proc-log": "^4.0.0" + "minipass-fetch": "^4.0.0", + "minizlib": "^3.0.1", + "npm-package-arg": "^12.0.0", + "proc-log": "^5.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-registry-fetch/node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-registry-fetch/node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", - "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -24250,13 +25355,23 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/npm-registry-fetch/node_modules/fs-minipass": { @@ -24301,27 +25416,26 @@ "license": "ISC" }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-registry-fetch/node_modules/minimatch": { @@ -24364,60 +25478,157 @@ } }, "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", + "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minizlib": "^3.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, + "node_modules/npm-registry-fetch/node_modules/minizlib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/npm-registry-fetch/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm-registry-fetch/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm-registry-fetch/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-registry-fetch/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/npm-registry-fetch/node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" } }, "node_modules/npm-registry-fetch/node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/npm-registry-fetch/node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/npm-run-path": { @@ -24474,24 +25685,23 @@ } }, "node_modules/nwsapi": { - "version": "2.2.13", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.13.tgz", - "integrity": "sha512-cTGB9ptp9dY9A5VbMSe7fQBcl/tt22Vcqdq8+eN93rblOuE0aCFu4aZ2vMwct/2t+lFnosm8RkQW1I0Omb1UtQ==", + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", "dev": true, "license": "MIT" }, "node_modules/nx": { - "version": "19.8.10", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.10.tgz", - "integrity": "sha512-/QCJZ5jDDzYIKjFNseb3Ehi/PxO3KZdOnH37603doO6B7N/x1yyB7pVTtf4MKVogOcoltmUZbsq975Ery3QFEA==", + "version": "20.2.2", + "resolved": "https://registry.npmjs.org/nx/-/nx-20.2.2.tgz", + "integrity": "sha512-wHgC/NQ82Q3LOeUZXPI2j/JhpZwb7JjRc0uDn3kQU+lN/ulySCJHTHCf4CIglW4NjZeN1WZZ7YMeddtFWETGGA==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.8.10", "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", + "@yarnpkg/parsers": "3.0.2", "@zkochan/js-yaml": "0.0.7", "axios": "^1.7.4", "chalk": "^4.1.0", @@ -24515,11 +25725,11 @@ "ora": "5.3.0", "semver": "^7.5.3", "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", "tar-stream": "~2.2.0", "tmp": "~0.2.1", "tsconfig-paths": "^4.1.2", "tslib": "^2.3.0", + "yaml": "^2.6.0", "yargs": "^17.6.2", "yargs-parser": "21.1.1" }, @@ -24528,16 +25738,16 @@ "nx-cloud": "bin/nx-cloud.js" }, "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.8.10", - "@nx/nx-darwin-x64": "19.8.10", - "@nx/nx-freebsd-x64": "19.8.10", - "@nx/nx-linux-arm-gnueabihf": "19.8.10", - "@nx/nx-linux-arm64-gnu": "19.8.10", - "@nx/nx-linux-arm64-musl": "19.8.10", - "@nx/nx-linux-x64-gnu": "19.8.10", - "@nx/nx-linux-x64-musl": "19.8.10", - "@nx/nx-win32-arm64-msvc": "19.8.10", - "@nx/nx-win32-x64-msvc": "19.8.10" + "@nx/nx-darwin-arm64": "20.2.2", + "@nx/nx-darwin-x64": "20.2.2", + "@nx/nx-freebsd-x64": "20.2.2", + "@nx/nx-linux-arm-gnueabihf": "20.2.2", + "@nx/nx-linux-arm64-gnu": "20.2.2", + "@nx/nx-linux-arm64-musl": "20.2.2", + "@nx/nx-linux-x64-gnu": "20.2.2", + "@nx/nx-linux-x64-musl": "20.2.2", + "@nx/nx-win32-arm64-msvc": "20.2.2", + "@nx/nx-win32-x64-msvc": "20.2.2" }, "peerDependencies": { "@swc-node/register": "^1.8.0", @@ -24553,14 +25763,14 @@ } }, "node_modules/nx-electron": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/nx-electron/-/nx-electron-19.0.0.tgz", - "integrity": "sha512-nKuCa93japApS0fWM9LPl0jvXbKkM/iMMxVwyw+nsRBm5zQr+yMEXASs2tyoYBT1HmZn8jLmcjr/V3qpeETCUg==", + "version": "20.0.0-alpha.0", + "resolved": "https://registry.npmjs.org/nx-electron/-/nx-electron-20.0.0-alpha.0.tgz", + "integrity": "sha512-T5+sVG+5NWZNvDbNcq9U5WHKm97/fttSUL8HrKEk+asWVUfMilcg51laTRDIc1eSlF92iGr8GH7iCQLc1LnR1g==", "dev": true, "license": "Apache-2.0", "dependencies": { "copy-webpack-plugin": "^12.0.2", - "electron-builder": "^25.1.7", + "electron-builder": "^25.1.8", "fork-ts-checker-webpack-plugin": "^9.0.2", "license-webpack-plugin": "^4.0.2", "rxjs-for-await": "^1.0.0", @@ -24568,12 +25778,12 @@ "terser-webpack-plugin": "^5.3.10", "tree-kill": "^1.2.2", "ts-loader": "^9.5.1", - "tsconfig-paths-webpack-plugin": "^4.1.0", - "webpack": "^5.94.0", + "tsconfig-paths-webpack-plugin": "^4.2.0", + "webpack": "^5.97.1", "webpack-merge": "^5.10.0" }, "peerDependencies": { - "@nx/workspace": "^19", + "@nx/workspace": "^20", "electron": "*" } }, @@ -24620,13 +25830,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/nx-electron/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/nx-electron/node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -24655,6 +25858,31 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/nx-electron/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/nx-electron/node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -24682,6 +25910,30 @@ } } }, + "node_modules/nx-electron/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/nx-electron/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/nx-electron/node_modules/fork-ts-checker-webpack-plugin": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", @@ -24723,7 +25975,20 @@ "universalify": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=12" + } + }, + "node_modules/nx-electron/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/nx-electron/node_modules/js-yaml": { @@ -24739,6 +26004,13 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/nx-electron/node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, "node_modules/nx-electron/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -24769,6 +26041,32 @@ "node": ">=8" } }, + "node_modules/nx-electron/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/nx-electron/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/nx-electron/node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", @@ -24802,20 +26100,68 @@ } }, "node_modules/nx-electron/node_modules/tsconfig-paths-webpack-plugin": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz", - "integrity": "sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", "tsconfig-paths": "^4.1.2" }, "engines": { "node": ">=10.13.0" } }, + "node_modules/nx-electron/node_modules/webpack": { + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, "node_modules/nx-electron/node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -25257,7 +26603,8 @@ "resolved": "https://registry.npmjs.org/ordered-binary/-/ordered-binary-1.5.3.tgz", "integrity": "sha512-oGFr3T+pYdTGJ+YFEILMpS3es+GiIbs9h/XQrclBXUtd44ey7XwfsMzM31f64I1SQOawDoDr/D823kNCADI8TA==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/os-locale": { "version": "1.4.0", @@ -25376,9 +26723,9 @@ } }, "node_modules/p-retry": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.0.tgz", - "integrity": "sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", "dev": true, "license": "MIT", "dependencies": { @@ -25421,58 +26768,58 @@ "license": "BlueOak-1.0.0" }, "node_modules/pacote": { - "version": "18.0.6", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz", - "integrity": "sha512-+eK3G27SMwsB8kLIuj4h1FUhHtwiEUo21Tw8wNjmvdlpOEr613edv+8FUsTj/4F/VN5ywGE19X18N7CC2EJk6A==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-20.0.0.tgz", + "integrity": "sha512-pRjC5UFwZCgx9kUFDVM9YEahv4guZ1nSLqwmWiLUnDbGsjs+U5w7z6Uc8HNR1a6x8qnu5y9xtGE6D1uAuYz+0A==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/git": "^5.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/package-json": "^5.1.0", - "@npmcli/promise-spawn": "^7.0.0", - "@npmcli/run-script": "^8.0.0", - "cacache": "^18.0.0", + "@npmcli/git": "^6.0.0", + "@npmcli/installed-package-contents": "^3.0.0", + "@npmcli/package-json": "^6.0.0", + "@npmcli/promise-spawn": "^8.0.0", + "@npmcli/run-script": "^9.0.0", + "cacache": "^19.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", - "npm-package-arg": "^11.0.0", - "npm-packlist": "^8.0.0", - "npm-pick-manifest": "^9.0.0", - "npm-registry-fetch": "^17.0.0", - "proc-log": "^4.0.0", + "npm-package-arg": "^12.0.0", + "npm-packlist": "^9.0.0", + "npm-pick-manifest": "^10.0.0", + "npm-registry-fetch": "^18.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "sigstore": "^2.2.0", - "ssri": "^10.0.0", + "sigstore": "^3.0.0", + "ssri": "^12.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "bin/index.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/pacote/node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/pacote/node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", - "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -25480,13 +26827,41 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/cacache/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/pacote/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/pacote/node_modules/fs-minipass": { @@ -25569,43 +26944,112 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/pacote/node_modules/minizlib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/pacote/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/pacote/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pacote/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/pacote/node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/pacote/node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/pacote/node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/pacote/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/pako": { @@ -25949,18 +27393,6 @@ "node": ">=0.6.0" } }, - "node_modules/patch-package/node_modules/yaml": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", - "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -26031,9 +27463,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", - "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "dev": true, "license": "MIT" }, @@ -26288,13 +27720,13 @@ } }, "node_modules/piscina": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.6.1.tgz", - "integrity": "sha512-z30AwWGtQE+Apr+2WBZensP2lIvwoaMcOPkQlIEmSGMJNUvaYACylPYrQM6wSdUNJlnDVMSpLv7xTMJqlVshOA==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.7.0.tgz", + "integrity": "sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw==", "dev": true, "license": "MIT", "optionalDependencies": { - "nice-napi": "^1.0.2" + "@napi-rs/nice": "^1.0.1" } }, "node_modules/pixelmatch": { @@ -26321,84 +27753,38 @@ } }, "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "find-up": "^6.3.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" + "node": ">=14.16" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" }, "engines": { - "node": ">=6" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -26490,9 +27876,9 @@ } }, "node_modules/postcss": { - "version": "8.4.41", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", - "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "dev": true, "funding": [ { @@ -26511,8 +27897,8 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.1", - "source-map-js": "^1.2.0" + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -27176,13 +28562,13 @@ } }, "node_modules/proc-log": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-4.2.0.tgz", - "integrity": "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz", + "integrity": "sha512-Azwzvl90HaF0aCz1JrDdXQykFakSSNPaPoiZ9fm5qJIMHioDZEi7OAdRwSm6rSoPtY3Qutnm3L7ogmg3dc+wbQ==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/process": { @@ -27277,13 +28663,16 @@ "optional": true }, "node_modules/psl": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.10.0.tgz", - "integrity": "sha512-KSKHEbjAnpUuAUserOq0FxGXCUrzC3WniuSJhvdbs102rL55266ZcHBqLWOsG30spQMlPdpy7icATiAQehg/iA==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" } }, "node_modules/pump": { @@ -27325,9 +28714,9 @@ "license": "MIT" }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", + "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -27424,6 +28813,19 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -27642,29 +29044,17 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readdirp/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">= 14.16.0" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/reflect-metadata": { @@ -27674,6 +29064,29 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.8.tgz", + "integrity": "sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "dunder-proto": "^1.0.0", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.2.0", + "which-builtin-type": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -27738,16 +29151,16 @@ } }, "node_modules/regexpu-core": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz", - "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", - "regjsparser": "^0.11.0", + "regjsparser": "^0.12.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" }, @@ -27763,9 +29176,9 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz", - "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -27775,19 +29188,6 @@ "regjsparser": "bin/parser" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -28177,22 +29577,14 @@ "node": ">=8.0" } }, - "node_modules/roarr/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true - }, "node_modules/rollup": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.22.4.tgz", - "integrity": "sha512-vD8HJ5raRcWOyymsR6Z3o6+RzfEPCnVLMFJ6vRslO1jt4LO6dUo5Qnpg7y4RkZFM2DMe3WUirkI5c16onjrc6A==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.26.0.tgz", + "integrity": "sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.5" + "@types/estree": "1.0.6" }, "bin": { "rollup": "dist/bin/rollup" @@ -28202,32 +29594,27 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.22.4", - "@rollup/rollup-android-arm64": "4.22.4", - "@rollup/rollup-darwin-arm64": "4.22.4", - "@rollup/rollup-darwin-x64": "4.22.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.22.4", - "@rollup/rollup-linux-arm-musleabihf": "4.22.4", - "@rollup/rollup-linux-arm64-gnu": "4.22.4", - "@rollup/rollup-linux-arm64-musl": "4.22.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.22.4", - "@rollup/rollup-linux-riscv64-gnu": "4.22.4", - "@rollup/rollup-linux-s390x-gnu": "4.22.4", - "@rollup/rollup-linux-x64-gnu": "4.22.4", - "@rollup/rollup-linux-x64-musl": "4.22.4", - "@rollup/rollup-win32-arm64-msvc": "4.22.4", - "@rollup/rollup-win32-ia32-msvc": "4.22.4", - "@rollup/rollup-win32-x64-msvc": "4.22.4", + "@rollup/rollup-android-arm-eabi": "4.26.0", + "@rollup/rollup-android-arm64": "4.26.0", + "@rollup/rollup-darwin-arm64": "4.26.0", + "@rollup/rollup-darwin-x64": "4.26.0", + "@rollup/rollup-freebsd-arm64": "4.26.0", + "@rollup/rollup-freebsd-x64": "4.26.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.26.0", + "@rollup/rollup-linux-arm-musleabihf": "4.26.0", + "@rollup/rollup-linux-arm64-gnu": "4.26.0", + "@rollup/rollup-linux-arm64-musl": "4.26.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.26.0", + "@rollup/rollup-linux-riscv64-gnu": "4.26.0", + "@rollup/rollup-linux-s390x-gnu": "4.26.0", + "@rollup/rollup-linux-x64-gnu": "4.26.0", + "@rollup/rollup-linux-x64-musl": "4.26.0", + "@rollup/rollup-win32-arm64-msvc": "4.26.0", + "@rollup/rollup-win32-ia32-msvc": "4.26.0", + "@rollup/rollup-win32-x64-msvc": "4.26.0", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true, - "license": "MIT" - }, "node_modules/run-applescript": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", @@ -28360,14 +29747,14 @@ } }, "node_modules/sass": { - "version": "1.77.6", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.6.tgz", - "integrity": "sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==", + "version": "1.80.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", + "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", "dev": true, "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", + "chokidar": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -28375,12 +29762,15 @@ }, "engines": { "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" } }, "node_modules/sass-loader": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.0.tgz", - "integrity": "sha512-n13Z+3rU9A177dk4888czcVFiC8CL9dii4qpXWUg3YIIgZEvi9TCFKjOQcbK0kJM7DJu9VucrZFddvNfYCPwtw==", + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz", + "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==", "dev": true, "license": "MIT", "dependencies": { @@ -28862,11 +30252,14 @@ } }, "node_modules/shell-quote": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", - "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -28904,21 +30297,21 @@ } }, "node_modules/sigstore": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.3.1.tgz", - "integrity": "sha512-8G+/XDU8wNsJOQS5ysDVO0Etg9/2uA5gR9l4ZwijjlwxBcrU6RPfwi2+jJmbP+Ap1Hlp/nVAaEO4Fj22/SL2gQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-3.0.0.tgz", + "integrity": "sha512-PHMifhh3EN4loMcHCz6l3v/luzgT3za+9f8subGgeMNjbJjzH4Ij/YoX3Gvu+kaouJRIlVdTHHCREADYf+ZteA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@sigstore/bundle": "^2.3.2", - "@sigstore/core": "^1.0.0", + "@sigstore/bundle": "^3.0.0", + "@sigstore/core": "^2.0.0", "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^2.3.2", - "@sigstore/tuf": "^2.3.4", - "@sigstore/verify": "^1.2.1" + "@sigstore/sign": "^3.0.0", + "@sigstore/tuf": "^3.0.0", + "@sigstore/verify": "^2.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/simple-update-notifier": { @@ -29095,19 +30488,6 @@ "webpack": "^5.72.1" } }, - "node_modules/source-map-loader/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -29208,9 +30588,9 @@ } }, "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true, "license": "BSD-3-Clause" }, @@ -29540,24 +30920,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/strtok3": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", @@ -29611,23 +30973,23 @@ } }, "node_modules/stylus": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.59.0.tgz", - "integrity": "sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==", + "version": "0.64.0", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.64.0.tgz", + "integrity": "sha512-ZIdT8eUv8tegmqy1tTIdJv9We2DumkNZFdCF5mz/Kpq3OcTaxSuCAYZge6HKK2CmNC02G1eJig2RV7XTw5hQrA==", "dev": true, "license": "MIT", "dependencies": { - "@adobe/css-tools": "^4.0.1", + "@adobe/css-tools": "~4.3.3", "debug": "^4.3.2", - "glob": "^7.1.6", - "sax": "~1.2.4", + "glob": "^10.4.5", + "sax": "~1.4.1", "source-map": "^0.7.3" }, "bin": { "stylus": "bin/stylus" }, "engines": { - "node": "*" + "node": ">=16" }, "funding": { "url": "https://opencollective.com/stylus" @@ -29655,12 +31017,52 @@ "webpack": "^5.0.0" } }, - "node_modules/stylus/node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "node_modules/stylus/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" + "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/stylus/node_modules/minimatch": { + "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" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/stylus/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, "node_modules/sumchecker": { "version": "3.0.1", @@ -29995,9 +31397,9 @@ } }, "node_modules/terser": { - "version": "5.31.6", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", - "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", + "version": "5.36.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", + "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -30175,13 +31577,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/thingies": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz", @@ -30246,23 +31641,37 @@ "dev": true, "license": "MIT" }, + "node_modules/tinyglobby": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", + "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/tldts": { - "version": "6.1.61", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.61.tgz", - "integrity": "sha512-rv8LUyez4Ygkopqn+M6OLItAOT9FF3REpPQDkdMx5ix8w4qkuE7Vo2o/vw1nxKQYmJDV8JpAMJQr1b+lTKf0FA==", + "version": "6.1.66", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.66.tgz", + "integrity": "sha512-l3ciXsYFel/jSRfESbyKYud1nOw7WfhrBEF9I3UiarYk/qEaOOwu3qXNECHw4fHGHGTEOuhf/VdKgoDX5M/dhQ==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^6.1.61" + "tldts-core": "^6.1.66" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "6.1.61", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.61.tgz", - "integrity": "sha512-In7VffkDWUPgwa+c9picLUxvb0RltVwTkSgMNFgvlGSWveCzGBemBqTsgJCL4EDFWZ6WH0fKTsot6yNhzy3ZzQ==", + "version": "6.1.66", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.66.tgz", + "integrity": "sha512-s07jJruSwndD2X8bVjwioPfqpIc1pDTzszPe9pL1Skbh4bjytL85KNQ3tolqLbCvpQHawIsGfFi9dgerWjqW4g==", "dev": true, "license": "MIT" }, @@ -30397,9 +31806,9 @@ } }, "node_modules/ts-api-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz", - "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", + "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "license": "MIT", "engines": { @@ -30672,41 +32081,41 @@ } }, "node_modules/tuf-js": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz", - "integrity": "sha512-GwIJau9XaA8nLVbUXsN3IlFi7WmQ48gBUrl3FTkkL/XLu/POhBzfmX9hd33FNMX1qAsfl6ozO1iMmW9NC8YniA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-3.0.1.tgz", + "integrity": "sha512-+68OP1ZzSF84rTckf3FA95vJ1Zlx/uaXyiiKyPd1pA4rZNkpEvDAKmsu1xUSmbF/chCRYgZ6UZkDwC7PmzmAyA==", "dev": true, "license": "MIT", "dependencies": { - "@tufjs/models": "2.0.1", - "debug": "^4.3.4", - "make-fetch-happen": "^13.0.1" + "@tufjs/models": "3.0.1", + "debug": "^4.3.6", + "make-fetch-happen": "^14.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/tuf-js/node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-4.0.0.tgz", + "integrity": "sha512-/xGlezI6xfGO9NwuJlnwz/K14qD1kCSAGtacBHnGzeAIuJGazcp45KP5NuyARXoKb7cwulAGWVsbeSxdG/cb0Q==", "dev": true, "license": "ISC", "dependencies": { "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/tuf-js/node_modules/cacache": { - "version": "18.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.4.tgz", - "integrity": "sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==", + "version": "19.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-19.0.1.tgz", + "integrity": "sha512-hdsUxulXCi5STId78vRVYEtDAjq99ICAUktLTeTYsLoTE6Z8dS0c8pWNCxwdrk9YfJeobDZc2Y186hD/5ZQgFQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/fs": "^3.1.0", + "@npmcli/fs": "^4.0.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", "lru-cache": "^10.0.1", @@ -30714,13 +32123,23 @@ "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" + "p-map": "^7.0.2", + "ssri": "^12.0.0", + "tar": "^7.4.3", + "unique-filename": "^4.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/tuf-js/node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/tuf-js/node_modules/fs-minipass": { @@ -30765,27 +32184,26 @@ "license": "ISC" }, "node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.1.tgz", - "integrity": "sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-14.0.3.tgz", + "integrity": "sha512-QMjGbFTP0blj97EeidG5hk/QhKQ3T4ICckQGLgz38QF7Vgbk6e6FTARN8KhKxyBbWn8R0HU+bnw8aSoFPD4qtQ==", "dev": true, "license": "ISC", "dependencies": { - "@npmcli/agent": "^2.0.0", - "cacache": "^18.0.0", + "@npmcli/agent": "^3.0.0", + "cacache": "^19.0.1", "http-cache-semantics": "^4.1.1", - "is-lambda": "^1.0.1", "minipass": "^7.0.2", - "minipass-fetch": "^3.0.0", + "minipass-fetch": "^4.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "proc-log": "^4.2.0", + "negotiator": "^1.0.0", + "proc-log": "^5.0.0", "promise-retry": "^2.0.1", - "ssri": "^10.0.0" + "ssri": "^12.0.0" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/tuf-js/node_modules/minimatch": { @@ -30809,79 +32227,176 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "ISC", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tuf-js/node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tuf-js/node_modules/minipass-fetch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-4.0.0.tgz", + "integrity": "sha512-2v6aXUXwLP1Epd/gc32HAMIWoczx+fZwEPRHm/VwtrJzRGwR1qGZXEYV3Zp8ZjjbwaZhMrM6uHV4KVkk+XCc2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^3.0.1" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/tuf-js/node_modules/minizlib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^7.0.4", + "rimraf": "^5.0.5" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/tuf-js/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tuf-js/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/tuf-js/node_modules/p-map": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", + "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tuf-js/node_modules/minipass-collect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", - "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", + "node_modules/tuf-js/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^7.0.3" + "glob": "^10.3.7" }, - "engines": { - "node": ">=16 || 14 >=14.17" + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", + "node_modules/tuf-js/node_modules/ssri": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-12.0.0.tgz", + "integrity": "sha512-S7iGNosepx9RadX82oimUkvr0Ct7IjJbEbs4mJcTxst8um95J3sDYU1RBEOvdu6oL1Wek2ODI5i4MAw+dZ6cAQ==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" + "minipass": "^7.0.3" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" + "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/tuf-js/node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", + "node_modules/tuf-js/node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, "license": "ISC", "dependencies": { - "minipass": "^7.0.3" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=18" } }, "node_modules/tuf-js/node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-4.0.0.tgz", + "integrity": "sha512-XSnEewXmQ+veP7xX2dS5Q4yZAvO40cBN2MWkJ7D/6sW4Dg6wYBNwM1Vrnz1FhH5AdeLIlUXRI9e28z1YZi71NQ==", "dev": true, "license": "ISC", "dependencies": { - "unique-slug": "^4.0.0" + "unique-slug": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/tuf-js/node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-5.0.0.tgz", + "integrity": "sha512-9OdaqO5kwqR+1kVgHAhsp5vPNU0hnxRa26rBFNfNgM7M6pNtgzeBn3s/xbyCQL3dcjzOatcef6UUHpB/6MaETg==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/tuf-js/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" } }, "node_modules/tunnel-agent": { @@ -30990,9 +32505,9 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", "dev": true, "license": "MIT", "dependencies": { @@ -31001,7 +32516,8 @@ "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -31011,18 +32527,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" }, "engines": { "node": ">= 0.4" @@ -31046,9 +32562,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -31060,15 +32576,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", - "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.18.0.tgz", + "integrity": "sha512-Xq2rRjn6tzVpAyHr3+nmSg1/9k9aIHnJ2iZeOH7cfGOWqTkXTm3kwpQglEuLGdNrYvPF+2gtAs+/KF5rjVo+WQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.14.0", - "@typescript-eslint/parser": "8.14.0", - "@typescript-eslint/utils": "8.14.0" + "@typescript-eslint/eslint-plugin": "8.18.0", + "@typescript-eslint/parser": "8.18.0", + "@typescript-eslint/utils": "8.18.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -31077,10 +32593,9 @@ "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/unbox-primitive": { @@ -31385,13 +32900,13 @@ } }, "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-6.0.0.tgz", + "integrity": "sha512-d7KLgL1LD3U3fgnvWEY1cQXoO/q6EQ1BSz48Sa149V/5zVTAbgmZIpyI8TRi6U9/JNyeYLlTKsEMPtLC27RFUg==", "dev": true, "license": "ISC", "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/vary": { @@ -31420,9 +32935,9 @@ } }, "node_modules/vite": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", - "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "license": "MIT", "dependencies": { @@ -31909,35 +33424,6 @@ "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/vite/node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", @@ -31962,9 +33448,9 @@ } }, "node_modules/watchpack": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", - "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "license": "MIT", "dependencies": { @@ -32000,7 +33486,8 @@ "resolved": "https://registry.npmjs.org/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz", "integrity": "sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw==", "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/webidl-conversions": { "version": "7.0.0", @@ -32013,19 +33500,19 @@ } }, "node_modules/webpack": { - "version": "5.94.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", - "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "^1.0.5", + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", "@webassemblyjs/wasm-parser": "^1.12.1", - "acorn": "^8.7.1", - "acorn-import-attributes": "^1.9.5", - "browserslist": "^4.21.10", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", @@ -32090,9 +33577,9 @@ } }, "node_modules/webpack-dev-middleware/node_modules/memfs": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.14.0.tgz", - "integrity": "sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==", + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.15.0.tgz", + "integrity": "sha512-q9MmZXd2rRWHS6GU3WEm3HyiXZyyoA1DqdOhEq0lxPBmKb5S7IAOwX0RgUCwJfqjelDCySa5h8ujOy24LqsWcw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -32110,9 +33597,9 @@ } }, "node_modules/webpack-dev-server": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", - "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.1.0.tgz", + "integrity": "sha512-aQpaN81X6tXie1FoOB7xlMfCsN19pSvRAeYUHOdFWOlhpQ/LlbfTqYwwmEDFV0h8GGuqmCmKmT+pxcUV/Nt2gQ==", "dev": true, "license": "MIT", "dependencies": { @@ -32129,8 +33616,7 @@ "colorette": "^2.0.10", "compression": "^1.7.4", "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", + "express": "^4.19.2", "graceful-fs": "^4.2.6", "html-entities": "^2.4.0", "http-proxy-middleware": "^2.0.3", @@ -32138,14 +33624,13 @@ "launch-editor": "^2.6.1", "open": "^10.0.3", "p-retry": "^6.2.0", - "rimraf": "^5.0.5", "schema-utils": "^4.2.0", "selfsigned": "^2.4.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", - "webpack-dev-middleware": "^7.1.0", - "ws": "^8.16.0" + "webpack-dev-middleware": "^7.4.2", + "ws": "^8.18.0" }, "bin": { "webpack-dev-server": "bin/webpack-dev-server.js" @@ -32169,25 +33654,42 @@ } } }, - "node_modules/webpack-dev-server/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==", + "node_modules/webpack-dev-server/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, - "bin": { - "glob": "dist/esm/bin.mjs" + "engines": { + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/webpack-dev-server/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" } }, "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": { @@ -32225,46 +33727,30 @@ "node": ">= 10" } }, - "node_modules/webpack-dev-server/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/webpack-dev-server/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "license": "MIT", "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=8.6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/webpack-dev-server/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/webpack-dev-server/node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "node_modules/webpack-dev-server/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" + "picomatch": "^2.2.1" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8.10.0" } }, "node_modules/webpack-merge": { @@ -32446,19 +33932,6 @@ "node": ">=12" } }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", @@ -32499,17 +33972,67 @@ } }, "node_modules/which-boxed-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.0.tgz", + "integrity": "sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.0", + "is-number-object": "^1.1.0", + "is-string": "^1.1.0", + "is-symbol": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", + "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -32523,9 +34046,9 @@ "license": "ISC" }, "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", + "integrity": "sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==", "dev": true, "license": "MIT", "dependencies": { @@ -32783,13 +34306,15 @@ "license": "ISC" }, "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { - "node": ">= 6" + "node": ">= 14" } }, "node_modules/yargs": { @@ -32918,9 +34443,9 @@ } }, "node_modules/zone.js": { - "version": "0.14.10", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.14.10.tgz", - "integrity": "sha512-YGAhaO7J5ywOXW6InXNlLmfU194F8lVgu7bRntUF3TiG8Y3nBK0x1UJJuHUP/e8IyihkjCYqhCScpSwnlaSRkQ==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.15.0.tgz", + "integrity": "sha512-9oxn0IIjbCZkJ67L+LkhYWRyAy7axphb3VgE2MBDlOqnmHMPWGYMxJxBYFueFq/JGY2GMwS0rU+UCLunEmy5UA==", "license": "MIT" } } diff --git a/package.json b/package.json index 8998a5f..ce0795a 100644 --- a/package.json +++ b/package.json @@ -18,53 +18,53 @@ "postinstall": "patch-package && electron-builder install-app-deps" }, "dependencies": { - "@angular/animations": "~18.2.0", - "@angular/common": "~18.2.0", - "@angular/compiler": "~18.2.0", - "@angular/core": "~18.2.0", - "@angular/forms": "~18.2.0", - "@angular/platform-browser": "~18.2.0", - "@angular/platform-browser-dynamic": "~18.2.0", - "@angular/router": "~18.2.0", + "@angular/animations": "~19.0.0", + "@angular/common": "~19.0.0", + "@angular/compiler": "~19.0.0", + "@angular/core": "~19.0.0", + "@angular/forms": "~19.0.0", + "@angular/platform-browser": "~19.0.0", + "@angular/platform-browser-dynamic": "~19.0.0", + "@angular/router": "~19.0.0", "@ionic/angular": "^8.0.0", "apexcharts": "^4.1.0", "electron-updater": "^6.3.9", "ionicons": "^7.0.0", - "ng-apexcharts": "^1.13.0", + "ng-apexcharts": "^1.15.0", "patch-package": "^8.0.0", "rxjs": "~7.8.0", "serialport": "^12.0.0", - "zone.js": "~0.14.3" + "zone.js": "~0.15.0" }, "devDependencies": { - "@angular-devkit/build-angular": "~18.2.0", - "@angular-devkit/core": "~18.2.0", - "@angular-devkit/schematics": "~18.2.0", - "@angular/cli": "~18.2.0", - "@angular/compiler-cli": "~18.2.0", - "@angular/language-service": "~18.2.0", + "@angular-devkit/build-angular": "~19.0.0", + "@angular-devkit/core": "~19.0.0", + "@angular-devkit/schematics": "~19.0.0", + "@angular/cli": "~19.0.0", + "@angular/compiler-cli": "~19.0.0", + "@angular/language-service": "~19.0.0", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", "@eslint/js": "^9.8.0", - "@nx/angular": "19.8.10", - "@nx/cypress": "19.8.10", - "@nx/eslint": "19.8.10", - "@nx/eslint-plugin": "19.8.10", - "@nx/jest": "19.8.10", - "@nx/js": "19.8.10", - "@nx/web": "19.8.10", - "@nx/workspace": "19.8.10", - "@nxext/ionic-angular": "^19.1.2", - "@schematics/angular": "~18.2.0", + "@nx/angular": "20.2.2", + "@nx/cypress": "20.2.2", + "@nx/eslint": "20.2.2", + "@nx/eslint-plugin": "20.2.2", + "@nx/jest": "20.2.2", + "@nx/js": "20.2.2", + "@nx/web": "20.2.2", + "@nx/workspace": "20.2.2", + "@nxext/ionic-angular": "^20.0.5", + "@schematics/angular": "~19.0.0", "@swc-node/register": "~1.9.1", "@swc/core": "~1.5.7", "@swc/helpers": "~0.5.11", "@types/jest": "^29.5.12", "@types/node": "18.16.9", "@typescript-eslint/utils": "^8.0.0", - "angular-eslint": "^18.3.0", + "angular-eslint": "^19.0.0", "cypress": "^13.13.0", - "electron": "^31.0.1", + "electron": "^33.3.0", "electron-icon-builder": "^2.0.1", "eslint": "^9.8.0", "eslint-config-prettier": "^9.0.0", @@ -74,14 +74,14 @@ "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", "jest-environment-node": "^29.7.0", - "jest-preset-angular": "~14.1.0", - "nx": "19.8.10", - "nx-electron": "^19.0.0", + "jest-preset-angular": "~14.4.2", + "nx": "20.2.2", + "nx-electron": "20.0.0-alpha.0", "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tslib": "^2.3.0", - "typescript": "~5.5.2", + "typescript": "~5.6.3", "typescript-eslint": "^8.0.0" } } diff --git a/patches/@nx+eslint-plugin+19.8.10.patch b/patches/@nx+eslint-plugin+19.8.10.patch deleted file mode 100644 index a9b2759..0000000 --- a/patches/@nx+eslint-plugin+19.8.10.patch +++ /dev/null @@ -1,28 +0,0 @@ -diff --git a/node_modules/@nx/eslint-plugin/src/flat-configs/javascript.js b/node_modules/@nx/eslint-plugin/src/flat-configs/javascript.js -index 8768261..01bb575 100644 ---- a/node_modules/@nx/eslint-plugin/src/flat-configs/javascript.js -+++ b/node_modules/@nx/eslint-plugin/src/flat-configs/javascript.js -@@ -22,7 +22,8 @@ const isPrettierAvailable = (0, config_utils_1.packageExists)('prettier') && (0, - * breaking changes - we should also look to replace all the @typescript-eslint - * related plugins and rules below. - */ --exports.default = typescript_eslint_1.default.config(js_1.default.configs.recommended, ...typescript_eslint_1.default.configs.recommended, ...(isPrettierAvailable ? [require('eslint-config-prettier')] : []), { -+exports.default = typescript_eslint_1.default.config({files: ['**/*.js', '**/*.jsx'], -+ extends: [js_1.default.configs.recommended, ...typescript_eslint_1.default.configs.recommended]}, ...(isPrettierAvailable ? [require('eslint-config-prettier')] : []), { - languageOptions: { - parser: typescript_eslint_1.default.parser, - ecmaVersion: 2020, -diff --git a/node_modules/@nx/eslint-plugin/src/flat-configs/typescript.js b/node_modules/@nx/eslint-plugin/src/flat-configs/typescript.js -index 889d98e..de7692d 100644 ---- a/node_modules/@nx/eslint-plugin/src/flat-configs/typescript.js -+++ b/node_modules/@nx/eslint-plugin/src/flat-configs/typescript.js -@@ -13,7 +13,8 @@ const isPrettierAvailable = (0, config_utils_1.packageExists)('prettier') && (0, - * It should therefore NOT contain any rules or plugins which are specific - * to one ecosystem, such as React, Angular, Node etc. - */ --exports.default = typescript_eslint_1.default.config(js_1.default.configs.recommended, ...typescript_eslint_1.default.configs.recommended, ...(isPrettierAvailable ? [require('eslint-config-prettier')] : []), { -+exports.default = typescript_eslint_1.default.config({files: ['**/*.js', '**/*.jsx'], -+ extends: [js_1.default.configs.recommended, ...typescript_eslint_1.default.configs.recommended]}, ...(isPrettierAvailable ? [require('eslint-config-prettier')] : []), { - plugins: { '@typescript-eslint': typescript_eslint_1.default.plugin }, - languageOptions: { - parser: typescript_eslint_1.default.parser, From 6ed71cf6ebc88c2a2b1f39974a09c9300416f5a8 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 17 Dec 2024 20:55:08 +0930 Subject: [PATCH 13/23] feat(spie-ui): add web worker for plotter --- apps/spie-ui/project.json | 6 +- .../connection/connection.component.ts | 2 +- .../components/plotter/plotter.component.html | 27 +-- .../components/plotter/plotter.component.ts | 199 +++++++++--------- .../components/plotter/plotter.worker.spec.ts | 152 +++++++++++++ .../app/components/plotter/plotter.worker.ts | 126 +++++++++++ .../terminal/terminal.component.html | 14 +- .../components/terminal/terminal.component.ts | 8 +- apps/spie-ui/src/test-setup.ts | 13 +- apps/spie-ui/tsconfig.worker.json | 9 + 10 files changed, 411 insertions(+), 145 deletions(-) create mode 100644 apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts create mode 100644 apps/spie-ui/src/app/components/plotter/plotter.worker.ts create mode 100644 apps/spie-ui/tsconfig.worker.json diff --git a/apps/spie-ui/project.json b/apps/spie-ui/project.json index 8779f1b..2285668 100644 --- a/apps/spie-ui/project.json +++ b/apps/spie-ui/project.json @@ -27,7 +27,8 @@ "apps/spie-ui/src/global.scss", "apps/spie-ui/src/theme/variables.scss" ], - "scripts": ["node_modules/apexcharts/dist/apexcharts.min.js"] + "scripts": ["node_modules/apexcharts/dist/apexcharts.min.js"], + "webWorkerTsConfig": "apps/spie-ui/tsconfig.worker.json" }, "configurations": { "production": { @@ -81,7 +82,8 @@ "executor": "@nx/jest:jest", "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/spie-ui/jest.config.ts" + "jestConfig": "apps/spie-ui/jest.config.ts", + "webWorkerTsConfig": "apps/spie-ui/tsconfig.worker.json" } }, "serve-static": { diff --git a/apps/spie-ui/src/app/components/connection/connection.component.ts b/apps/spie-ui/src/app/components/connection/connection.component.ts index 359d151..ccb413c 100644 --- a/apps/spie-ui/src/app/components/connection/connection.component.ts +++ b/apps/spie-ui/src/app/components/connection/connection.component.ts @@ -96,7 +96,7 @@ export class ConnectionComponent { }); }) .catch((error) => { - console.error('Error initializing serial ports:', error); // TODO: Toaster? + console.warn('Error initializing serial ports:', error); }); } diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.html b/apps/spie-ui/src/app/components/plotter/plotter.component.html index bf2fa3d..f2ab043 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.html +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.html @@ -5,15 +5,14 @@ @@ -22,9 +21,7 @@ - {{ - isDataEventPausedSubject.getValue() && isOpen() - ? 'Continue' - : 'Pause' - }} + {{ isPausedSubject.getValue() && isOpen() ? 'Continue' : 'Pause' }} diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts index 58c8d8f..468048c 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.ts +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -1,5 +1,9 @@ -import { Component, computed, inject, signal, viewChild } from '@angular/core'; -import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop'; +import { Component, computed, inject, signal } from '@angular/core'; +import { + takeUntilDestroyed, + toObservable, + toSignal, +} from '@angular/core/rxjs-interop'; import { IonButton, IonCard, @@ -13,6 +17,7 @@ import { } from '@ionic/angular/standalone'; import { type DataEvent } from '@spie/types'; import { + type ApexAxisChartSeries, type ApexChart, type ApexDataLabels, type ApexGrid, @@ -20,11 +25,21 @@ import { type ApexTooltip, type ApexXAxis, type ApexYAxis, - type ChartComponent, NgApexchartsModule, } from 'ng-apexcharts'; -import { BehaviorSubject, Subject, filter, map, merge, tap } from 'rxjs'; - +import { + BehaviorSubject, + Observable, + Subject, + bufferTime, + combineLatest, + filter, + map, + merge, + tap, +} from 'rxjs'; + +import { type WorkerMessage, type WorkerResult } from './plotter.worker'; import { SerialPortService } from '../../services/serial-port.service'; interface ChartOptions { @@ -33,6 +48,8 @@ interface ChartOptions { xaxis: ApexXAxis; grid: ApexGrid; stroke: ApexStroke; + chart: ApexChart; + tooltip: ApexTooltip; } @Component({ @@ -57,18 +74,20 @@ export class PlotterComponent { constructor() { this.dataEvent$.subscribe(); + this.parsedPlotterData$.subscribe(); } - chartArea = viewChild.required('chartObj'); - clearSeriesSubject = new Subject(); isOpen = this.serialPortService.isOpen; + + worker: Worker | undefined; private dataEvent$ = merge( this.serialPortService.dataEvent$.pipe( - filter(() => !this.isDataEventPausedSubject.getValue()) + filter(() => !this.isPausedSubject.getValue()) ), this.clearSeriesSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) ).pipe( + // throttleTime(10), tap((dataEvent) => { if (dataEvent.type === 'clear') { // Clear series @@ -76,105 +95,94 @@ export class PlotterComponent { return; } - const data = dataEvent.data; - const isDataTruncated = data.split('\n').length - 1 > 1; - if (isDataTruncated) { - console.warn('data truncated:'); - return; - } + const message: WorkerMessage = { + message: [dataEvent.data], + }; + + this.worker?.postMessage(message); + }), + takeUntilDestroyed() + ); + private parsedPlotterData$ = new Observable((observer) => { + this.worker = new Worker(new URL('./plotter.worker', import.meta.url)); - // Detect separator - const detectedSeparator = this.detectSeparator(data); + const listener = (messageEvent: MessageEvent) => { + observer.next(messageEvent.data); + }; - // Split values - const values = detectedSeparator - ? data - .split(detectedSeparator) - .map((value: string) => parseFloat(value)) - : [parseFloat(data)]; + this.worker?.addEventListener('message', listener); - // Update series with the correct amount of variables - if (this.series().length !== values.length) { - const newSeries = values.map((value: number, index: number) => ({ - name: `Variable ${index + 1}`, - data: [{ x: Date.now(), y: value }], - })); + return () => { + this.worker?.removeEventListener('message', listener); + }; + }).pipe( + bufferTime(50), + tap((workerResults: WorkerResult[]) => { + workerResults.forEach((workerResult) => { + const newSeries = workerResult.series; - this.series.set(newSeries); - return; - } + // TODO: Check if this is needed on tests + if (newSeries.length === 0) { + return; + } - let variableData: { x: number; y: number }[][] = []; + // Update series with the correct amount of variables + if (this.series().length !== newSeries.length) { + console.warn('Number of variables has changed'); - // Initialize variableData for the first time based on the number of variables - if (variableData.length === 0) { - variableData = Array.from({ length: values.length }, () => []); - } + this.series.set(newSeries); - // Populate data points for each variable - values.forEach((value: number, index: number) => { - variableData[index].push({ - x: Date.now(), - y: value, - }); - }); + return; + } - // TODO: plotter options scrollbackLength - const scrollbackLength = 1000; + const scrollbackLength = 500; // TODO: add to advanced settings - // Slice series based on scrollbackLength - if (this.series()[0].data.length > scrollbackLength) { this.series.update((series) => { - return series.map((variable) => { - const data = variable.data as { x: any; y: any }[]; - const truncatedData = data.slice(1); + return series.map((dataset, index) => { + const data = dataset.data as { x: any; y: any }[]; + const newDataPoint = newSeries[index]; - return { ...variable, data: truncatedData }; - }); - }); - } + if (newDataPoint && newDataPoint.data.length > 0) { + if (data.length >= scrollbackLength) { + data.shift(); + } - // Update series - this.series.update((series) => { - return series.map((variable, index) => { - const data = variable.data as { x: any; y: any }[]; - const updatedData = [...data, variableData[index][0]]; + data.push(newDataPoint.data[0] as { x: any; y: any }); + } - return { ...variable, data: updatedData }; + return { ...dataset, data }; + }); }); }); }), takeUntilDestroyed() ); - series = signal([]); - isDataEventPausedSubject = new BehaviorSubject(false); - private isDataEventPaused = toSignal(this.isDataEventPausedSubject, { - initialValue: false, - }); + isPausedSubject = new BehaviorSubject(false); + private isPaused = toSignal( + combineLatest([this.isPausedSubject, toObservable(this.isOpen)]).pipe( + map(([isPaused, isOpen]) => isPaused || !isOpen) + ), + { initialValue: false } + ); - private detectSeparator(line: string): string { - if (line.includes('\t')) return '\t'; - if (line.includes(',')) return ','; - if (line.includes(' ')) return ' '; - return ''; - } + series = signal([]); - chart = computed(() => { - return { + chartOptions = computed(() => ({ + chart: { type: 'line', animations: { enabled: false, }, zoom: { - enabled: this.isDataEventPaused(), + enabled: this.isPaused(), }, - }; - }); - - tooltip = computed(() => { - return { - enabled: this.isDataEventPaused(), + toolbar: { + show: this.isPaused(), + }, + }, + tooltip: { + enabled: this.isPaused(), x: { show: true, // format: 'dd/MM/yy HH:mm:ss:fff', // milliseconds is not working here @@ -192,23 +200,13 @@ export class PlotterComponent { return `${day}/${month}/${year} ${hours}:${minutes}:${seconds}:${milliseconds}`; }, }, - }; - }); - - chartOptions: ChartOptions = { + }, dataLabels: { enabled: false, }, - yaxis: { - // axisTicks: { - // show: false, - // }, - }, + yaxis: {}, xaxis: { - type: 'datetime', - // axisTicks: { - // show: false, - // }, + type: 'datetime', // TODO: toggle between time and linear (sample count) }, grid: { show: true, @@ -218,26 +216,21 @@ export class PlotterComponent { show: true, }, }, - yaxis: { - lines: { - show: true, - }, - }, }, stroke: { show: true, - curve: 'straight', - width: 2, + curve: 'straight', // TODO: toggle between straight and stepline? + width: 1, }, - }; + })); onClickClearTerminal(): void { this.clearSeriesSubject.next(); } onClickPauseTerminal(): void { - const currentValue = this.isDataEventPausedSubject.getValue(); - this.isDataEventPausedSubject.next(!currentValue); + const currentValue = this.isPausedSubject.getValue(); + this.isPausedSubject.next(!currentValue); } async onClickTerminalAdvancedModal() { diff --git a/apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts b/apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts new file mode 100644 index 0000000..9715b45 --- /dev/null +++ b/apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts @@ -0,0 +1,152 @@ +import { + cleanBuffer, + parseSerialMessages, + setCurrentTimestamp, +} from './plotter.worker'; + +describe('Plotter web worker', () => { + const fixedTimestamp = 1734411049296; + + beforeEach(() => { + setCurrentTimestamp(fixedTimestamp); + }); + + afterEach(() => { + cleanBuffer(); + }); + + describe.each([ + ['space', ' '], + ['tab', '\t'], + ['comma', ','], + ])('%s variable delimiter', (_, delimiter) => { + describe.each([ + ['trailing', delimiter], + ['no trailing', ''], + ])('%s', (_, trailingDelimiter) => { + describe.each([ + ['LF', '\n'], + ['CRLF', '\r\n'], + ])('%s record delimiter', (_, terminator) => { + it('should parse single variable', () => { + const messages = [ + `1${trailingDelimiter}${terminator}`, + `2${trailingDelimiter}${terminator}`, + ]; + + const assertion = { + series: [ + { + name: 'Variable 1', + data: [ + { x: fixedTimestamp, y: 1 }, + { x: fixedTimestamp, y: 2 }, + ], + }, + ], + }; + + const parsedMessage = parseSerialMessages(messages); + expect(parsedMessage).toEqual(assertion); + }); + + it('should handle multiple variables correctly', () => { + if (delimiter !== ' ') { + return; + } + const messages = [ + `1${delimiter}2${trailingDelimiter}${terminator}`, + `3${delimiter}4${trailingDelimiter}${terminator}`, + ]; + + const assertion = { + series: [ + { + name: 'Variable 1', + data: [ + { x: fixedTimestamp, y: 1 }, + { x: fixedTimestamp, y: 3 }, + ], + }, + { + name: 'Variable 2', + data: [ + { x: fixedTimestamp, y: 2 }, + { x: fixedTimestamp, y: 4 }, + ], + }, + ], + }; + + const parsedMessage = parseSerialMessages(messages); + expect(parsedMessage).toEqual(assertion); + }); + + it('should handle labeled variables correctly', () => { + const messages = [ + `temperature_1:1${delimiter}temperature_2:2${trailingDelimiter}${terminator}`, + `temperature_1:3${delimiter}temperature_2:4${trailingDelimiter}${terminator}`, + ]; + + const assertion = { + series: [ + { + name: 'temperature_1', + data: [ + { x: fixedTimestamp, y: 1 }, + { x: fixedTimestamp, y: 3 }, + ], + }, + { + name: 'temperature_2', + data: [ + { x: fixedTimestamp, y: 2 }, + { x: fixedTimestamp, y: 4 }, + ], + }, + ], + }; + + const parsedMessage = parseSerialMessages(messages); + expect(parsedMessage).toEqual(assertion); + }); + + it('should handle incomplete message buffering', () => { + const messages1 = [`1${delimiter}`]; + const assertion1 = { + series: [], + }; + const parsedMessage1 = parseSerialMessages(messages1); + expect(parsedMessage1).toEqual(assertion1); + + const messages2 = [`2${trailingDelimiter}${terminator}`]; + const assertion2 = { + series: [ + { + name: 'Variable 1', + data: [{ x: fixedTimestamp, y: 1 }], + }, + { + name: 'Variable 2', + data: [{ x: fixedTimestamp, y: 2 }], + }, + ], + }; + const parsedMessage2 = parseSerialMessages(messages2); + expect(parsedMessage2).toEqual(assertion2); + }); + + it('should return empty series if no valid data', () => { + const messages = ['invalid_data']; + + const assertion = { + series: [], + }; + + const parsedMessage = parseSerialMessages(messages); + expect(parsedMessage).toEqual(assertion); + }); + }); + }); + }); +}); diff --git a/apps/spie-ui/src/app/components/plotter/plotter.worker.ts b/apps/spie-ui/src/app/components/plotter/plotter.worker.ts new file mode 100644 index 0000000..0140507 --- /dev/null +++ b/apps/spie-ui/src/app/components/plotter/plotter.worker.ts @@ -0,0 +1,126 @@ +/// + +interface Series { + name: string; + data: { x: any; y: any }[]; +} + +export interface WorkerResult { + series: Series[]; +} + +export interface WorkerMessage { + message?: string[]; +} + +let useTestTimestamp = false; +let currentTimestamp: number = Date.now(); // Default to current time +let buffer = ''; +const separator = '\r?\n'; // Line break separator regex, matches both \n and \r\n +const delimiter = '[, \t]+'; // Delimiters: comma, space, tab (in the original order) +const separatorRegex = new RegExp(`(${separator})`, 'g'); +const delimiterRegex = new RegExp(delimiter, 'g'); + +// Handle incoming messages +addEventListener('message', (event: MessageEvent) => { + const { message } = event.data; + if (message) { + postMessage(parseSerialMessages(message)); + } +}); + +// Parse serial messages into structured data +export const parseSerialMessages = (messages: string[]): WorkerResult => { + // Combine messages and append any leftover buffer + const fullMessage = (buffer || '') + messages.join(''); + const messagesAndBuffer = fullMessage.split(separatorRegex).filter(Boolean); + + // Reset buffer for future incomplete messages + buffer = ''; + + // Check for incomplete message at the end and save it for the next chunk + if (!separatorRegex.test(messagesAndBuffer[messagesAndBuffer.length - 1])) { + buffer = messagesAndBuffer.pop()!; + } + + const timestamp = useTestTimestamp ? currentTimestamp : Date.now(); + const datasetNames: Set = new Set(); + const parsedLines: { [key: string]: { x: number; y: number }[] } = {}; + + // Process each message to extract key-value pairs + messagesAndBuffer.forEach((message) => + processMessage(message, timestamp, parsedLines, datasetNames) + ); + + // Convert parsed data into series + const series: Series[] = Array.from(datasetNames).map((varName) => ({ + name: varName, + data: parsedLines[varName] || [], + })); + + return { series }; +}; + +// Process a single message to extract tokens and add to parsed data +const processMessage = ( + message: string, + timestamp: number, + parsedLines: { [key: string]: { x: number; y: number }[] }, + datasetNames: Set +) => { + const tokens: string[] = parseTokens(message); + + // Add parsed tokens to the dataset + for (let i = 0; i < tokens.length; i += 2) { + const varName = tokens[i]; + const varValue = parseFloat(tokens[i + 1]); + + if (varName && !isNaN(varValue)) { + datasetNames.add(varName); + + if (!parsedLines[varName]) { + parsedLines[varName] = []; + } + + parsedLines[varName].push({ x: timestamp, y: varValue }); + } + } +}; + +// Parse a message into an array of tokens (handling both labelled and unlabelled formats) +const parseTokens = (message: string): string[] => { + const tokens: string[] = []; + + // Split the message using delimiters + const parts = message.split(delimiterRegex); + + if (message.includes(':')) { + // Process key-value pair format (labelled) + parts.forEach((keyValue) => { + const [key, value] = keyValue.split(':').map((part) => part.trim()); + if (key && value) { + tokens.push(key, value); + } + }); + } else { + // Process unlabelled format + parts.forEach((value, index) => { + if (value) { + tokens.push(`Variable ${index + 1}`, value); + } + }); + } + + return tokens; +}; + +// INFO: This is for unit testing only +export const setCurrentTimestamp = (timestamp: number) => { + currentTimestamp = timestamp; + useTestTimestamp = true; +}; + +// INFO: This is for unit testing only +export const cleanBuffer = () => { + buffer = ''; +}; diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.html b/apps/spie-ui/src/app/components/terminal/terminal.component.html index 2e67c45..5dc809a 100644 --- a/apps/spie-ui/src/app/components/terminal/terminal.component.html +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.html @@ -8,7 +8,7 @@ - {{ - isDataEventPausedSubject.getValue() && isOpen() - ? 'Continue' - : 'Pause' - }} + {{ isPausedSubject.getValue() && isOpen() ? 'Continue' : 'Pause' }} diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.ts b/apps/spie-ui/src/app/components/terminal/terminal.component.ts index 82af0c5..204d386 100644 --- a/apps/spie-ui/src/app/components/terminal/terminal.component.ts +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.ts @@ -60,7 +60,7 @@ export class TerminalComponent { terminalOptions = this.serialPortService.terminalOptions; private dataEvent$ = merge( this.serialPortService.dataEvent$.pipe( - filter(() => !this.isDataEventPausedSubject.getValue()) + filter(() => !this.isPausedSubject.getValue()) ), this.clearTerminalSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) ).pipe( @@ -121,7 +121,7 @@ export class TerminalComponent { takeUntilDestroyed() ); data = signal(''); - isDataEventPausedSubject = new BehaviorSubject(false); + isPausedSubject = new BehaviorSubject(false); terminalTextArea = viewChild.required('terminalTextArea'); private terminalAdvancedComponent = viewChild.required( @@ -133,8 +133,8 @@ export class TerminalComponent { } onClickPauseTerminal(): void { - const currentValue = this.isDataEventPausedSubject.getValue(); - this.isDataEventPausedSubject.next(!currentValue); + const currentValue = this.isPausedSubject.getValue(); + this.isPausedSubject.next(!currentValue); } async onClickTerminalAdvancedModal() { diff --git a/apps/spie-ui/src/test-setup.ts b/apps/spie-ui/src/test-setup.ts index d2c50cd..ea41401 100644 --- a/apps/spie-ui/src/test-setup.ts +++ b/apps/spie-ui/src/test-setup.ts @@ -1,9 +1,6 @@ -import 'jest-preset-angular/setup-jest'; +import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; -// @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment -globalThis.ngJest = { - testEnvironmentOptions: { - errorOnUnknownElements: true, - errorOnUnknownProperties: true, - }, -}; +setupZoneTestEnv({ + errorOnUnknownElements: true, + errorOnUnknownProperties: true, +}); diff --git a/apps/spie-ui/tsconfig.worker.json b/apps/spie-ui/tsconfig.worker.json new file mode 100644 index 0000000..48841fc --- /dev/null +++ b/apps/spie-ui/tsconfig.worker.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "../..//out-tsc/worker", + "lib": ["es2018", "webworker"], + "types": [] + }, + "include": ["src/**/*.worker.ts"] +} From ed3176559aae3133c06df0b4087ea5030e593635 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 17 Dec 2024 23:29:13 +0930 Subject: [PATCH 14/23] feat(spie-ui): improve plotter chart --- .../components/plotter/plotter.component.html | 2 ++ .../components/plotter/plotter.component.ts | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.html b/apps/spie-ui/src/app/components/plotter/plotter.component.html index f2ab043..24f41a2 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.html +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.html @@ -13,6 +13,8 @@ [grid]="chartOptions().grid" [stroke]="chartOptions().stroke" [dataLabels]="chartOptions().dataLabels" + [legend]="chartOptions().legend" + [markers]="chartOptions().markers" /> diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts index 468048c..9c02422 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.ts +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -21,6 +21,8 @@ import { type ApexChart, type ApexDataLabels, type ApexGrid, + type ApexLegend, + type ApexMarkers, type ApexStroke, type ApexTooltip, type ApexXAxis, @@ -50,6 +52,8 @@ interface ChartOptions { stroke: ApexStroke; chart: ApexChart; tooltip: ApexTooltip; + legend: ApexLegend; + markers: ApexMarkers; } @Component({ @@ -135,7 +139,7 @@ export class PlotterComponent { return; } - const scrollbackLength = 500; // TODO: add to advanced settings + const scrollbackLength = 1000; // TODO: add to advanced settings this.series.update((series) => { return series.map((dataset, index) => { @@ -204,8 +208,11 @@ export class PlotterComponent { dataLabels: { enabled: false, }, - yaxis: {}, + yaxis: { + title: { text: 'Amplitude' }, + }, xaxis: { + title: { text: 'Time (ms)' }, type: 'datetime', // TODO: toggle between time and linear (sample count) }, grid: { @@ -222,6 +229,13 @@ export class PlotterComponent { curve: 'straight', // TODO: toggle between straight and stepline? width: 1, }, + legend: { + position: 'top', + show: this.isPaused(), + }, + markers: { + size: 0, + }, })); onClickClearTerminal(): void { From 264f988a18840ff2b30846d73c1b43f719cd7c67 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:21:48 +0930 Subject: [PATCH 15/23] refactor(spie): rename events --- apps/spie/src/app/api/main.preload.ts | 12 +++++----- .../src/app/events/serial-port.events.spec.ts | 8 +++---- .../spie/src/app/events/serial-port.events.ts | 19 ++++++++-------- .../spie/src/app/events/update.events.spec.ts | 16 +++++++------- apps/spie/src/app/events/update.events.ts | 22 +++++++++---------- 5 files changed, 38 insertions(+), 39 deletions(-) diff --git a/apps/spie/src/app/api/main.preload.ts b/apps/spie/src/app/api/main.preload.ts index a3eb918..c4c05eb 100644 --- a/apps/spie/src/app/api/main.preload.ts +++ b/apps/spie/src/app/api/main.preload.ts @@ -14,17 +14,17 @@ export const electronAPI: ElectronAPI = { downloadUpdate: () => ipcRenderer.invoke('app-download-update'), installUpdate: () => ipcRenderer.invoke('app-install-update'), onUpdateEvent: (callback: (autoUpdaterEvent: AutoUpdaterEvent) => void) => { - const eventName = 'app-update-notification'; + const eventName = 'app-update-event'; const dataListener = ( _: IpcRendererEvent, autoUpdaterEvent: AutoUpdaterEvent ) => callback(autoUpdaterEvent); - ipcRenderer.send('app-update-add-notification-event-listener'); + ipcRenderer.send('app-update-event-add-listener'); ipcRenderer.on(eventName, dataListener); return () => { ipcRenderer.removeListener(eventName, dataListener); - ipcRenderer.send('app-update-remove-notification-event-listener'); + ipcRenderer.send('app-update-event-remove-listener'); }; }, serialPort: { @@ -40,17 +40,17 @@ export const electronAPI: ElectronAPI = { getReadEncoding: () => ipcRenderer.invoke('serial-port-get-read-encoding'), getOpenOptions: () => ipcRenderer.invoke('serial-port-get-open-options'), onEvent: (callback: (serialPortEvent: SerialPortEvent) => void) => { - const eventName = 'serial-port-notification'; + const eventName = 'serial-port-event'; const dataListener = ( _: IpcRendererEvent, serialPortEvent: SerialPortEvent ) => callback(serialPortEvent); - ipcRenderer.send('serial-port-add-notification-event-listener'); + ipcRenderer.send('serial-port-event-add-listener'); ipcRenderer.on(eventName, dataListener); return () => { ipcRenderer.removeListener(eventName, dataListener); - ipcRenderer.send('serial-port-remove-notification-event-listener'); + ipcRenderer.send('serial-port-event-remove-listener'); }; }, }, diff --git a/apps/spie/src/app/events/serial-port.events.spec.ts b/apps/spie/src/app/events/serial-port.events.spec.ts index 9fa936d..27bf6be 100644 --- a/apps/spie/src/app/events/serial-port.events.spec.ts +++ b/apps/spie/src/app/events/serial-port.events.spec.ts @@ -183,10 +183,10 @@ describe('Serial Port events', () => { const cleanup = window.electron.serialPort.onEvent(callback); expect(ipcRenderer.send).toHaveBeenCalledWith( - 'serial-port-add-notification-event-listener' + 'serial-port-event-add-listener' ); expect(ipcRenderer.on).toHaveBeenCalledWith( - 'serial-port-notification', + 'serial-port-event', expect.any(Function) ); @@ -294,11 +294,11 @@ describe('Serial Port events', () => { cleanup(); expect(ipcRenderer.removeListener).toHaveBeenCalledWith( - 'serial-port-notification', + 'serial-port-event', expect.any(Function) ); expect(ipcRenderer.send).toHaveBeenCalledWith( - 'serial-port-remove-notification-event-listener' + 'serial-port-event-remove-listener' ); }); }); diff --git a/apps/spie/src/app/events/serial-port.events.ts b/apps/spie/src/app/events/serial-port.events.ts index ee973d6..86650d3 100644 --- a/apps/spie/src/app/events/serial-port.events.ts +++ b/apps/spie/src/app/events/serial-port.events.ts @@ -60,17 +60,17 @@ export default class SerialPortEvents { addEventListener('error', (error: Error) => { const notification: SerialPortEvent = { type: 'error', error }; - event.sender.send('serial-port-notification', notification); + event.sender.send('serial-port-event', notification); }); addEventListener('open', () => { const notification: SerialPortEvent = { type: 'open' }; - event.sender.send('serial-port-notification', notification); + event.sender.send('serial-port-event', notification); }); addEventListener('close', () => { const notification: SerialPortEvent = { type: 'close' }; - event.sender.send('serial-port-notification', notification); + event.sender.send('serial-port-event', notification); }); addEventListener('data', (chunk: any) => { @@ -80,12 +80,12 @@ export default class SerialPortEvents { : chunk.toString('ascii'); const notification: SerialPortEvent = { type: 'data', data }; - event.sender.send('serial-port-notification', notification); + event.sender.send('serial-port-event', notification); }); addEventListener('drain', () => { const notification: SerialPortEvent = { type: 'drain' }; - event.sender.send('serial-port-notification', notification); + event.sender.send('serial-port-event', notification); }); SerialPortEvents.areListenersRegistered = true; @@ -242,7 +242,6 @@ export default class SerialPortEvents { ipcMain.handle('serial-port-get-read-encoding', () => { // console.warn('serial-port-get-read-encoding'); - return Promise.resolve(SerialPortEvents.encoding); }); @@ -251,13 +250,13 @@ export default class SerialPortEvents { return Promise.resolve(SerialPortEvents.openOptions); }); - ipcMain.on('serial-port-add-notification-event-listener', (event) => { - // console.warn('serial-port-add-notification-event-listener'); + ipcMain.on('serial-port-event-add-listener', (event) => { + // console.warn('serial-port-event-add-listener'); return SerialPortEvents.addEventListeners(event); }); - ipcMain.on('serial-port-remove-notification-event-listener', () => { - // console.warn('serial-port-remove-notification-event-listener'); + ipcMain.on('serial-port-event-remove-listener', () => { + // console.warn('serial-port-event-remove-listener'); return SerialPortEvents.removeEventListeners(); }); } diff --git a/apps/spie/src/app/events/update.events.spec.ts b/apps/spie/src/app/events/update.events.spec.ts index 8be8b99..601f719 100644 --- a/apps/spie/src/app/events/update.events.spec.ts +++ b/apps/spie/src/app/events/update.events.spec.ts @@ -95,10 +95,10 @@ describe('Update Events', () => { const cleanup = window.electron.onUpdateEvent(callback); expect(ipcRenderer.send).toHaveBeenCalledWith( - 'app-update-add-notification-event-listener' + 'app-update-event-add-listener' ); expect(ipcRenderer.on).toHaveBeenCalledWith( - 'app-update-notification', + 'app-update-event', expect.any(Function) ); @@ -106,11 +106,11 @@ describe('Update Events', () => { cleanup(); expect(ipcRenderer.removeListener).toHaveBeenCalledWith( - 'app-update-notification', + 'app-update-event', expect.any(Function) ); expect(ipcRenderer.send).toHaveBeenCalledWith( - 'app-update-remove-notification-event-listener' + 'app-update-event-remove-listener' ); }); }); @@ -123,10 +123,10 @@ describe('onUpdateEvent', () => { const cleanup = window.electron.onUpdateEvent(callback); expect(ipcRenderer.send).toHaveBeenCalledWith( - 'app-update-add-notification-event-listener' + 'app-update-event-add-listener' ); expect(ipcRenderer.on).toHaveBeenCalledWith( - 'app-update-notification', + 'app-update-event', expect.any(Function) ); @@ -283,11 +283,11 @@ describe('onUpdateEvent', () => { cleanup(); expect(ipcRenderer.removeListener).toHaveBeenCalledWith( - 'app-update-notification', + 'app-update-event', expect.any(Function) ); expect(ipcRenderer.send).toHaveBeenCalledWith( - 'app-update-remove-notification-event-listener' + 'app-update-event-remove-listener' ); }); }); diff --git a/apps/spie/src/app/events/update.events.ts b/apps/spie/src/app/events/update.events.ts index 8ef0e5b..4209906 100644 --- a/apps/spie/src/app/events/update.events.ts +++ b/apps/spie/src/app/events/update.events.ts @@ -45,14 +45,14 @@ export default class UpdateEvents { error, message, }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); }); addEventListener('checking-for-update', () => { const updateNotification: AutoUpdaterEvent = { type: 'checking-for-update', }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); }); addEventListener('update-not-available', (updateInfo: UpdateInfo) => { @@ -60,7 +60,7 @@ export default class UpdateEvents { type: 'update-not-available', updateInfo, }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); }); addEventListener('update-available', (updateInfo: UpdateInfo) => { @@ -75,7 +75,7 @@ export default class UpdateEvents { updateInfo, }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); }); addEventListener( @@ -85,7 +85,7 @@ export default class UpdateEvents { type: 'update-downloaded', updateDownloadedEvent, }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); } ); @@ -94,7 +94,7 @@ export default class UpdateEvents { type: 'download-progress', progressInfo, }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); }); addEventListener('update-cancelled', (updateInfo: UpdateInfo) => { @@ -102,7 +102,7 @@ export default class UpdateEvents { type: 'update-cancelled', updateInfo, }; - event.sender.send('app-update-notification', updateNotification); + event.sender.send('app-update-event', updateNotification); }); return Promise.resolve(); @@ -154,14 +154,14 @@ export default class UpdateEvents { const delayAfterAppReady = App.isDevelopmentMode() ? 3000 : 10000; setTimeout(checkForUpdates, delayAfterAppReady); - ipcMain.on('app-update-add-notification-event-listener', (event) => { - // console.warn('app-update-add-notification-event-listener'); + ipcMain.on('app-update-event-add-listener', (event) => { + // console.warn('app-update-event-add-listener'); return UpdateEvents.addEventListeners(event); }); - ipcMain.on('app-update-remove-notification-event-listener', () => { - // console.warn('app-update-remove-notification-event-listener'); + ipcMain.on('app-update-event-remove-listener', () => { + // console.warn('app-update-event-remove-listener'); return UpdateEvents.removeEventListeners(); }); From 9037786a0cfe3c1168de9de52d7df6dd7ac89aa4 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:28:36 +0930 Subject: [PATCH 16/23] test(spie-ui): improve unit testing --- .../src/app/services/electron.service.spec.ts | 29 ++------------- apps/spie-ui/src/test-setup.ts | 36 +++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/apps/spie-ui/src/app/services/electron.service.spec.ts b/apps/spie-ui/src/app/services/electron.service.spec.ts index f90c5e7..961b608 100644 --- a/apps/spie-ui/src/app/services/electron.service.spec.ts +++ b/apps/spie-ui/src/app/services/electron.service.spec.ts @@ -1,40 +1,15 @@ import { describe } from 'node:test'; import { TestBed } from '@angular/core/testing'; -import type { - AutoUpdaterEvent, - ElectronAPI, - SerialPortEvent, -} from '@spie/types'; +import type { AutoUpdaterEvent, SerialPortEvent } from '@spie/types'; import { ElectronService } from './electron.service'; +import { mockElectronAPI } from '../../test-setup'; describe('ElectronService', () => { let service: ElectronService; - const mockElectronAPI: ElectronAPI = { - platform: '', - quit: jest.fn(), - getVersion: jest.fn(), - downloadUpdate: jest.fn(), - installUpdate: jest.fn(), - onUpdateEvent: jest.fn(), - serialPort: { - list: jest.fn(), - open: jest.fn(), - close: jest.fn(), - write: jest.fn(), - isOpen: jest.fn(), - setReadEncoding: jest.fn(), - getReadEncoding: jest.fn(), - getOpenOptions: jest.fn(), - onEvent: jest.fn(), - }, - }; - beforeEach(() => { - (window as Window).electron = mockElectronAPI; - TestBed.configureTestingModule({ providers: [ElectronService], }); diff --git a/apps/spie-ui/src/test-setup.ts b/apps/spie-ui/src/test-setup.ts index ea41401..0bd7c1d 100644 --- a/apps/spie-ui/src/test-setup.ts +++ b/apps/spie-ui/src/test-setup.ts @@ -1,6 +1,42 @@ +import { TestBed } from '@angular/core/testing'; +import { type ElectronAPI } from '@spie/types'; import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone'; +import { ElectronService } from './app/services/electron.service'; + setupZoneTestEnv({ errorOnUnknownElements: true, errorOnUnknownProperties: true, }); + +export const mockElectronAPI: ElectronAPI = { + platform: '', + quit: jest.fn(), + getVersion: jest.fn(), + downloadUpdate: jest.fn(), + installUpdate: jest.fn(), + onUpdateEvent: jest.fn(), + serialPort: { + list: jest.fn(), + open: jest.fn(), + close: jest.fn(), + write: jest.fn(), + isOpen: jest.fn(), + setReadEncoding: jest.fn(), + getReadEncoding: jest.fn(), + getOpenOptions: jest.fn(), + onEvent: jest.fn(), + }, +}; + +beforeEach(() => { + (window as Window).electron = mockElectronAPI; + + TestBed.configureTestingModule({ + providers: [ElectronService], + }); +}); + +afterEach(() => { + jest.clearAllMocks(); +}); diff --git a/package-lock.json b/package-lock.json index c0a3228..f0bf929 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,7 @@ "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tslib": "^2.3.0", - "typescript": "~5.6.3", + "typescript": "~5.5.2", "typescript-eslint": "^8.0.0" } }, diff --git a/package.json b/package.json index ce0795a..20c1c49 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "ts-jest": "^29.1.0", "ts-node": "10.9.1", "tslib": "^2.3.0", - "typescript": "~5.6.3", + "typescript": "~5.5.2", "typescript-eslint": "^8.0.0" } } From 921738d5e9485d3ac04109551cb707a9dbb16b95 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:31:36 +0930 Subject: [PATCH 17/23] feat(spie-ui): add @angular/material --- apps/spie-ui/jest.config.ts | 2 +- apps/spie-ui/project.json | 10 ++--- apps/spie-ui/src/main.ts | 2 + package-lock.json | 84 +++++++++++++++++++++++++++++++++---- package.json | 7 +++- 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/apps/spie-ui/jest.config.ts b/apps/spie-ui/jest.config.ts index 3c7835c..047afc5 100644 --- a/apps/spie-ui/jest.config.ts +++ b/apps/spie-ui/jest.config.ts @@ -13,7 +13,7 @@ export default { ], }, transformIgnorePatterns: [ - '/node_modules/(?!(@ionic/core|@ionic/angular|@stencil/core|.*.mjs$))', + '/node_modules/(?!(@ionic/core|@ionic/angular|@stencil/core|ionicons|@angular/*|.*\\.mjs$))', ], snapshotSerializers: [ 'jest-preset-angular/build/serializers/no-ng-attributes', diff --git a/apps/spie-ui/project.json b/apps/spie-ui/project.json index 2285668..cd99305 100644 --- a/apps/spie-ui/project.json +++ b/apps/spie-ui/project.json @@ -24,11 +24,11 @@ } ], "styles": [ + "@angular/material/prebuilt-themes/azure-blue.css", "apps/spie-ui/src/global.scss", "apps/spie-ui/src/theme/variables.scss" ], - "scripts": ["node_modules/apexcharts/dist/apexcharts.min.js"], - "webWorkerTsConfig": "apps/spie-ui/tsconfig.worker.json" + "scripts": ["node_modules/apexcharts/dist/apexcharts.min.js"] }, "configurations": { "production": { @@ -55,7 +55,8 @@ "ci": { "progress": false } - } + }, + "defaultConfiguration": "production" }, "serve": { "executor": "@angular-devkit/build-angular:dev-server", @@ -82,8 +83,7 @@ "executor": "@nx/jest:jest", "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { - "jestConfig": "apps/spie-ui/jest.config.ts", - "webWorkerTsConfig": "apps/spie-ui/tsconfig.worker.json" + "jestConfig": "apps/spie-ui/jest.config.ts" } }, "serve-static": { diff --git a/apps/spie-ui/src/main.ts b/apps/spie-ui/src/main.ts index 0af307a..6fe6b8f 100644 --- a/apps/spie-ui/src/main.ts +++ b/apps/spie-ui/src/main.ts @@ -1,4 +1,5 @@ import { bootstrapApplication } from '@angular/platform-browser'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; import { PreloadAllModules, RouteReuseStrategy, @@ -18,5 +19,6 @@ bootstrapApplication(AppComponent, { { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }, provideIonicAngular(), provideRouter(routes, withPreloading(PreloadAllModules)), + provideAnimationsAsync(), ], }); diff --git a/package-lock.json b/package-lock.json index f0bf929..bb2ab74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,15 +11,17 @@ "license": "MIT", "dependencies": { "@angular/animations": "~19.0.0", + "@angular/cdk": "~19.0.4", "@angular/common": "~19.0.0", "@angular/compiler": "~19.0.0", "@angular/core": "~19.0.0", "@angular/forms": "~19.0.0", + "@angular/material": "~19.0.4", "@angular/platform-browser": "~19.0.0", "@angular/platform-browser-dynamic": "~19.0.0", "@angular/router": "~19.0.0", "@ionic/angular": "^8.0.0", - "apexcharts": "^4.1.0", + "apexcharts": "^4.3.0", "electron-updater": "^6.3.9", "ionicons": "^7.0.0", "ng-apexcharts": "^1.15.0", @@ -35,6 +37,7 @@ "@angular/cli": "~19.0.0", "@angular/compiler-cli": "~19.0.0", "@angular/language-service": "~19.0.0", + "@angular/material": "^19.0.4", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", "@eslint/js": "^9.8.0", @@ -53,7 +56,7 @@ "@swc/helpers": "~0.5.11", "@types/jest": "^29.5.12", "@types/node": "18.16.9", - "@typescript-eslint/utils": "^8.0.0", + "@typescript-eslint/utils": "^8.13.0", "angular-eslint": "^19.0.0", "cypress": "^13.13.0", "electron": "^33.3.0", @@ -512,6 +515,36 @@ } } }, + "node_modules/@angular/cdk": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.0.4.tgz", + "integrity": "sha512-P8V1n6AFFjBUJG3YRgw8DiiNDWPZVrwQ42wbwgZxd4s2TQAuNFg3YY8h/DSMVxt2sXpavrshZsoLtP9yLKZjHA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/cdk/node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/@angular/cli": { "version": "19.0.4", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.0.4.tgz", @@ -655,6 +688,25 @@ "node": "^18.19.1 || ^20.11.1 || >=22.0.0" } }, + "node_modules/@angular/material": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-19.0.4.tgz", + "integrity": "sha512-8WRMbN1+oRXx1ZFLni+BRz60F4FWzJPFORsQ8qAvY3sHWzyjunsYZkpbze3uiZO6bu3hiyQCU6g+k/58Qc6kkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/animations": "^19.0.0 || ^20.0.0", + "@angular/cdk": "19.0.4", + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", + "@angular/forms": "^19.0.0 || ^20.0.0", + "@angular/platform-browser": "^19.0.0 || ^20.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@angular/platform-browser": { "version": "19.0.3", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.0.3.tgz", @@ -7652,6 +7704,20 @@ "node": ">=8" } }, + "node_modules/@nx/eslint/node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/@nx/jest": { "version": "20.2.2", "resolved": "https://registry.npmjs.org/@nx/jest/-/jest-20.2.2.tgz", @@ -12075,9 +12141,9 @@ } }, "node_modules/apexcharts": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.2.0.tgz", - "integrity": "sha512-MQ5o8KnwMGcAlo+LhXlAjWGk8wBNBK2O1gFv+JiB6w3oJeuDJUFqa6FLTDlXvdhtObNQ3vIfAtv0AbMSkDv0DQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.3.0.tgz", + "integrity": "sha512-PfvZQpv91T68hzry9l5zP3Gip7sQvF0nFK91uCBrswIKX7rbIdbVNS4fOks9m9yP3Ppgs6LHgU2M/mjoG4NM0A==", "license": "MIT", "dependencies": { "@svgdotjs/svg.draggable.js": "^3.0.4", @@ -16691,7 +16757,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -32562,9 +32628,9 @@ "license": "MIT" }, "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index 20c1c49..c62af17 100644 --- a/package.json +++ b/package.json @@ -19,15 +19,17 @@ }, "dependencies": { "@angular/animations": "~19.0.0", + "@angular/cdk": "~19.0.4", "@angular/common": "~19.0.0", "@angular/compiler": "~19.0.0", "@angular/core": "~19.0.0", "@angular/forms": "~19.0.0", + "@angular/material": "~19.0.4", "@angular/platform-browser": "~19.0.0", "@angular/platform-browser-dynamic": "~19.0.0", "@angular/router": "~19.0.0", "@ionic/angular": "^8.0.0", - "apexcharts": "^4.1.0", + "apexcharts": "^4.3.0", "electron-updater": "^6.3.9", "ionicons": "^7.0.0", "ng-apexcharts": "^1.15.0", @@ -43,6 +45,7 @@ "@angular/cli": "~19.0.0", "@angular/compiler-cli": "~19.0.0", "@angular/language-service": "~19.0.0", + "@angular/material": "^19.0.4", "@commitlint/cli": "^19.5.0", "@commitlint/config-conventional": "^19.5.0", "@eslint/js": "^9.8.0", @@ -61,7 +64,7 @@ "@swc/helpers": "~0.5.11", "@types/jest": "^29.5.12", "@types/node": "18.16.9", - "@typescript-eslint/utils": "^8.0.0", + "@typescript-eslint/utils": "^8.13.0", "angular-eslint": "^19.0.0", "cypress": "^13.13.0", "electron": "^33.3.0", From 83da0b3bc8d95932a1891cf26092c4208607dad3 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:34:51 +0930 Subject: [PATCH 18/23] refactor(spie-ui): standardise position of modals --- .../components/connection/connection.component.html | 8 ++++---- .../src/app/components/plotter/plotter.component.html | 11 +++++++---- .../src/app/components/plotter/plotter.component.ts | 6 +++--- .../src/app/components/send/send.component.html | 4 ++-- .../app/components/terminal/terminal.component.html | 8 ++++---- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/spie-ui/src/app/components/connection/connection.component.html b/apps/spie-ui/src/app/components/connection/connection.component.html index 4cbb4ae..faf143a 100644 --- a/apps/spie-ui/src/app/components/connection/connection.component.html +++ b/apps/spie-ui/src/app/components/connection/connection.component.html @@ -71,11 +71,11 @@ - - + + diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.html b/apps/spie-ui/src/app/components/plotter/plotter.component.html index 24f41a2..84a963c 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.html +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.html @@ -26,7 +26,7 @@ isPausedSubject.getValue() && isOpen() ? 'danger' : 'secondary' " [disabled]="!isOpen()" - (click)="onClickPauseTerminal()" + (click)="onClickPauseSeries()" > Clear @@ -54,7 +54,7 @@ @@ -64,4 +64,7 @@ - + diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts index 9c02422..cf454be 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.ts +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -238,16 +238,16 @@ export class PlotterComponent { }, })); - onClickClearTerminal(): void { + onClickClearSeries(): void { this.clearSeriesSubject.next(); } - onClickPauseTerminal(): void { + onClickPauseSeries(): void { const currentValue = this.isPausedSubject.getValue(); this.isPausedSubject.next(!currentValue); } - async onClickTerminalAdvancedModal() { + async onClickPlotterAdvancedModal(): Promise { // this.terminalAdvancedComponent().terminalAdvancedModal().present(); // TODO } } diff --git a/apps/spie-ui/src/app/components/send/send.component.html b/apps/spie-ui/src/app/components/send/send.component.html index ca3b94f..2ddd768 100644 --- a/apps/spie-ui/src/app/components/send/send.component.html +++ b/apps/spie-ui/src/app/components/send/send.component.html @@ -39,7 +39,7 @@ - - + + diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.html b/apps/spie-ui/src/app/components/terminal/terminal.component.html index 5dc809a..90ec7a5 100644 --- a/apps/spie-ui/src/app/components/terminal/terminal.component.html +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.html @@ -59,9 +59,9 @@ - - + + From 7cc4bba41763770103fcc38d040ad76862300b0a Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:36:15 +0930 Subject: [PATCH 19/23] feat(spie): create data delimited event --- .../src/app/services/serial-port.service.ts | 14 ++++ .../spie/src/app/events/serial-port.events.ts | 64 +++++++++++-------- libs/types/src/lib/electron.d.ts | 6 +- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/apps/spie-ui/src/app/services/serial-port.service.ts b/apps/spie-ui/src/app/services/serial-port.service.ts index d323a15..6253860 100644 --- a/apps/spie-ui/src/app/services/serial-port.service.ts +++ b/apps/spie-ui/src/app/services/serial-port.service.ts @@ -89,4 +89,18 @@ export class SerialPortService { serialPortEvent.type === 'data' || serialPortEvent.type === 'clear' ) ); + + dataDelimitedEvent$: Observable = toObservable(this.isOpen).pipe( + switchMap(() => + merge( + this.electronService.serialPort.onEvent(), + this.clearDataSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) + ) + ), + filter( + (serialPortEvent) => + serialPortEvent.type === 'data-delimited' || + serialPortEvent.type === 'clear' + ) + ); } diff --git a/apps/spie/src/app/events/serial-port.events.ts b/apps/spie/src/app/events/serial-port.events.ts index 86650d3..76dd44c 100644 --- a/apps/spie/src/app/events/serial-port.events.ts +++ b/apps/spie/src/app/events/serial-port.events.ts @@ -5,11 +5,9 @@ import type { SerialPortEventType, } from '@spie/types'; import { ipcMain } from 'electron'; -import { InterByteTimeoutParser, SerialPort } from 'serialport'; +import { ReadlineParser, SerialPort } from 'serialport'; export default class SerialPortEvents { - private static serialPort: SerialPort | null = null; - private static parser: InterByteTimeoutParser | null = null; private static eventListeners = new Map< SerialPortEventType, (...args: any[]) => void @@ -18,6 +16,9 @@ export default class SerialPortEvents { SerialPortEventType, (...args: any[]) => void >(); + private static serialPort: SerialPort | null = null; + private static parser: ReadlineParser | null = null; + private static parserCallback: (data: string) => void | null = null; private static encoding: Encoding = 'ascii'; private static areListenersRegistered = false; private static openOptions: OpenOptions | null = null; @@ -33,11 +34,7 @@ export default class SerialPortEvents { serialPortEventType: SerialPortEventType, callback: (...args: any[]) => void ) => { - if ( - !SerialPortEvents.serialPort || - !SerialPortEvents.parser || - !SerialPortEvents.serialPort.isOpen - ) { + if (!SerialPortEvents.serialPort || !SerialPortEvents.serialPort.isOpen) { if (!SerialPortEvents.listenerQueue.has(serialPortEventType)) { // console.log('SerialPortEvents.addEventListener queue', serialPortEventType, callback); // Port is not open, queue the callback @@ -49,13 +46,17 @@ export default class SerialPortEvents { if (!SerialPortEvents.eventListeners.has(serialPortEventType)) { // console.log('SerialPortEvents.addEventListener attach', serialPortEventType, callback); // Port is open, attach callback immediately - if (serialPortEventType === 'data') { - SerialPortEvents.parser.on(serialPortEventType, callback); - } else { - SerialPortEvents.serialPort.on(serialPortEventType, callback); - } + SerialPortEvents.serialPort.on(serialPortEventType, callback); SerialPortEvents.eventListeners.set(serialPortEventType, callback); } + + if ( + SerialPortEvents.parser && + SerialPortEvents.parser.listenerCount('data') === 0 && + SerialPortEvents.parserCallback + ) { + SerialPortEvents.parser.on('data', SerialPortEvents.parserCallback); + } }; addEventListener('error', (error: Error) => { @@ -73,7 +74,7 @@ export default class SerialPortEvents { event.sender.send('serial-port-event', notification); }); - addEventListener('data', (chunk: any) => { + addEventListener('data', (chunk: Buffer) => { const data: string = SerialPortEvents.encoding === 'hex' ? chunk.toString('hex').toUpperCase().match(/.{2}/g).join(' ') @@ -88,6 +89,11 @@ export default class SerialPortEvents { event.sender.send('serial-port-event', notification); }); + SerialPortEvents.parserCallback = (data: string) => { + const notification: SerialPortEvent = { type: 'data-delimited', data }; + event.sender.send('serial-port-event', notification); + }; + SerialPortEvents.areListenersRegistered = true; return Promise.resolve(); @@ -99,14 +105,15 @@ export default class SerialPortEvents { } SerialPortEvents.eventListeners.forEach((callback, serialPortEventType) => { - // console.log('SerialPortEvents.removeEventListener', serialPortEventType, callback); - if (serialPortEventType === 'data') { - SerialPortEvents.parser.off(serialPortEventType, callback); - } else { - SerialPortEvents.serialPort.off(serialPortEventType, callback); - } + // console.log('SerialPortEvents.serialPort.off', serialPortEventType, callback); + SerialPortEvents.serialPort.off(serialPortEventType, callback); }); + if (SerialPortEvents.parser) { + // console.log('SerialPortEvents.parser.off', serialPortEventType, callback); + SerialPortEvents.parser.off('data', SerialPortEvents.parserCallback); + } + SerialPortEvents.eventListeners.clear(); SerialPortEvents.areListenersRegistered = false; @@ -139,25 +146,28 @@ export default class SerialPortEvents { } ); - // INFO: InterByteTimeoutParser should become a toggleable parameter if the added "delay" becomes a problem. SerialPortEvents.parser = SerialPortEvents.serialPort.pipe( - new InterByteTimeoutParser({ interval: 5 }) + new ReadlineParser({ includeDelimiter: true }) // TODO: remove includeDelimiter ); // Process queued listeners after opening SerialPortEvents.listenerQueue.forEach( (callback, serialPortEventType) => { // console.log(`Processing queued listener for serialPortEventType: ${serialPortEventType}`); - if (serialPortEventType === 'data') { - SerialPortEvents.parser.on(serialPortEventType, callback); - } else { - SerialPortEvents.serialPort.on(serialPortEventType, callback); - } + SerialPortEvents.serialPort.on(serialPortEventType, callback); SerialPortEvents.eventListeners.set(serialPortEventType, callback); } ); SerialPortEvents.listenerQueue.clear(); + if ( + SerialPortEvents.parser && + SerialPortEvents.parser.listenerCount('data') === 0 && + SerialPortEvents.parserCallback + ) { + SerialPortEvents.parser.on('data', SerialPortEvents.parserCallback); + } + SerialPortEvents.serialPort.open((error) => { if (error) { return reject(error); diff --git a/libs/types/src/lib/electron.d.ts b/libs/types/src/lib/electron.d.ts index 05d09f0..7e6d6bc 100644 --- a/libs/types/src/lib/electron.d.ts +++ b/libs/types/src/lib/electron.d.ts @@ -28,9 +28,13 @@ export type SerialPortEvent = | { type: 'open' } | { type: 'close' } | { type: 'data'; data: string } + | { type: 'data-delimited'; data: string } | { type: 'drain' }; -export type DataEvent = { type: 'data'; data: string } | { type: 'clear' }; +export type DataEvent = + | { type: 'data'; data: string } + | { type: 'data-delimited'; data: string } + | { type: 'clear' }; export interface SerialPortAPI { list: () => Promise; From 950ec9eed488217143e38131120b703eace965b6 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:37:00 +0930 Subject: [PATCH 20/23] feat(spie-ui): add more baud rates --- .../src/app/components/connection/connection.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/spie-ui/src/app/components/connection/connection.component.ts b/apps/spie-ui/src/app/components/connection/connection.component.ts index ccb413c..312ffdc 100644 --- a/apps/spie-ui/src/app/components/connection/connection.component.ts +++ b/apps/spie-ui/src/app/components/connection/connection.component.ts @@ -109,8 +109,8 @@ export class ConnectionComponent { ); baudRates = [ - 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 31250, 38400, - 57600, 115200, + 300, 600, 750, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, + 460800, 500000, 921600, 1000000, 2000000, ]; serialPorts = signal([]); From 2da0911c75148afabb162c0f4aadbed7b6041d7f Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:41:54 +0930 Subject: [PATCH 21/23] feat(spie-ui): improve scrollbackLength logic --- .../terminal-advanced-modal.component.html | 13 +++++++++---- .../terminal-advanced-modal.component.ts | 19 +++++++++++++++++-- .../components/terminal/terminal.component.ts | 2 +- .../src/app/interfaces/app.interface.ts | 6 +++++- .../src/app/services/serial-port.service.ts | 2 +- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html index 006abf2..77e9c2b 100644 --- a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html +++ b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html @@ -47,13 +47,18 @@ diff --git a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts index 1ca029d..09d2f03 100644 --- a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts +++ b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.ts @@ -17,6 +17,7 @@ import { import { type Encoding } from '@spie/types'; import { type Subject } from 'rxjs'; +import { SCROLLBACK_LENGTH_VALUES } from '../../interfaces/app.interface'; import { type CheckboxCustomEvent, type RangeCustomEvent, @@ -54,6 +55,8 @@ export class TerminalAdvancedComponent { terminalAdvancedModal = viewChild.required('terminalAdvancedModal'); + SCROLLBACK_LENGTH_VALUES = SCROLLBACK_LENGTH_VALUES; + onChangeTerminalEncoding(event: SelectCustomEvent): void { const selectedOption = event.detail.value; this.terminalOptions.update((terminalOptions) => ({ @@ -84,8 +87,10 @@ export class TerminalAdvancedComponent { // this.clearTerminalSubject().next(); } + onScrollbackLength(event: RangeCustomEvent): void { - const selectedOption = event.detail.value as number; + const index = event.detail.value as number; + const selectedOption = SCROLLBACK_LENGTH_VALUES[index]; this.terminalOptions.update((terminalOptions) => ({ ...terminalOptions, scrollbackLength: selectedOption, @@ -94,7 +99,17 @@ export class TerminalAdvancedComponent { // this.clearTerminalSubject().next(); } + onChangeUseReadlineParser(event: CheckboxCustomEvent): void { + const selectedOption = event.detail.checked; + this.terminalOptions.update((terminalOptions) => ({ + ...terminalOptions, + useReadlineParser: selectedOption, + })); + + this.clearTerminalSubject().next(); + } + pinFormatter(value: number): string { - return `${value}0k`; + return `${value + 1}0k`; } } diff --git a/apps/spie-ui/src/app/components/terminal/terminal.component.ts b/apps/spie-ui/src/app/components/terminal/terminal.component.ts index 204d386..e412118 100644 --- a/apps/spie-ui/src/app/components/terminal/terminal.component.ts +++ b/apps/spie-ui/src/app/components/terminal/terminal.component.ts @@ -98,7 +98,7 @@ export class TerminalComponent { } const excess = - prevData.length - this.terminalOptions().scrollbackLength * 10000; + prevData.length - this.terminalOptions().scrollbackLength; if (excess > 0) { return prevData.slice(excess); diff --git a/apps/spie-ui/src/app/interfaces/app.interface.ts b/apps/spie-ui/src/app/interfaces/app.interface.ts index 084b49a..01fef2e 100644 --- a/apps/spie-ui/src/app/interfaces/app.interface.ts +++ b/apps/spie-ui/src/app/interfaces/app.interface.ts @@ -1,10 +1,14 @@ import { type Delimiter, type Encoding } from '@spie/types'; +export const SCROLLBACK_LENGTH_VALUES = [ + 10000, 20000, 30000, 40000, 50000, +] as const; +export type ScrollbackLength = (typeof SCROLLBACK_LENGTH_VALUES)[number]; export interface TerminalOptions { encoding: Encoding; isAutoScrollEnabled: boolean; showTimestampsEnabled: boolean; - scrollbackLength: number; + scrollbackLength: ScrollbackLength; } export interface SendOptions { diff --git a/apps/spie-ui/src/app/services/serial-port.service.ts b/apps/spie-ui/src/app/services/serial-port.service.ts index 6253860..2d819ea 100644 --- a/apps/spie-ui/src/app/services/serial-port.service.ts +++ b/apps/spie-ui/src/app/services/serial-port.service.ts @@ -44,7 +44,7 @@ export class SerialPortService { encoding: 'ascii', isAutoScrollEnabled: true, showTimestampsEnabled: false, - scrollbackLength: 1, + scrollbackLength: 10000, }); sendOptions = signal({ From 350d82335e46b8421eef96d0d1a2b83733c033ac Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Tue, 24 Dec 2024 11:48:05 +0930 Subject: [PATCH 22/23] feat(spie-ui): add terminal option to use Readline parser --- apps/spie-ui/src/app/app.component.ts | 2 ++ .../terminal-advanced-modal.component.html | 14 ++++++++++ .../terminal-advanced-modal.component.ts | 4 +++ .../components/terminal/terminal.component.ts | 26 ++++++++++++------- .../src/app/interfaces/app.interface.ts | 1 + .../src/app/services/serial-port.service.ts | 1 + 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/apps/spie-ui/src/app/app.component.ts b/apps/spie-ui/src/app/app.component.ts index 248c2f9..04c50ec 100644 --- a/apps/spie-ui/src/app/app.component.ts +++ b/apps/spie-ui/src/app/app.component.ts @@ -4,6 +4,7 @@ import { addIcons } from 'ionicons'; import { cloudUploadOutline, documentOutline, + helpCircleOutline, logInOutline, logOutOutline, pauseOutline, @@ -28,6 +29,7 @@ export class AppComponent { constructor() { addIcons({ cloudUploadOutline }); addIcons({ documentOutline }); + addIcons({ helpCircleOutline }); addIcons({ logInOutline }); addIcons({ logOutOutline }); addIcons({ pauseOutline }); diff --git a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html index 77e9c2b..3abab0b 100644 --- a/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html +++ b/apps/spie-ui/src/app/components/terminal-advanced-modal/terminal-advanced-modal.component.html @@ -44,6 +44,20 @@ > + + Use readline parser + + terminalOptions.useReadlineParser), + switchMap((useReadlineParser) => + useReadlineParser + ? this.serialPortService.dataDelimitedEvent$ + : this.serialPortService.dataEvent$ + ), filter(() => !this.isPausedSubject.getValue()) ), this.clearTerminalSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) @@ -71,11 +85,6 @@ export class TerminalComponent { } const data = dataEvent.data; - const isDataTruncated = data.split('\n').length - 1 > 1; - if (isDataTruncated) { - console.warn('data truncated:'); - return; - } this.data.update((prevData) => { // Append timestamp if it is enabled @@ -91,7 +100,6 @@ export class TerminalComponent { // Append data prevData += `${data}`; - // TODO: evaluate if this should also be done for ascii // Append new line if hex encoding if (this.terminalOptions().encoding === 'hex') { prevData += '\n'; diff --git a/apps/spie-ui/src/app/interfaces/app.interface.ts b/apps/spie-ui/src/app/interfaces/app.interface.ts index 01fef2e..61d735a 100644 --- a/apps/spie-ui/src/app/interfaces/app.interface.ts +++ b/apps/spie-ui/src/app/interfaces/app.interface.ts @@ -9,6 +9,7 @@ export interface TerminalOptions { isAutoScrollEnabled: boolean; showTimestampsEnabled: boolean; scrollbackLength: ScrollbackLength; + useReadlineParser: boolean; } export interface SendOptions { diff --git a/apps/spie-ui/src/app/services/serial-port.service.ts b/apps/spie-ui/src/app/services/serial-port.service.ts index 2d819ea..7e9e237 100644 --- a/apps/spie-ui/src/app/services/serial-port.service.ts +++ b/apps/spie-ui/src/app/services/serial-port.service.ts @@ -45,6 +45,7 @@ export class SerialPortService { isAutoScrollEnabled: true, showTimestampsEnabled: false, scrollbackLength: 10000, + useReadlineParser: false, }); sendOptions = signal({ From 0a33b8fa7cd5fed082211435cf45ffbd77999070 Mon Sep 17 00:00:00 2001 From: Robson Oliveira dos Santos Date: Thu, 26 Dec 2024 00:03:40 +0930 Subject: [PATCH 23/23] feat(spie-ui): finish plotter feature --- apps/spie-ui-e2e/src/e2e/plotter.cy.ts | 168 ++++++++------ .../plotter-advanced-modal.component.html | 50 ++++ .../plotter-advanced-modal.component.scss | 0 .../plotter-advanced-modal.component.ts | 76 ++++++ .../components/plotter/plotter.component.ts | 126 ++++------ .../components/plotter/plotter.worker.spec.ts | 152 ------------ .../app/components/plotter/plotter.worker.ts | 126 ---------- .../src/app/interfaces/app.interface.ts | 40 ++++ .../src/app/utils/message-parser.spec.ts | 218 ++++++++++++++++++ apps/spie-ui/src/app/utils/message-parser.ts | 89 +++++++ apps/spie-ui/tsconfig.worker.json | 9 - package-lock.json | 8 +- package.json | 2 +- 13 files changed, 630 insertions(+), 434 deletions(-) create mode 100644 apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.html create mode 100644 apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.scss create mode 100644 apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.ts delete mode 100644 apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts delete mode 100644 apps/spie-ui/src/app/components/plotter/plotter.worker.ts create mode 100644 apps/spie-ui/src/app/utils/message-parser.spec.ts create mode 100644 apps/spie-ui/src/app/utils/message-parser.ts delete mode 100644 apps/spie-ui/tsconfig.worker.json diff --git a/apps/spie-ui-e2e/src/e2e/plotter.cy.ts b/apps/spie-ui-e2e/src/e2e/plotter.cy.ts index 77fabe4..eeb7f5a 100644 --- a/apps/spie-ui-e2e/src/e2e/plotter.cy.ts +++ b/apps/spie-ui-e2e/src/e2e/plotter.cy.ts @@ -41,6 +41,13 @@ describe('Plotter routine', () => { cy.get('.apexcharts-canvas').should('be.visible'); }); + it.only('should use sample count by default', () => { + cy.get('.apexcharts-xaxis-title-text').should( + 'contain.text', + 'Sample count' + ); + }); + it('should render series', () => { const numberOfPoints = 2; const mockEventData = plotOneVariable.eventData.slice(0, numberOfPoints); @@ -51,16 +58,14 @@ describe('Plotter routine', () => { return new Promise((resolve) => { // Mock data event with numberOfPoints point 50ms apart mockEventData.forEach((data, index) => { - setTimeout(() => { - win.onSerialPortEventTrigger({ - type: 'data', - data: data, - }); + win.onSerialPortEventTrigger({ + type: 'data-delimited', + data: data, + }); - if (index === mockEventData.length - 1) { - resolve(); - } - }, index * 50); + if (index === mockEventData.length - 1) { + resolve(); + } }); }); }) @@ -81,16 +86,14 @@ describe('Plotter routine', () => { return new Promise((resolve) => { // Mock data event with numberOfPoints point 50ms apart mockEventData.forEach((data, index) => { - setTimeout(() => { - win.onSerialPortEventTrigger({ - type: 'data', - data: data, - }); + win.onSerialPortEventTrigger({ + type: 'data-delimited', + data: data, + }); - if (index === mockEventData.length - 1) { - resolve(); - } - }, index * 50); + if (index === mockEventData.length - 1) { + resolve(); + } }); }); }) @@ -119,16 +122,14 @@ describe('Plotter routine', () => { return new Promise((resolve) => { // Mock data event with numberOfPoints point 50ms apart mockEventData.forEach((data, index) => { - setTimeout(() => { - win.onSerialPortEventTrigger({ - type: 'data', - data: data, - }); + win.onSerialPortEventTrigger({ + type: 'data-delimited', + data: data, + }); - if (index === mockEventData.length - 1) { - resolve(); - } - }, index * 50); + if (index === mockEventData.length - 1) { + resolve(); + } }); }); }) @@ -161,24 +162,20 @@ describe('Plotter routine', () => { it('should render multiple variables and large series', () => { const mockEventData = plotThreeVariables.eventData; const mockSeries = plotThreeVariables.series; - const chartStartOffset = 89; // Estimated offset to the first tooltip - const chartEndOffset = 9; // Estimated offset to the last tooltip cy.window() .then((win) => { return new Promise((resolve) => { // Mock data event with numberOfPoints point 50ms apart mockEventData.forEach((data, index) => { - setTimeout(() => { - win.onSerialPortEventTrigger({ - type: 'data', - data: data, - }); + win.onSerialPortEventTrigger({ + type: 'data-delimited', + data: data, + }); - if (index === mockEventData.length - 1) { - resolve(); - } - }, index * 50); + if (index === mockEventData.length - 1) { + resolve(); + } }); }); }) @@ -193,41 +190,47 @@ describe('Plotter routine', () => { .should('be.below', 940) .wait(500); - // Select the first path element and extract X coordinates cy.get('g.apexcharts-series path.apexcharts-line') - .first() - .then(($path) => { - const pathData = $path.attr('d'); - - const xCoordinates = (pathData as string) - .split('L') - .map((segment, index, array) => { - const [x] = segment - .trim() - .replace('M', '') - .split(' ') - .map(Number); - - // If it's the last element in the array, adjust the X coordinate - if (index === array.length - 1) { - return x + chartStartOffset - chartEndOffset; - } - - // Otherwise, add the pageOffset to the X value - return x + chartStartOffset; - }) - .filter((x) => !isNaN(x)); // Filter out NaN values + .invoke('attr', 'd') + .then((dAttribute) => { + // Get coordinates from the first line element + const coordinates: { x: any; y: any }[] = []; + const commands = (dAttribute as string).match( + /[ML]\s*[-\d.]+\s*[-\d.]+/g + ); + if (commands) { + commands.forEach((command) => { + const [x, y] = command.slice(1).trim().split(/\s+/).map(Number); + coordinates.push({ x, y }); + }); + } + return coordinates; + }) + .then((coordinates) => { + // Get the chart offset coordinates bases on the first vertical line + return cy.get('.apexcharts-xaxis-tick').then(($ticks) => { + const firstElement = $ticks[0]; + const firstX = firstElement.getBoundingClientRect().x; + const firstY = firstElement.getBoundingClientRect().x; + + return coordinates.map((point) => ({ + x: point.x + firstX, + y: point.y + firstY + 15, + })); + }); + }) + .then((coordinates) => { // Test labels and values mockSeries.forEach((points, pointsIndex) => { // // Helper for debug // cy.get('body').then(($body) => { // const refCircle = document.createElement('div'); // refCircle.style.position = 'absolute'; - // refCircle.style.left = `${xCoordinates[pointsIndex]}px`; - // refCircle.style.top = `${150}px`; - // refCircle.style.width = '5px'; - // refCircle.style.height = '5px'; + // refCircle.style.left = `${coordinates[pointsIndex].x}px`; + // refCircle.style.top = `${coordinates[pointsIndex].y}px`; + // refCircle.style.width = '2px'; + // refCircle.style.height = '2px'; // refCircle.style.borderRadius = '50%'; // refCircle.style.backgroundColor = 'red'; // Red for visibility // refCircle.style.zIndex = '9999'; // High z-index to appear on top @@ -238,8 +241,8 @@ describe('Plotter routine', () => { // Move mouse to estimated tooltip position cy.get('.apexcharts-canvas').trigger('mousemove', { - clientX: xCoordinates[pointsIndex], - clientY: 150, + clientX: coordinates[pointsIndex].x, + clientY: coordinates[pointsIndex].y, }); points.forEach((point, pointIndex) => { @@ -259,4 +262,35 @@ describe('Plotter routine', () => { }); }); }); + + it('should open and close the advanced modal', () => { + cy.get('app-plotter-component ion-button [name="settings-outline"]') + .parent() + .click(); + cy.get('ion-modal ion-toolbar ion-title').should( + 'contain', + 'Advanced Plotter Settings' + ); + cy.get('ion-modal ion-toolbar ion-button').click(); + cy.get('ion-modal').should('not.be.visible'); + }); + + it('should use timestamps if it is set', () => { + cy.get('app-plotter-component ion-button [name="settings-outline"]') + .parent() + .click(); + cy.get('ion-modal ion-toolbar ion-title').should( + 'contain', + 'Advanced Plotter Settings' + ); + + cy.getAdvancedModalCheckboxElement( + 'plotter-advanced-modal', + 'Use sample counter' + ).click(); + + cy.get('ion-modal ion-toolbar ion-button').click(); + + cy.get('.apexcharts-xaxis-title-text').should('contain.text', 'Time (ms)'); + }); }); diff --git a/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.html b/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.html new file mode 100644 index 0000000..46fa0f7 --- /dev/null +++ b/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.html @@ -0,0 +1,50 @@ + + + + + Advanced Plotter Settings + + Close + + + + + + + + Use sample counter + + + + + + + + + + diff --git a/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.scss b/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.ts b/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.ts new file mode 100644 index 0000000..8aef554 --- /dev/null +++ b/apps/spie-ui/src/app/components/plotter-advanced-modal/plotter-advanced-modal.component.ts @@ -0,0 +1,76 @@ +import { Component, model, output, viewChild } from '@angular/core'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { + IonButton, + IonButtons, + IonCheckbox, + IonContent, + IonHeader, + IonItem, + IonList, + IonModal, + IonRange, + IonTitle, + IonToolbar, +} from '@ionic/angular/standalone'; + +import { + NUMBER_OF_POINTS_VALUES, + type PlotterOptions, +} from '../../interfaces/app.interface'; +import { + type CheckboxCustomEvent, + type RangeCustomEvent, +} from '../../interfaces/ionic.interface'; + +@Component({ + selector: 'app-plotter-advanced-modal-component', + templateUrl: 'plotter-advanced-modal.component.html', + styleUrls: ['./plotter-advanced-modal.component.scss'], + imports: [ + IonButton, + IonButtons, + IonCheckbox, + IonContent, + IonHeader, + IonItem, + IonList, + IonModal, + IonRange, + IonTitle, + IonToolbar, + MatTooltipModule, + ], +}) +export class PlotterAdvancedComponent { + plotterOptions = model.required(); + clearChart = output(); + + plotterAdvancedModal = viewChild.required('plotterAdvancedModal'); + + NUMBER_OF_POINTS_VALUES = NUMBER_OF_POINTS_VALUES; + + onChangeUseSampleCount(event: CheckboxCustomEvent): void { + const selectedOption = event.detail.checked; + this.plotterOptions.update((plotterOptions) => ({ + ...plotterOptions, + useSampleCount: selectedOption, + })); + + this.clearChart.emit(); + } + + onChangeNumberOfPoints(event: RangeCustomEvent): void { + const index = event.detail.value as number; + const selectedOption = NUMBER_OF_POINTS_VALUES[index]; + this.plotterOptions.update((plotterOptions) => ({ + ...plotterOptions, + numberOfPoints: selectedOption, + })); + } + + pinFormatter(index: number): string { + const rangeValues = NUMBER_OF_POINTS_VALUES; + return `${rangeValues[index]}`; + } +} diff --git a/apps/spie-ui/src/app/components/plotter/plotter.component.ts b/apps/spie-ui/src/app/components/plotter/plotter.component.ts index cf454be..19dd63f 100644 --- a/apps/spie-ui/src/app/components/plotter/plotter.component.ts +++ b/apps/spie-ui/src/app/components/plotter/plotter.component.ts @@ -1,4 +1,4 @@ -import { Component, computed, inject, signal } from '@angular/core'; +import { Component, computed, inject, signal, viewChild } from '@angular/core'; import { takeUntilDestroyed, toObservable, @@ -16,22 +16,9 @@ import { IonText, } from '@ionic/angular/standalone'; import { type DataEvent } from '@spie/types'; -import { - type ApexAxisChartSeries, - type ApexChart, - type ApexDataLabels, - type ApexGrid, - type ApexLegend, - type ApexMarkers, - type ApexStroke, - type ApexTooltip, - type ApexXAxis, - type ApexYAxis, - NgApexchartsModule, -} from 'ng-apexcharts'; +import { NgApexchartsModule } from 'ng-apexcharts'; import { BehaviorSubject, - Observable, Subject, bufferTime, combineLatest, @@ -41,20 +28,14 @@ import { tap, } from 'rxjs'; -import { type WorkerMessage, type WorkerResult } from './plotter.worker'; +import { + type ChartOptions, + type PlotterOptions, + type Series, +} from '../../interfaces/app.interface'; import { SerialPortService } from '../../services/serial-port.service'; - -interface ChartOptions { - dataLabels: ApexDataLabels; - yaxis: ApexYAxis; - xaxis: ApexXAxis; - grid: ApexGrid; - stroke: ApexStroke; - chart: ApexChart; - tooltip: ApexTooltip; - legend: ApexLegend; - markers: ApexMarkers; -} +import MessageParser from '../../utils/message-parser'; +import { PlotterAdvancedComponent } from '../plotter-advanced-modal/plotter-advanced-modal.component'; @Component({ selector: 'app-plotter-component', @@ -71,87 +52,71 @@ interface ChartOptions { IonRow, IonText, NgApexchartsModule, + PlotterAdvancedComponent, ], }) export class PlotterComponent { private readonly serialPortService = inject(SerialPortService); + private plotterAdvancedComponent = viewChild.required( + PlotterAdvancedComponent + ); + constructor() { this.dataEvent$.subscribe(); - this.parsedPlotterData$.subscribe(); } clearSeriesSubject = new Subject(); isOpen = this.serialPortService.isOpen; - worker: Worker | undefined; private dataEvent$ = merge( - this.serialPortService.dataEvent$.pipe( + this.serialPortService.dataDelimitedEvent$.pipe( filter(() => !this.isPausedSubject.getValue()) ), this.clearSeriesSubject.pipe(map(() => ({ type: 'clear' } as DataEvent))) ).pipe( - // throttleTime(10), - tap((dataEvent) => { - if (dataEvent.type === 'clear') { - // Clear series - this.series.set([]); - return; - } - - const message: WorkerMessage = { - message: [dataEvent.data], - }; - - this.worker?.postMessage(message); - }), - takeUntilDestroyed() - ); - private parsedPlotterData$ = new Observable((observer) => { - this.worker = new Worker(new URL('./plotter.worker', import.meta.url)); - - const listener = (messageEvent: MessageEvent) => { - observer.next(messageEvent.data); - }; - - this.worker?.addEventListener('message', listener); - - return () => { - this.worker?.removeEventListener('message', listener); - }; - }).pipe( bufferTime(50), - tap((workerResults: WorkerResult[]) => { - workerResults.forEach((workerResult) => { - const newSeries = workerResult.series; + filter((dataEvents) => dataEvents.length > 0), + tap((dataEvents) => { + dataEvents.forEach((dataEvent) => { + if (dataEvent.type === 'clear') { + // Clear series + this.series.set([]); + return; + } + + const newSeries = MessageParser.parse( + dataEvent.data, + this.plotterOptions().useSampleCount + ); - // TODO: Check if this is needed on tests if (newSeries.length === 0) { + console.warn('Empty series returned'); return; } // Update series with the correct amount of variables if (this.series().length !== newSeries.length) { console.warn('Number of variables has changed'); - this.series.set(newSeries); - return; } - const scrollbackLength = 1000; // TODO: add to advanced settings + const numberOfPoints = this.plotterOptions().numberOfPoints; this.series.update((series) => { return series.map((dataset, index) => { - const data = dataset.data as { x: any; y: any }[]; + const data = dataset.data; const newDataPoint = newSeries[index]; if (newDataPoint && newDataPoint.data.length > 0) { - if (data.length >= scrollbackLength) { - data.shift(); + const excessLength = data.length - numberOfPoints + 1; + + if (excessLength > 0) { + data.splice(0, excessLength); } - data.push(newDataPoint.data[0] as { x: any; y: any }); + data.push(newDataPoint.data[0]); } return { ...dataset, data }; @@ -170,7 +135,12 @@ export class PlotterComponent { { initialValue: false } ); - series = signal([]); + plotterOptions = signal({ + useSampleCount: true, + numberOfPoints: 500, + }); + + series = signal([]); chartOptions = computed(() => ({ chart: { @@ -210,10 +180,16 @@ export class PlotterComponent { }, yaxis: { title: { text: 'Amplitude' }, + min: (min) => min + min * 0.05, + max: (max) => max + max * 0.05, }, xaxis: { - title: { text: 'Time (ms)' }, - type: 'datetime', // TODO: toggle between time and linear (sample count) + title: { + text: this.plotterOptions().useSampleCount + ? 'Sample count' + : 'Time (ms)', + }, + type: this.plotterOptions().useSampleCount ? 'numeric' : 'datetime', }, grid: { show: true, @@ -248,6 +224,6 @@ export class PlotterComponent { } async onClickPlotterAdvancedModal(): Promise { - // this.terminalAdvancedComponent().terminalAdvancedModal().present(); // TODO + this.plotterAdvancedComponent().plotterAdvancedModal().present(); } } diff --git a/apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts b/apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts deleted file mode 100644 index 9715b45..0000000 --- a/apps/spie-ui/src/app/components/plotter/plotter.worker.spec.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { - cleanBuffer, - parseSerialMessages, - setCurrentTimestamp, -} from './plotter.worker'; - -describe('Plotter web worker', () => { - const fixedTimestamp = 1734411049296; - - beforeEach(() => { - setCurrentTimestamp(fixedTimestamp); - }); - - afterEach(() => { - cleanBuffer(); - }); - - describe.each([ - ['space', ' '], - ['tab', '\t'], - ['comma', ','], - ])('%s variable delimiter', (_, delimiter) => { - describe.each([ - ['trailing', delimiter], - ['no trailing', ''], - ])('%s', (_, trailingDelimiter) => { - describe.each([ - ['LF', '\n'], - ['CRLF', '\r\n'], - ])('%s record delimiter', (_, terminator) => { - it('should parse single variable', () => { - const messages = [ - `1${trailingDelimiter}${terminator}`, - `2${trailingDelimiter}${terminator}`, - ]; - - const assertion = { - series: [ - { - name: 'Variable 1', - data: [ - { x: fixedTimestamp, y: 1 }, - { x: fixedTimestamp, y: 2 }, - ], - }, - ], - }; - - const parsedMessage = parseSerialMessages(messages); - expect(parsedMessage).toEqual(assertion); - }); - - it('should handle multiple variables correctly', () => { - if (delimiter !== ' ') { - return; - } - const messages = [ - `1${delimiter}2${trailingDelimiter}${terminator}`, - `3${delimiter}4${trailingDelimiter}${terminator}`, - ]; - - const assertion = { - series: [ - { - name: 'Variable 1', - data: [ - { x: fixedTimestamp, y: 1 }, - { x: fixedTimestamp, y: 3 }, - ], - }, - { - name: 'Variable 2', - data: [ - { x: fixedTimestamp, y: 2 }, - { x: fixedTimestamp, y: 4 }, - ], - }, - ], - }; - - const parsedMessage = parseSerialMessages(messages); - expect(parsedMessage).toEqual(assertion); - }); - - it('should handle labeled variables correctly', () => { - const messages = [ - `temperature_1:1${delimiter}temperature_2:2${trailingDelimiter}${terminator}`, - `temperature_1:3${delimiter}temperature_2:4${trailingDelimiter}${terminator}`, - ]; - - const assertion = { - series: [ - { - name: 'temperature_1', - data: [ - { x: fixedTimestamp, y: 1 }, - { x: fixedTimestamp, y: 3 }, - ], - }, - { - name: 'temperature_2', - data: [ - { x: fixedTimestamp, y: 2 }, - { x: fixedTimestamp, y: 4 }, - ], - }, - ], - }; - - const parsedMessage = parseSerialMessages(messages); - expect(parsedMessage).toEqual(assertion); - }); - - it('should handle incomplete message buffering', () => { - const messages1 = [`1${delimiter}`]; - const assertion1 = { - series: [], - }; - const parsedMessage1 = parseSerialMessages(messages1); - expect(parsedMessage1).toEqual(assertion1); - - const messages2 = [`2${trailingDelimiter}${terminator}`]; - const assertion2 = { - series: [ - { - name: 'Variable 1', - data: [{ x: fixedTimestamp, y: 1 }], - }, - { - name: 'Variable 2', - data: [{ x: fixedTimestamp, y: 2 }], - }, - ], - }; - const parsedMessage2 = parseSerialMessages(messages2); - expect(parsedMessage2).toEqual(assertion2); - }); - - it('should return empty series if no valid data', () => { - const messages = ['invalid_data']; - - const assertion = { - series: [], - }; - - const parsedMessage = parseSerialMessages(messages); - expect(parsedMessage).toEqual(assertion); - }); - }); - }); - }); -}); diff --git a/apps/spie-ui/src/app/components/plotter/plotter.worker.ts b/apps/spie-ui/src/app/components/plotter/plotter.worker.ts deleted file mode 100644 index 0140507..0000000 --- a/apps/spie-ui/src/app/components/plotter/plotter.worker.ts +++ /dev/null @@ -1,126 +0,0 @@ -/// - -interface Series { - name: string; - data: { x: any; y: any }[]; -} - -export interface WorkerResult { - series: Series[]; -} - -export interface WorkerMessage { - message?: string[]; -} - -let useTestTimestamp = false; -let currentTimestamp: number = Date.now(); // Default to current time -let buffer = ''; -const separator = '\r?\n'; // Line break separator regex, matches both \n and \r\n -const delimiter = '[, \t]+'; // Delimiters: comma, space, tab (in the original order) -const separatorRegex = new RegExp(`(${separator})`, 'g'); -const delimiterRegex = new RegExp(delimiter, 'g'); - -// Handle incoming messages -addEventListener('message', (event: MessageEvent) => { - const { message } = event.data; - if (message) { - postMessage(parseSerialMessages(message)); - } -}); - -// Parse serial messages into structured data -export const parseSerialMessages = (messages: string[]): WorkerResult => { - // Combine messages and append any leftover buffer - const fullMessage = (buffer || '') + messages.join(''); - const messagesAndBuffer = fullMessage.split(separatorRegex).filter(Boolean); - - // Reset buffer for future incomplete messages - buffer = ''; - - // Check for incomplete message at the end and save it for the next chunk - if (!separatorRegex.test(messagesAndBuffer[messagesAndBuffer.length - 1])) { - buffer = messagesAndBuffer.pop()!; - } - - const timestamp = useTestTimestamp ? currentTimestamp : Date.now(); - const datasetNames: Set = new Set(); - const parsedLines: { [key: string]: { x: number; y: number }[] } = {}; - - // Process each message to extract key-value pairs - messagesAndBuffer.forEach((message) => - processMessage(message, timestamp, parsedLines, datasetNames) - ); - - // Convert parsed data into series - const series: Series[] = Array.from(datasetNames).map((varName) => ({ - name: varName, - data: parsedLines[varName] || [], - })); - - return { series }; -}; - -// Process a single message to extract tokens and add to parsed data -const processMessage = ( - message: string, - timestamp: number, - parsedLines: { [key: string]: { x: number; y: number }[] }, - datasetNames: Set -) => { - const tokens: string[] = parseTokens(message); - - // Add parsed tokens to the dataset - for (let i = 0; i < tokens.length; i += 2) { - const varName = tokens[i]; - const varValue = parseFloat(tokens[i + 1]); - - if (varName && !isNaN(varValue)) { - datasetNames.add(varName); - - if (!parsedLines[varName]) { - parsedLines[varName] = []; - } - - parsedLines[varName].push({ x: timestamp, y: varValue }); - } - } -}; - -// Parse a message into an array of tokens (handling both labelled and unlabelled formats) -const parseTokens = (message: string): string[] => { - const tokens: string[] = []; - - // Split the message using delimiters - const parts = message.split(delimiterRegex); - - if (message.includes(':')) { - // Process key-value pair format (labelled) - parts.forEach((keyValue) => { - const [key, value] = keyValue.split(':').map((part) => part.trim()); - if (key && value) { - tokens.push(key, value); - } - }); - } else { - // Process unlabelled format - parts.forEach((value, index) => { - if (value) { - tokens.push(`Variable ${index + 1}`, value); - } - }); - } - - return tokens; -}; - -// INFO: This is for unit testing only -export const setCurrentTimestamp = (timestamp: number) => { - currentTimestamp = timestamp; - useTestTimestamp = true; -}; - -// INFO: This is for unit testing only -export const cleanBuffer = () => { - buffer = ''; -}; diff --git a/apps/spie-ui/src/app/interfaces/app.interface.ts b/apps/spie-ui/src/app/interfaces/app.interface.ts index 61d735a..d328d52 100644 --- a/apps/spie-ui/src/app/interfaces/app.interface.ts +++ b/apps/spie-ui/src/app/interfaces/app.interface.ts @@ -1,4 +1,15 @@ import { type Delimiter, type Encoding } from '@spie/types'; +import { + type ApexChart, + type ApexDataLabels, + type ApexGrid, + type ApexLegend, + type ApexMarkers, + type ApexStroke, + type ApexTooltip, + type ApexXAxis, + type ApexYAxis, +} from 'ng-apexcharts'; export const SCROLLBACK_LENGTH_VALUES = [ 10000, 20000, 30000, 40000, 50000, @@ -17,3 +28,32 @@ export interface SendOptions { encoding: Encoding; isSendInputValid: boolean; } + +export const NUMBER_OF_POINTS_VALUES = [50, 100, 500, 1000, 5000] as const; +export type NumberOfPoints = (typeof NUMBER_OF_POINTS_VALUES)[number]; +export interface PlotterOptions { + useSampleCount: boolean; + numberOfPoints: NumberOfPoints; +} + +export interface ChartOptions { + dataLabels: ApexDataLabels; + yaxis: ApexYAxis; + xaxis: ApexXAxis; + grid: ApexGrid; + stroke: ApexStroke; + chart: ApexChart; + tooltip: ApexTooltip; + legend: ApexLegend; + markers: ApexMarkers; +} + +export interface Data { + x: number; + y: number; +} + +export type Series = { + name?: string; + data: Data[]; +}[]; diff --git a/apps/spie-ui/src/app/utils/message-parser.spec.ts b/apps/spie-ui/src/app/utils/message-parser.spec.ts new file mode 100644 index 0000000..070910f --- /dev/null +++ b/apps/spie-ui/src/app/utils/message-parser.spec.ts @@ -0,0 +1,218 @@ +import MessageParser from './message-parser'; +import { type Series } from '../interfaces/app.interface'; + +describe('PlotterComponent', () => { + const fixedTimestamp = 1734411049296; + + describe('should parse serial messages', () => { + describe.each([ + ['space', ' '], + ['tab', '\t'], + ['comma', ','], + ])('%s variable delimiter', (_, delimiter) => { + describe.each([ + ['trailing', delimiter], + ['no trailing', ''], + ])('%s', (_, trailingDelimiter) => { + describe.each([ + ['LF', '\n'], + ['CRLF', '\r\n'], + ])('%s record delimiter', (_, terminator) => { + describe.each([ + ['with counter', true], + ['with timestamp', false], + ])('%s', (_, useSampleCount) => { + beforeEach(() => { + MessageParser['sampleCounter'] = 0; + MessageParser['useTestTimestamp'] = false; + MessageParser['testTimestamp'] = 0; + + if (!useSampleCount) { + MessageParser['testTimestamp'] = fixedTimestamp; + MessageParser['useTestTimestamp'] = true; + } + }); + + it('should parse single variable', () => { + const messages = [ + `1${trailingDelimiter}${terminator}`, + `2${trailingDelimiter}${terminator}`, + `3${trailingDelimiter}${terminator}`, + ]; + const assertion = [ + [ + { + name: 'Variable 1', + data: [{ x: useSampleCount ? 1 : fixedTimestamp, y: 1 }], + }, + ], + [ + { + name: 'Variable 1', + data: [{ x: useSampleCount ? 2 : fixedTimestamp, y: 2 }], + }, + ], + [ + { + name: 'Variable 1', + data: [{ x: useSampleCount ? 3 : fixedTimestamp, y: 3 }], + }, + ], + ]; + + const parsedMessages = messages.map((message) => { + return MessageParser.parse(message, useSampleCount); + }); + expect(parsedMessages).toEqual(assertion); + }); + + it('should handle multiple variables correctly', () => { + const messages = [ + `1${delimiter}2${trailingDelimiter}${terminator}`, + `3${delimiter}4${trailingDelimiter}${terminator}`, + `5${delimiter}6${trailingDelimiter}${terminator}`, + ]; + const assertion = [ + [ + { + name: 'Variable 1', + data: [{ x: useSampleCount ? 1 : fixedTimestamp, y: 1 }], + }, + { + name: 'Variable 2', + data: [{ x: useSampleCount ? 1 : fixedTimestamp, y: 2 }], + }, + ], + [ + { + name: 'Variable 1', + data: [{ x: useSampleCount ? 2 : fixedTimestamp, y: 3 }], + }, + { + name: 'Variable 2', + data: [{ x: useSampleCount ? 2 : fixedTimestamp, y: 4 }], + }, + ], + [ + { + name: 'Variable 1', + data: [{ x: useSampleCount ? 3 : fixedTimestamp, y: 5 }], + }, + { + name: 'Variable 2', + data: [{ x: useSampleCount ? 3 : fixedTimestamp, y: 6 }], + }, + ], + ]; + + const parsedMessages = messages.map((message) => { + return MessageParser.parse(message, useSampleCount); + }); + expect(parsedMessages).toEqual(assertion); + }); + + it('should handle labeled variables correctly', () => { + const messages = [ + `temperature_1:1${delimiter}temperature_2:2${trailingDelimiter}${terminator}`, + `temperature_1:3${delimiter}temperature_2:4${trailingDelimiter}${terminator}`, + `temperature_1:5${delimiter}temperature_2:6${trailingDelimiter}${terminator}`, + ]; + const assertion = [ + [ + { + name: 'temperature_1', + data: [{ x: useSampleCount ? 1 : fixedTimestamp, y: 1 }], + }, + { + name: 'temperature_2', + data: [{ x: useSampleCount ? 1 : fixedTimestamp, y: 2 }], + }, + ], + [ + { + name: 'temperature_1', + data: [{ x: useSampleCount ? 2 : fixedTimestamp, y: 3 }], + }, + { + name: 'temperature_2', + data: [{ x: useSampleCount ? 2 : fixedTimestamp, y: 4 }], + }, + ], + [ + { + name: 'temperature_1', + data: [{ x: useSampleCount ? 3 : fixedTimestamp, y: 5 }], + }, + { + name: 'temperature_2', + data: [{ x: useSampleCount ? 3 : fixedTimestamp, y: 6 }], + }, + ], + ]; + + const parsedMessages = messages.map((message) => { + return MessageParser.parse(message, useSampleCount); + }); + // console.log(JSON.stringify(parsedMessages)); + expect(parsedMessages).toEqual(assertion); + }); + + it('should handle duplicates labeled variables correctly', () => { + const messages = [ + `temperature_1:1${delimiter}temperature_1:2${trailingDelimiter}${terminator}`, + `temperature_1:3${delimiter}temperature_1:4${trailingDelimiter}${terminator}`, + `temperature_1:5${delimiter}temperature_1:6${trailingDelimiter}${terminator}`, + ]; + const assertion = [ + [ + { + name: 'temperature_1', + data: [ + { x: useSampleCount ? 1 : fixedTimestamp, y: 1 }, + { x: useSampleCount ? 1 : fixedTimestamp, y: 2 }, + ], + }, + ], + [ + { + name: 'temperature_1', + data: [ + { x: useSampleCount ? 2 : fixedTimestamp, y: 3 }, + { x: useSampleCount ? 2 : fixedTimestamp, y: 4 }, + ], + }, + ], + [ + { + name: 'temperature_1', + data: [ + { x: useSampleCount ? 3 : fixedTimestamp, y: 5 }, + { x: useSampleCount ? 3 : fixedTimestamp, y: 6 }, + ], + }, + ], + ]; + + const parsedMessages = messages.map((message) => { + return MessageParser.parse(message, useSampleCount); + }); + // console.log(JSON.stringify(parsedMessages)); + expect(parsedMessages).toEqual(assertion); + }); + + it('should return empty series if no valid data', () => { + const messages = 'invalid_data'; + const assertion: Series[] = []; + + const parsedMessage = MessageParser.parse( + messages, + useSampleCount + ); + expect(parsedMessage).toEqual(assertion); + }); + }); + }); + }); + }); + }); +}); diff --git a/apps/spie-ui/src/app/utils/message-parser.ts b/apps/spie-ui/src/app/utils/message-parser.ts new file mode 100644 index 0000000..984b14c --- /dev/null +++ b/apps/spie-ui/src/app/utils/message-parser.ts @@ -0,0 +1,89 @@ +import { type Data, type Series } from '../interfaces/app.interface'; + +export default class MessageParser { + private static sampleCounter = 0; + private static useTestTimestamp = false; + private static testTimestamp = 0; + + private static parseTokens(message: string): string[] { + // Variable delimiters: comma, space, tab + const delimiter = '[, \t]+'; + const delimiterRegex = new RegExp(delimiter, 'g'); + const tokens: string[] = []; + + message.split(delimiterRegex).forEach((part, index) => { + if (!part) { + return; + } + + if (part.includes(':')) { + const [key, value] = part.split(':').map((s) => s.trim()); + if (key && value) { + tokens.push(key, value); + } + } else { + tokens.push(`Variable ${index + 1}`, part); + } + }); + + return tokens; + } + + private static processMessage( + message: string, + datasetData: { [key: string]: Data[] }, + datasetNames: Set, + useSampleCount: boolean + ): void { + const tokens: string[] = MessageParser.parseTokens(message); + + let accounted = false; + + // Add parsed tokens to the dataset + for (let i = 0; i < tokens.length; i += 2) { + const label = tokens[i]; + const varValue = parseFloat(tokens[i + 1]); + + if (!label || isNaN(varValue)) { + continue; + } + + datasetNames.add(label); + + if (!datasetData[label]) { + datasetData[label] = []; + } + + if (!accounted) { + accounted = true; + MessageParser.sampleCounter++; + } + + const timestamp = MessageParser.useTestTimestamp + ? MessageParser.testTimestamp + : Date.now(); + const xAxisData = useSampleCount + ? MessageParser.sampleCounter + : timestamp; + + datasetData[label].push({ x: xAxisData, y: varValue }); + } + } + + static parse(message: string, useSampleCount: boolean): Series { + const datasetNames: Set = new Set(); + const datasetData: Record = {}; + + MessageParser.processMessage( + message, + datasetData, + datasetNames, + useSampleCount + ); + + return Array.from(datasetNames).map((label) => ({ + name: label, + data: datasetData[label] || [], + })); + } +} diff --git a/apps/spie-ui/tsconfig.worker.json b/apps/spie-ui/tsconfig.worker.json deleted file mode 100644 index 48841fc..0000000 --- a/apps/spie-ui/tsconfig.worker.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "../..//out-tsc/worker", - "lib": ["es2018", "webworker"], - "types": [] - }, - "include": ["src/**/*.worker.ts"] -} diff --git a/package-lock.json b/package-lock.json index bb2ab74..829e286 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,7 +71,7 @@ "jest-environment-node": "^29.7.0", "jest-preset-angular": "~14.4.2", "nx": "20.2.2", - "nx-electron": "20.0.0-alpha.0", + "nx-electron": "^20.0.0", "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1", @@ -25829,9 +25829,9 @@ } }, "node_modules/nx-electron": { - "version": "20.0.0-alpha.0", - "resolved": "https://registry.npmjs.org/nx-electron/-/nx-electron-20.0.0-alpha.0.tgz", - "integrity": "sha512-T5+sVG+5NWZNvDbNcq9U5WHKm97/fttSUL8HrKEk+asWVUfMilcg51laTRDIc1eSlF92iGr8GH7iCQLc1LnR1g==", + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/nx-electron/-/nx-electron-20.0.0.tgz", + "integrity": "sha512-b+cFh2z31vxoe/f9f393Hip1VDRLaQyBSAA4524OTc2ZIXa6kMWQpnJLXbNlJYbF9SkRf0QYTcdbj6iGJgLZww==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index c62af17..4ab5bd4 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "jest-environment-node": "^29.7.0", "jest-preset-angular": "~14.4.2", "nx": "20.2.2", - "nx-electron": "20.0.0-alpha.0", + "nx-electron": "^20.0.0", "prettier": "^2.6.2", "ts-jest": "^29.1.0", "ts-node": "10.9.1",