diff --git a/.changes/settings-section-pages.md b/.changes/settings-section-pages.md new file mode 100644 index 000000000..c63e6f9b4 --- /dev/null +++ b/.changes/settings-section-pages.md @@ -0,0 +1,6 @@ +--- +type: feature +area: settings +--- + +Settings sections are now separate pages with shareable URLs and a floating Save/Discard bar that appears only when you have unsaved changes; leaving settings with pending edits asks whether to save, discard, or keep editing. The EPG panel's "Open EPG settings" button now jumps straight to the EPG settings page. diff --git a/AGENTS.md b/AGENTS.md index 1cd9ef295..9b0084ee3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,9 +18,9 @@ This file provides guidance to coding agents working in this repository. - See `docs/architecture/nx-workspace-boundaries.md` for the current Nx tag and alias policy. - Keep `nx` and every official `@nx/*` package on the same exact version; run `pnpm run deps:nx:validate` after dependency updates. -- Vite `7.3.5`, resolved through Angular's build tooling, is patched with +- Vite `7.3.6`, resolved through Angular's build tooling, is patched with bounded transform prefilters and the upstream precise matchers in - `patches/vite@7.3.5.patch`. Keep the patch until supported Angular tooling + `patches/vite@7.3.6.patch`. Keep the patch until supported Angular tooling resolves a Vite version containing the fix, and run `pnpm run deps:vite:test` after related dependency updates. - A directory holding files consumed by other projects must be an Nx project. diff --git a/CLAUDE.md b/CLAUDE.md index aa7da18b0..a4b532776 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -76,9 +76,9 @@ pnpm nx show projects - See `docs/architecture/nx-workspace-boundaries.md` for the current Nx tag and alias policy. - Keep `nx` and every official `@nx/*` package on the same exact version; run `pnpm run deps:nx:validate` after dependency updates. -- Vite `7.3.5`, resolved through Angular's build tooling, is patched with +- Vite `7.3.6`, resolved through Angular's build tooling, is patched with bounded transform prefilters and the upstream precise matchers in - `patches/vite@7.3.5.patch`. Keep the patch until supported Angular tooling + `patches/vite@7.3.6.patch`. Keep the patch until supported Angular tooling resolves a Vite version containing the fix, and run `pnpm run deps:vite:test` after related dependency updates. - A directory holding files consumed by other projects must be an Nx project. @@ -514,7 +514,7 @@ See `docs/architecture/m3u-playlist-module.md` for complete documentation. `/workspace/xtreams/:id/downloads/:downloadId` and `/workspace/stalker/:id/downloads/:downloadId`. Focused download details hide the workspace context panel. -- Settings: `/workspace/settings` (`/settings` redirects there) +- Settings: `/workspace/settings/:section` — one page per section (`general`, `playback`, `epg`, `dashboard`, `remote-control`, `tmdb`, `backup`, `reset`, `about`); `/workspace/settings` redirects to `general`, unknown or capability-gated sections redirect there too, and `/settings` redirects into the workspace. The shared form lives on the parent `SettingsComponent`, so edits survive section switches; a floating unsaved-changes bar (Save/Discard) replaces the old always-visible footer Save button. Leaving the settings AREA with a dirty form triggers `settingsUnsavedChangesGuard` (canDeactivate) and a save/discard/stay dialog — section switches deliberately bypass it, and a failed save cancels the navigation **Service Architecture** (Factory Pattern): diff --git a/apps/electron-backend-e2e/src/backup-roundtrip.e2e.ts b/apps/electron-backend-e2e/src/backup-roundtrip.e2e.ts index 102cf35f6..d0e6df701 100644 --- a/apps/electron-backend-e2e/src/backup-roundtrip.e2e.ts +++ b/apps/electron-backend-e2e/src/backup-roundtrip.e2e.ts @@ -8,6 +8,7 @@ import { expect, launchElectronApp, openSettings, + openSettingsSection, openSources, openWorkspaceSection, resetMockServers, @@ -69,6 +70,7 @@ test.describe('Electron playlist backup round-trip', () => { }, exportPath); await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'backup'); const backupSection = app.mainWindow.locator('#backup'); await backupSection .getByRole('button', { name: 'Export', exact: true }) @@ -113,6 +115,7 @@ test.describe('Electron playlist backup round-trip', () => { // Import the exported file back through the settings flow; the // renderer opens a browser file chooser for it. await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'backup'); const fileChooserPromise = app.mainWindow.waitForEvent('filechooser'); await backupSection diff --git a/apps/electron-backend-e2e/src/downloads.e2e.ts b/apps/electron-backend-e2e/src/downloads.e2e.ts index bb3d2e47f..42ae1148b 100644 --- a/apps/electron-backend-e2e/src/downloads.e2e.ts +++ b/apps/electron-backend-e2e/src/downloads.e2e.ts @@ -123,6 +123,9 @@ async function selectDownloadCoverSize( ): Promise { await openSettings(page); await page.getByTestId(`cover-size-${size}`).click(); + // Cover size is staged like every other setting now — it reaches the + // store (and the document dataset) only once the save lands. + await saveSettings(page); await expect .poll(() => page.evaluate( @@ -130,7 +133,6 @@ async function selectDownloadCoverSize( ) ) .toBe(size); - await saveSettings(page); await openDownloadsPage(page); } diff --git a/apps/electron-backend-e2e/src/electron-test-fixtures.ts b/apps/electron-backend-e2e/src/electron-test-fixtures.ts index 818546505..2af39ac3e 100644 --- a/apps/electron-backend-e2e/src/electron-test-fixtures.ts +++ b/apps/electron-backend-e2e/src/electron-test-fixtures.ts @@ -983,10 +983,24 @@ export async function openSettings(page: Page): Promise { await expect(page.getByTestId('settings-container')).toBeVisible(); } +/** + * Settings render one section page at a time (`/workspace/settings/:section`), + * so a control can only be interacted with after its section page is open. + */ +export async function openSettingsSection( + page: Page, + sectionId: string +): Promise { + await page.getByTestId(`settings-section-${sectionId}`).click(); + await page.waitForURL(new RegExp(`/workspace/settings/${sectionId}$`)); +} + export async function enableRemoteControl( page: Page, port: number ): Promise { + await openSettingsSection(page, 'remote-control'); + const remoteControlCheckbox = page.locator( 'mat-checkbox[formcontrolname="remoteControl"] input[type="checkbox"]' ); @@ -1011,9 +1025,10 @@ export async function saveSettings(page: Page): Promise { // deterministic post-save state below. await saveButton.click({ noWaitAfter: true }); // `onSubmit()` calls `applyChangedSettings()` -> `markAsPristine()` once the - // settings write resolves, which disables the button. Awaiting that is a - // stronger, race-free confirmation that the save actually committed. - await expect(saveButton).toBeDisabled(); + // settings write resolves, which hides the whole unsaved-changes bar. + // Awaiting that is a stronger, race-free confirmation that the save + // actually committed. + await expect(saveButton).toBeHidden(); // Let the fire-and-forget `window.electron.updateSettings(...)` IPC flush to // the main process before callers may relaunch the app to assert persistence. await page.waitForTimeout(300); diff --git a/apps/electron-backend-e2e/src/epg.e2e.ts b/apps/electron-backend-e2e/src/epg.e2e.ts index 783daefdd..28c6f9a5c 100644 --- a/apps/electron-backend-e2e/src/epg.e2e.ts +++ b/apps/electron-backend-e2e/src/epg.e2e.ts @@ -9,6 +9,8 @@ import { launchElectronApp, openWorkspaceSection, openSettings, + openSettingsSection, + saveSettings, test, } from './electron-test-fixtures'; @@ -74,6 +76,7 @@ test.describe('Electron EPG', () => { try { await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'epg'); await app.mainWindow .getByRole('button', { name: 'Add EPG source' }) .click(); @@ -254,6 +257,7 @@ test.describe('Electron EPG', () => { ); await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'epg'); await app.mainWindow .getByRole('button', { name: 'Add EPG source' }) .click(); @@ -272,6 +276,11 @@ test.describe('Electron EPG', () => { }) .toBeGreaterThan(0); + // The added source is still only staged in the form — leaving + // settings without saving would surface the unsaved-changes + // dialog and block the navigation below. + await saveSettings(app.mainWindow); + await openWorkspaceSection(app.mainWindow, 'All channels'); const channelItem = channelItemByTitle( diff --git a/apps/electron-backend-e2e/src/remote-control.e2e.ts b/apps/electron-backend-e2e/src/remote-control.e2e.ts index 8807e2cc8..7fda35064 100644 --- a/apps/electron-backend-e2e/src/remote-control.e2e.ts +++ b/apps/electron-backend-e2e/src/remote-control.e2e.ts @@ -10,6 +10,7 @@ import { importM3uPlaylistFromNativeDialog, launchElectronApp, openSettings, + openSettingsSection, saveSettings, test, waitForM3uCatalog, @@ -47,6 +48,7 @@ test.describe('Electron Remote Control', () => { try { await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'playback'); await selectSettingsOption( app.mainWindow, 'select-video-player', diff --git a/apps/electron-backend-e2e/src/settings.e2e.ts b/apps/electron-backend-e2e/src/settings.e2e.ts index 7e974cfcf..fe28297c1 100644 --- a/apps/electron-backend-e2e/src/settings.e2e.ts +++ b/apps/electron-backend-e2e/src/settings.e2e.ts @@ -16,6 +16,7 @@ import { m3uFixturePath, openGlobalRecent, openSettings, + openSettingsSection, openWorkspaceSection, resetMockServers, restartElectronApp, @@ -49,6 +50,7 @@ test.describe('Electron Settings', () => { try { await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'about'); await expect(app.mainWindow.getByTestId('app-update-status')).toBeVisible(); await expect(app.mainWindow.getByTestId('app-update-check')).toBeVisible(); @@ -75,6 +77,7 @@ test.describe('Electron Settings', () => { await installExternalPlayerLaunchCapture(app); await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'playback'); await expect( app.mainWindow.getByTestId( 'external-player-double-click-setting' @@ -117,6 +120,7 @@ test.describe('Electron Settings', () => { }); await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'playback'); await expect(doubleClickSetting).toBeVisible(); await doubleClickCheckbox.check(); await saveSettings(app.mainWindow); @@ -229,6 +233,7 @@ test.describe('Electron Settings', () => { await firstLaunch.mainWindow .locator('[data-test-id="DARK_THEME"]') .click(); + await openSettingsSection(firstLaunch.mainWindow, 'playback'); await selectSettingsOption( firstLaunch.mainWindow, 'select-video-player', @@ -250,6 +255,7 @@ test.describe('Electron Settings', () => { ) .uncheck(); await enableRemoteControl(firstLaunch.mainWindow, 8877); + await openSettingsSection(firstLaunch.mainWindow, 'epg'); await firstLaunch.mainWindow .getByRole('button', { name: 'Add EPG source' }) .click(); @@ -273,6 +279,7 @@ test.describe('Electron Settings', () => { await expect( secondLaunch.mainWindow.locator('[data-test-id="DARK_THEME"]') ).toHaveAttribute('aria-checked', 'true'); + await openSettingsSection(secondLaunch.mainWindow, 'playback'); await expect( secondLaunch.mainWindow.getByTestId('select-video-player') ).toContainText(/HTML5/i); @@ -289,6 +296,7 @@ test.describe('Electron Settings', () => { 'mat-checkbox[formcontrolname="showExternalPlaybackBar"] input[type="checkbox"]' ) ).not.toBeChecked(); + await openSettingsSection(secondLaunch.mainWindow, 'remote-control'); await expect( secondLaunch.mainWindow.locator( 'mat-checkbox[formcontrolname="remoteControl"] input[type="checkbox"]' @@ -297,6 +305,7 @@ test.describe('Electron Settings', () => { await expect( secondLaunch.mainWindow.locator('#remoteControlPort') ).toHaveValue('8877'); + await openSettingsSection(secondLaunch.mainWindow, 'epg'); await expect( secondLaunch.mainWindow.locator('.epg-source-row input').first() ).toHaveValue(epgServer.resourceUrl); @@ -313,6 +322,7 @@ test.describe('Electron Settings', () => { try { await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'playback'); await selectSettingsOption( app.mainWindow, 'select-video-player', @@ -478,6 +488,7 @@ test.describe('Electron Settings', () => { try { await openSettings(firstLaunch.mainWindow); + await openSettingsSection(firstLaunch.mainWindow, 'epg'); const listToggle = firstLaunch.mainWindow.locator( '[data-test-id="epg-view-mode-list"]' ); @@ -493,6 +504,7 @@ test.describe('Electron Settings', () => { try { await openSettings(secondLaunch.mainWindow); + await openSettingsSection(secondLaunch.mainWindow, 'epg'); await expect( secondLaunch.mainWindow.locator( '[data-test-id="epg-view-mode-list"]' @@ -508,6 +520,7 @@ test.describe('Electron Settings', () => { try { await openSettings(firstLaunch.mainWindow); + await openSettingsSection(firstLaunch.mainWindow, 'dashboard'); await firstLaunch.mainWindow .locator( 'mat-checkbox[formcontrolname="showDashboard"] input[type="checkbox"]' diff --git a/apps/electron-backend-e2e/src/xtream-epg.e2e.ts b/apps/electron-backend-e2e/src/xtream-epg.e2e.ts index f65926039..d337b6503 100644 --- a/apps/electron-backend-e2e/src/xtream-epg.e2e.ts +++ b/apps/electron-backend-e2e/src/xtream-epg.e2e.ts @@ -9,6 +9,7 @@ import { goToDashboard, launchElectronApp, openSettings, + openSettingsSection, openWorkspaceSection, resetMockServers, saveSettings, @@ -302,6 +303,7 @@ test('@epg @xtream @electron renders the vertical list view when the setting is // Opt into the list view first (from the fresh workspace) so the portal // → Live TV → channel flow afterwards mirrors the timeline test exactly. await openSettings(app.mainWindow); + await openSettingsSection(app.mainWindow, 'epg'); await app.mainWindow .locator('[data-test-id="epg-view-mode-list"]') .click(); diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change app language.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change app language.png new file mode 100644 index 000000000..9b09f0443 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change app language.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change app theme.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change app theme.png new file mode 100644 index 000000000..ae5559a5e Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change app theme.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change video player.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change video player.png new file mode 100644 index 000000000..9e4c06376 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Change video player.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Check settings page.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Check settings page.png new file mode 100644 index 000000000..34a05696c Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Check settings page.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Deep links open one section page and unknown sections redirect.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Deep links open one section page and unknown sections redirect.png new file mode 100644 index 000000000..18f7992d2 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Deep links open one section page and unknown sections redirect.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Enable shared web player controls.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Enable shared web player controls.png new file mode 100644 index 000000000..8f2faf1c4 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Enable shared web player controls.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Leaving with unsaved edits asks for confirmation.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Leaving with unsaved edits asks for confirmation.png new file mode 100644 index 000000000..b63a79e02 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Leaving with unsaved edits asks for confirmation.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Save-and-leave persists the staged edit.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Save-and-leave persists the staged edit.png new file mode 100644 index 000000000..06cb9eb42 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Save-and-leave persists the staged edit.png differ diff --git a/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Unsaved bar survives section switches and discard reverts.png b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Unsaved bar survives section switches and discard reverts.png new file mode 100644 index 000000000..9f075ac73 Binary files /dev/null and b/apps/web-e2e/dist/.playwright/apps/web-e2e/screenshots/settings/@settings @web Unsaved bar survives section switches and discard reverts.png differ diff --git a/apps/web-e2e/src/playback-recommendations.e2e.ts b/apps/web-e2e/src/playback-recommendations.e2e.ts index dcd73cbc1..301e49216 100644 --- a/apps/web-e2e/src/playback-recommendations.e2e.ts +++ b/apps/web-e2e/src/playback-recommendations.e2e.ts @@ -64,10 +64,16 @@ async function servePlaybackFixtures(page: Page): Promise { async function openSettings(page: Page): Promise { await page.getByRole('link', { name: 'Open settings' }).click(); - await page.waitForURL(/\/workspace\/settings$/); + // The bare settings URL redirects to the default section page; the + // player select lives on the playback section page. + await page.waitForURL(/\/workspace\/settings\/general$/); await expect( page.getByRole('button', { name: 'Back', exact: true }) ).toBeVisible(); + await page + .locator('[data-test-id="settings-section-playback"]') + .click(); + await page.waitForURL(/\/workspace\/settings\/playback$/); } async function selectAndSaveHtml5(page: Page): Promise { @@ -79,7 +85,8 @@ async function selectAndSaveHtml5(page: Page): Promise { const saveButton = page.getByRole('button', { name: 'Save changes' }); await saveButton.click(); - await expect(saveButton).toBeDisabled(); + // A successful save removes the unsaved-changes bar with its button. + await expect(saveButton).toBeHidden(); } async function importFatalHlsPlaylist(page: Page): Promise { @@ -131,7 +138,7 @@ test('@web @m3u @playback temporarily switches to the recommended player', async await openSettings(page); await page.reload(); - await expect(page).toHaveURL(/\/workspace\/settings$/); + await expect(page).toHaveURL(/\/workspace\/settings\/playback$/); const persistedPlayerSelect = page.locator( '[data-test-id="select-video-player"]' ); diff --git a/apps/web-e2e/src/settings.e2e.ts b/apps/web-e2e/src/settings.e2e.ts index 113fe8278..1589335fc 100644 --- a/apps/web-e2e/src/settings.e2e.ts +++ b/apps/web-e2e/src/settings.e2e.ts @@ -4,16 +4,25 @@ import { expect, test } from './fixtures'; async function openSettings(page: Page) { await page.locator('a[href$="/workspace/settings"]').click(); - await page.waitForURL(/\/workspace\/settings$/); + // The bare settings URL redirects to the default section page. + await page.waitForURL(/\/workspace\/settings\/general$/); await expect(page.locator('.settings-container')).toBeVisible(); await expect(page.locator('.settings-back-button')).toBeVisible(); } +/** Settings render one section page at a time — open it via the rail. */ +async function openSettingsSection(page: Page, sectionId: string) { + await page.locator(`[data-test-id="settings-section-${sectionId}"]`).click(); + await page.waitForURL(new RegExp(`/workspace/settings/${sectionId}$`)); +} + async function saveSettings(page: Page) { const saveButton = page.locator('[data-test-id="save-settings"]'); await saveButton.click(); - await expect(saveButton).toBeDisabled(); + // A successful save marks the form pristine, which removes the whole + // unsaved-changes bar together with the save button. + await expect(saveButton).toBeHidden(); } test.describe('Settings', () => { @@ -30,6 +39,7 @@ test.describe('Settings', () => { test('@settings @web Change video player', async ({ page }) => { await openSettings(page); + await openSettingsSection(page, 'playback'); const playerSelect = page.locator('[data-test-id="select-video-player"]'); @@ -42,6 +52,7 @@ test.describe('Settings', () => { await saveSettings(page); await page.reload(); await openSettings(page); + await openSettingsSection(page, 'playback'); await expect(playerSelect).toContainText( /HTML5/i @@ -52,6 +63,7 @@ test.describe('Settings', () => { page, }) => { await openSettings(page); + await openSettingsSection(page, 'playback'); const setting = page.locator( '[data-test-id="web-player-shared-controls-setting"]' @@ -64,6 +76,7 @@ test.describe('Settings', () => { await saveSettings(page); await page.reload(); await openSettings(page); + await openSettingsSection(page, 'playback'); await expect(checkbox).toBeChecked(); }); @@ -93,6 +106,134 @@ test.describe('Settings', () => { ).toHaveAttribute('aria-checked', 'true'); }); + test('@settings @web Deep links open one section page and unknown sections redirect', async ({ + page, + }) => { + await page.goto('/workspace/settings/playback'); + + // Only the routed section renders — the playback controls are + // there, the general ones are not. + await expect( + page.locator('[data-test-id="select-video-player"]') + ).toBeVisible(); + await expect( + page.locator('[data-test-id="select-language"]') + ).toHaveCount(0); + + // A stale or mistyped section URL is rewritten to the default page. + await page.goto('/workspace/settings/nonsense'); + await page.waitForURL(/\/workspace\/settings\/general$/); + await expect( + page.locator('[data-test-id="select-language"]') + ).toBeVisible(); + }); + + test('@settings @web Unsaved bar survives section switches and discard reverts', async ({ + page, + }) => { + await openSettings(page); + + const unsavedBar = page.locator( + '[data-test-id="settings-unsaved-bar"]' + ); + await expect(unsavedBar).toBeHidden(); + + const themeGroup = page.locator( + '[data-test-id="select-theme"][role="radiogroup"]' + ); + await themeGroup + .getByRole('radio', { name: 'Dark', exact: true }) + .click(); + await expect(unsavedBar).toBeVisible(); + + // The staged edit belongs to the page, not the section — moving to + // another section page must keep the bar (and the pending change). + await openSettingsSection(page, 'playback'); + await expect(unsavedBar).toBeVisible(); + + await page.locator('[data-test-id="discard-settings"]').click(); + await expect(unsavedBar).toBeHidden(); + + await openSettingsSection(page, 'general'); + await expect( + themeGroup.getByRole('radio', { name: 'System', exact: true }) + ).toHaveAttribute('aria-checked', 'true'); + }); + + test('@settings @web Leaving with unsaved edits asks for confirmation', async ({ + page, + }) => { + await openSettings(page); + + const themeGroup = page.locator( + '[data-test-id="select-theme"][role="radiogroup"]' + ); + await themeGroup + .getByRole('radio', { name: 'Dark', exact: true }) + .click(); + + // Trying to leave the settings area surfaces the dialog. + await page + .getByRole('navigation') + .getByRole('link', { name: 'Dashboard', exact: true }) + .click(); + const dialog = page.getByRole('dialog'); + await expect(dialog).toBeVisible(); + + // Keep editing: navigation is cancelled, the edit survives. + await dialog.locator('[data-test-id="unsaved-dialog-stay"]').click(); + await expect(dialog).toBeHidden(); + await expect(page).toHaveURL(/\/workspace\/settings\/general$/); + await expect( + page.locator('[data-test-id="settings-unsaved-bar"]') + ).toBeVisible(); + + // Leave without saving: the staged edit is discarded. + await page + .getByRole('navigation') + .getByRole('link', { name: 'Dashboard', exact: true }) + .click(); + await page + .getByRole('dialog') + .locator('[data-test-id="unsaved-dialog-discard"]') + .click(); + await page.waitForURL(/\/workspace\/dashboard$/); + + await openSettings(page); + await expect( + themeGroup.getByRole('radio', { name: 'System', exact: true }) + ).toHaveAttribute('aria-checked', 'true'); + }); + + test('@settings @web Save-and-leave persists the staged edit', async ({ + page, + }) => { + await openSettings(page); + + const themeGroup = page.locator( + '[data-test-id="select-theme"][role="radiogroup"]' + ); + await themeGroup + .getByRole('radio', { name: 'Dark', exact: true }) + .click(); + + await page + .getByRole('navigation') + .getByRole('link', { name: 'Dashboard', exact: true }) + .click(); + await page + .getByRole('dialog') + .locator('[data-test-id="unsaved-dialog-save"]') + .click(); + await page.waitForURL(/\/workspace\/dashboard$/); + + await page.reload(); + await openSettings(page); + await expect( + themeGroup.getByRole('radio', { name: 'Dark', exact: true }) + ).toHaveAttribute('aria-checked', 'true'); + }); + test('@settings @web Change app language', async ({ page }) => { await openSettings(page); const languageSelect = page.locator('[data-test-id="select-language"]'); diff --git a/apps/web/src/app/app.config.ts b/apps/web/src/app/app.config.ts index 19fff0c3a..d6835ea71 100644 --- a/apps/web/src/app/app.config.ts +++ b/apps/web/src/app/app.config.ts @@ -26,7 +26,6 @@ import { PORTAL_EXTERNAL_PLAYBACK, PORTAL_PLAYER, } from '@iptvnator/portal/shared/util'; -import { PLAYLIST_PLAYER_ACTIONS } from '@iptvnator/playlist/shared/util'; import { STALKER_PLAYLIST_CONNECTION_EDITOR } from '@iptvnator/playlist/shared/ui'; import { provideXtreamDataSource } from '@iptvnator/portal/xtream/data-access'; import { DataService } from '@iptvnator/services'; @@ -36,10 +35,6 @@ import { routes } from './app.routes'; import { ElectronService } from './services/electron.service'; import { ExternalPlaybackService } from './services/external-playback.service'; import { PlayerService } from './services/player.service'; -import { - AppPortalNavigationActionsService, - providePortalNavigationActions, -} from './services/portal-navigation-actions.service'; import { providePortalPlaybackPositions } from './services/portal-playback-positions.service'; import { PwaService } from './services/pwa.service'; import { shouldEnableServiceWorker } from './services/runtime-config'; @@ -149,11 +144,6 @@ export const appConfig: ApplicationConfig = { useExisting: ExternalPlaybackService, }, ...providePortalPlaybackPositions(), - ...providePortalNavigationActions(), - { - provide: PLAYLIST_PLAYER_ACTIONS, - useExisting: AppPortalNavigationActionsService, - }, { provide: STALKER_PLAYLIST_CONNECTION_EDITOR, useExisting: AppStalkerPlaylistConnectionEditorService, diff --git a/apps/web/src/app/app.routes.ts b/apps/web/src/app/app.routes.ts index 0fd1f60c6..565bfd3eb 100644 --- a/apps/web/src/app/app.routes.ts +++ b/apps/web/src/app/app.routes.ts @@ -2,6 +2,7 @@ import { inject } from '@angular/core'; import { Router, Routes } from '@angular/router'; import { RuntimeCapabilitiesService, SettingsStore } from '@iptvnator/services'; import { WorkspaceStartupPreferencesService } from '@iptvnator/workspace/shell/util'; +import { settingsUnsavedChangesGuard } from './settings/settings-unsaved-changes.guard'; const settingsReadyResolver = () => inject(SettingsStore).loadSettings(); @@ -141,10 +142,27 @@ export const routes: Routes = [ }, { path: 'settings', - loadComponent: () => - import('./settings/settings.component').then( - (c) => c.SettingsComponent - ), + children: [ + { + path: '', + pathMatch: 'full', + redirectTo: 'general', + }, + { + // One routed component for every section: the same + // instance survives :section param changes (default + // route reuse), so the settings form — and its dirty + // state — persists while the user moves between + // section pages. The guard only intercepts leaving + // the settings area with unsaved edits. + path: ':section', + canDeactivate: [settingsUnsavedChangesGuard], + loadComponent: () => + import('./settings/settings.component').then( + (c) => c.SettingsComponent + ), + }, + ], }, ], }, diff --git a/apps/web/src/app/services/portal-navigation-actions.service.ts b/apps/web/src/app/services/portal-navigation-actions.service.ts deleted file mode 100644 index 863185e71..000000000 --- a/apps/web/src/app/services/portal-navigation-actions.service.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { inject, Injectable, Provider } from '@angular/core'; -import { MatDialog } from '@angular/material/dialog'; -import { PlaylistInfoComponent } from '@iptvnator/playlist/shared/ui'; -import { - PORTAL_NAVIGATION_ACTIONS, - PortalNavigationActions, -} from '@iptvnator/portal/shared/util'; -import { XtreamStore } from '@iptvnator/portal/xtream/data-access'; -import { Playlist } from '@iptvnator/shared/interfaces'; -import { SettingsComponent } from '../settings/settings.component'; - -@Injectable({ providedIn: 'root' }) -export class AppPortalNavigationActionsService - implements PortalNavigationActions -{ - private readonly dialog = inject(MatDialog); - private readonly xtreamStore = inject(XtreamStore); - - openAccountInfo(): void { - const data = { - vodStreamsCount: this.xtreamStore.vodStreams().length, - liveStreamsCount: this.xtreamStore.liveStreams().length, - seriesCount: this.xtreamStore.serialStreams().length, - }; - - void import('@iptvnator/portal/xtream/feature').then( - ({ AccountInfoComponent }) => { - this.dialog.open(AccountInfoComponent, { - width: '80%', - maxWidth: '1200px', - maxHeight: '90vh', - data, - }); - } - ); - } - - openPlaylistInfo(playlist: Playlist | null | undefined): void { - this.dialog.open(PlaylistInfoComponent, { - data: playlist ?? null, - }); - } - - openSettings(): void { - this.dialog.open(SettingsComponent, { - width: '1200px', - maxWidth: '96vw', - maxHeight: '92vh', - data: { - isDialog: true, - }, - }); - } -} - -export function providePortalNavigationActions(): Provider[] { - return [ - AppPortalNavigationActionsService, - { - provide: PORTAL_NAVIGATION_ACTIONS, - useExisting: AppPortalNavigationActionsService, - }, - ]; -} diff --git a/apps/web/src/app/settings/settings-about-section.component.html b/apps/web/src/app/settings/settings-about-section.component.html index c5ab3ddaf..34881ab6d 100644 --- a/apps/web/src/app/settings/settings-about-section.component.html +++ b/apps/web/src/app/settings/settings-about-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-about-section.component.spec.ts b/apps/web/src/app/settings/settings-about-section.component.spec.ts index ce5c87265..689a93f38 100644 --- a/apps/web/src/app/settings/settings-about-section.component.spec.ts +++ b/apps/web/src/app/settings/settings-about-section.component.spec.ts @@ -16,7 +16,6 @@ function configureComponent( fixture: ComponentFixture, status: ElectronBridgeAppUpdateStatus ) { - fixture.componentRef.setInput('activeSection', 'about'); fixture.componentRef.setInput('isDesktop', true); fixture.componentRef.setInput('version', '0.22.0'); fixture.componentRef.setInput('updateMessage', ''); @@ -145,7 +144,6 @@ describe('SettingsAboutSectionComponent version display', () => { }).compileComponents(); fixture = TestBed.createComponent(SettingsAboutSectionComponent); - fixture.componentRef.setInput('activeSection', 'about'); fixture.componentRef.setInput('version', '0.23.0'); }); diff --git a/apps/web/src/app/settings/settings-about-section.component.ts b/apps/web/src/app/settings/settings-about-section.component.ts index eb02ce4e7..849803476 100644 --- a/apps/web/src/app/settings/settings-about-section.component.ts +++ b/apps/web/src/app/settings/settings-about-section.component.ts @@ -24,7 +24,6 @@ import { ], }) export class SettingsAboutSectionComponent { - readonly activeSection = input.required(); readonly isDesktop = input(false); readonly version = input(); readonly buildCommit = input(); diff --git a/apps/web/src/app/settings/settings-backup-section.component.html b/apps/web/src/app/settings/settings-backup-section.component.html index 0a9f7189d..bae147754 100644 --- a/apps/web/src/app/settings/settings-backup-section.component.html +++ b/apps/web/src/app/settings/settings-backup-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-backup-section.component.ts b/apps/web/src/app/settings/settings-backup-section.component.ts index 9cfb5af6c..5b092ca8b 100644 --- a/apps/web/src/app/settings/settings-backup-section.component.ts +++ b/apps/web/src/app/settings/settings-backup-section.component.ts @@ -17,7 +17,6 @@ import { TranslateModule } from '@ngx-translate/core'; styles: [':host { display: contents; }'], }) export class SettingsBackupSectionComponent { - readonly activeSection = input.required(); readonly isPwa = input(false); readonly isRemovingAllPlaylists = input(false); readonly isExportingData = input(false); diff --git a/apps/web/src/app/settings/settings-dashboard-section.component.html b/apps/web/src/app/settings/settings-dashboard-section.component.html index 8e2db7c31..1b35089af 100644 --- a/apps/web/src/app/settings/settings-dashboard-section.component.html +++ b/apps/web/src/app/settings/settings-dashboard-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-dashboard-section.component.ts b/apps/web/src/app/settings/settings-dashboard-section.component.ts index 11b544b4d..bba422dea 100644 --- a/apps/web/src/app/settings/settings-dashboard-section.component.ts +++ b/apps/web/src/app/settings/settings-dashboard-section.component.ts @@ -20,5 +20,4 @@ import { TranslateModule } from '@ngx-translate/core'; }) export class SettingsDashboardSectionComponent { readonly form = input.required(); - readonly activeSection = input.required(); } diff --git a/apps/web/src/app/settings/settings-epg-section.component.html b/apps/web/src/app/settings/settings-epg-section.component.html index d4153604e..43e3b3bdc 100644 --- a/apps/web/src/app/settings/settings-epg-section.component.html +++ b/apps/web/src/app/settings/settings-epg-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-epg-section.component.ts b/apps/web/src/app/settings/settings-epg-section.component.ts index 4fbd8aea0..38c415687 100644 --- a/apps/web/src/app/settings/settings-epg-section.component.ts +++ b/apps/web/src/app/settings/settings-epg-section.component.ts @@ -32,7 +32,6 @@ import { EpgViewModeOption } from './settings.models'; }) export class SettingsEpgSectionComponent { readonly form = input.required(); - readonly activeSection = input.required(); readonly epgUrl = input.required(); readonly isClearingEpgData = input(false); readonly epgViewModeOptions = input.required(); diff --git a/apps/web/src/app/settings/settings-form.facade.ts b/apps/web/src/app/settings/settings-form.facade.ts index 445b8e215..c64e46e3b 100644 --- a/apps/web/src/app/settings/settings-form.facade.ts +++ b/apps/web/src/app/settings/settings-form.facade.ts @@ -99,15 +99,18 @@ export class SettingsFormFacade { this.settingsService.changeTheme(theme); } + /** + * Staged like every other control — the write happens on Save. These two + * used to persist eagerly, which made Discard a lie: `hydrateFromStore()` + * would faithfully reload the just-persisted edit and the unsaved bar + * disappeared without anything being reverted. + */ selectCoverSize(coverSize: CoverSize): void { if (this.form.value.coverSize === coverSize) { return; } this.patchAndMarkDirty({ coverSize }, 'coverSize'); - this.settingsStore.updateSettings({ coverSize }).catch(() => { - this.settingsSnackbar.storageFailure('save'); - }); } selectEpgViewMode(epgViewMode: EpgViewMode): void { @@ -116,9 +119,6 @@ export class SettingsFormFacade { } this.patchAndMarkDirty({ epgViewMode }, 'epgViewMode'); - this.settingsStore.updateSettings({ epgViewMode }).catch(() => { - this.settingsSnackbar.storageFailure('save'); - }); } setRecordingFolder(recordingFolder: string): void { diff --git a/apps/web/src/app/settings/settings-general-section.component.html b/apps/web/src/app/settings/settings-general-section.component.html index dda4b45b5..84d8ba2f5 100644 --- a/apps/web/src/app/settings/settings-general-section.component.html +++ b/apps/web/src/app/settings/settings-general-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-general-section.component.ts b/apps/web/src/app/settings/settings-general-section.component.ts index 4125376dc..86dace21f 100644 --- a/apps/web/src/app/settings/settings-general-section.component.ts +++ b/apps/web/src/app/settings/settings-general-section.component.ts @@ -30,7 +30,6 @@ import { }) export class SettingsGeneralSectionComponent { readonly form = input.required(); - readonly activeSection = input.required(); readonly languageEnum = input.required(); readonly themeOptions = input.required(); readonly coverSizeOptions = input.required(); diff --git a/apps/web/src/app/settings/settings-options.spec.ts b/apps/web/src/app/settings/settings-options.spec.ts index 545c6b918..6b40049b3 100644 --- a/apps/web/src/app/settings/settings-options.spec.ts +++ b/apps/web/src/app/settings/settings-options.spec.ts @@ -1,81 +1,41 @@ -import { readFileSync, readdirSync } from 'fs'; +import { readFileSync } from 'fs'; import { resolve } from 'path'; import { buildSettingsSectionNavItems } from './settings-options'; /** - * Every nav-item id must match the `id="..."` attribute on its - * corresponding section component template, otherwise clicking the nav - * link silently no-ops (the scroll directive runs `document.getElementById` - * and falls through when no element is found). + * Every nav-item id must match a `@case ('...')` label in the settings page + * template (or the `@default` general section), otherwise clicking the nav + * link routes to `/workspace/settings/:id` and renders the fallback general + * page instead of the intended section. * - * This bug bit the Remote section once already — its nav id was set to - * the Nx library name (`@iptvnator/ui/remote-control`) instead of the - * template's `id="remote-control"`. The guard below catches future - * rename/copy-paste regressions before they ship. + * The id coupling bit the Remote section once already in the scroll-anchor + * era — its nav id was set to the Nx library name + * (`@iptvnator/ui/remote-control`) instead of `remote-control`. The guard + * below catches future rename/copy-paste regressions before they ship. */ describe('buildSettingsSectionNavItems', () => { // Anchor on the Nx workspace root (Jest runs from there); avoids // depending on __dirname which isn't defined under the project's // ESM Jest preset. - const settingsDir = resolve( - process.cwd(), - 'apps/web/src/app/settings' - ); + const settingsDir = resolve(process.cwd(), 'apps/web/src/app/settings'); - function collectSectionTemplateIds(): Set { - const ids = new Set(); - for (const fileName of readdirSync(settingsDir)) { - if (!/^settings-.+-section\.component\.html$/.test(fileName)) { - continue; - } - const html = readFileSync( - resolve(settingsDir, fileName), - 'utf-8' - ); - // Match the FIRST `id="…"` on the
root only — - // descendant elements (form controls, anchors) also use id= - // attributes and would pollute the set. - const rootMatch = /]*\sid="([^"]+)"/i.exec(html); - if (rootMatch) { - ids.add(rootMatch[1]); - } - } - return ids; - } - - function collectSettingsComponentSectionOrder(): string[] { + /** Section ids the page template can render: @case labels + @default. */ + function collectRenderableSectionIds(): Set { const html = readFileSync( resolve(settingsDir, 'settings.component.html'), 'utf-8' ); - const idsByComponent = new Map(); - - for (const fileName of readdirSync(settingsDir)) { - const componentMatch = - /^settings-(.+)-section\.component\.html$/.exec(fileName); - if (!componentMatch) { - continue; - } - const sectionHtml = readFileSync( - resolve(settingsDir, fileName), - 'utf-8' - ); - const rootMatch = /]*\sid="([^"]+)"/i.exec( - sectionHtml - ); - if (rootMatch) { - idsByComponent.set( - `app-settings-${componentMatch[1]}-section`, - rootMatch[1] - ); - } + const ids = new Set( + Array.from( + html.matchAll(/@case \('([a-z-]+)'\)/g), + (match) => match[1] + ) + ); + if (/@default\s*\{\s* idsByComponent.get(match[0].slice(1)) - ).filter((id): id is string => Boolean(id)); + return ids; } it('exposes feature-specific items only when their runtime capabilities are supported', () => { @@ -100,28 +60,34 @@ describe('buildSettingsSectionNavItems', () => { ).toBe(false); }); - it('every nav id matches an existing section template id (regression: remote-control nav no longer maps to the Nx lib name)', () => { + it('every nav id renders a section page in the settings template', () => { const navIds = new Set( buildSettingsSectionNavItems({ supportsEpg: true, supportsRemoteControl: true, }).map((item) => item.id) ); - const templateIds = collectSectionTemplateIds(); + const renderableIds = collectRenderableSectionIds(); - // Every nav id must exist as a section root id. - const orphans = [...navIds].filter((id) => !templateIds.has(id)); + // A nav id without a template case silently falls back to the + // general page. + const orphans = [...navIds].filter((id) => !renderableIds.has(id)); expect(orphans).toEqual([]); - // And every section template id must be reachable from the nav - // (catches the opposite drift — a new section added without a nav - // entry would never get scrolled to). - const unreachable = [...templateIds].filter((id) => !navIds.has(id)); + // And every template case must be reachable from the nav (catches + // the opposite drift — a new section page added without a nav entry + // could never be opened). + const unreachable = [...renderableIds].filter((id) => !navIds.has(id)); expect(unreachable).toEqual([]); }); - it('keeps Dashboard below EPG in both the settings rail and content order', () => { - const expectedOrder = [ + it('keeps the settings rail in the expected order', () => { + expect( + buildSettingsSectionNavItems({ + supportsEpg: true, + supportsRemoteControl: true, + }).map((item) => item.id) + ).toEqual([ 'general', 'playback', 'epg', @@ -131,14 +97,6 @@ describe('buildSettingsSectionNavItems', () => { 'backup', 'reset', 'about', - ]; - - expect( - buildSettingsSectionNavItems({ - supportsEpg: true, - supportsRemoteControl: true, - }).map((item) => item.id) - ).toEqual(expectedOrder); - expect(collectSettingsComponentSectionOrder()).toEqual(expectedOrder); + ]); }); }); diff --git a/apps/web/src/app/settings/settings-playback-section.auto-failover.spec.ts b/apps/web/src/app/settings/settings-playback-section.auto-failover.spec.ts index 82cbdc36e..a42f7c317 100644 --- a/apps/web/src/app/settings/settings-playback-section.auto-failover.spec.ts +++ b/apps/web/src/app/settings/settings-playback-section.auto-failover.spec.ts @@ -38,7 +38,6 @@ describe('SettingsPlaybackSectionComponent — VOD auto-failover', () => { }).compileComponents(); fixture = TestBed.createComponent(SettingsPlaybackSectionComponent); - fixture.componentRef.setInput('activeSection', 'playback'); fixture.componentRef.setInput('players', []); fixture.componentRef.setInput('streamFormatEnum', StreamFormat); }); diff --git a/apps/web/src/app/settings/settings-playback-section.component.html b/apps/web/src/app/settings/settings-playback-section.component.html index 453179207..243ebc1bf 100644 --- a/apps/web/src/app/settings/settings-playback-section.component.html +++ b/apps/web/src/app/settings/settings-playback-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-playback-section.component.spec.ts b/apps/web/src/app/settings/settings-playback-section.component.spec.ts index 8ad079ce4..4fdafeb9e 100644 --- a/apps/web/src/app/settings/settings-playback-section.component.spec.ts +++ b/apps/web/src/app/settings/settings-playback-section.component.spec.ts @@ -51,7 +51,6 @@ describe('SettingsPlaybackSectionComponent', () => { fixture = TestBed.createComponent(SettingsPlaybackSectionComponent); fixture.componentRef.setInput('form', createForm()); - fixture.componentRef.setInput('activeSection', 'playback'); fixture.componentRef.setInput('players', [ { id: VideoPlayer.VideoJs, diff --git a/apps/web/src/app/settings/settings-playback-section.component.ts b/apps/web/src/app/settings/settings-playback-section.component.ts index 52293eb2a..83ea439d0 100644 --- a/apps/web/src/app/settings/settings-playback-section.component.ts +++ b/apps/web/src/app/settings/settings-playback-section.component.ts @@ -45,7 +45,6 @@ export class SettingsPlaybackSectionComponent { ].join('\n'); readonly form = input.required(); - readonly activeSection = input.required(); readonly players = input.required(); readonly streamFormatEnum = input.required(); readonly isDesktop = input(false); diff --git a/apps/web/src/app/settings/settings-remote-control-section.component.html b/apps/web/src/app/settings/settings-remote-control-section.component.html index c49c44954..510c81ea4 100644 --- a/apps/web/src/app/settings/settings-remote-control-section.component.html +++ b/apps/web/src/app/settings/settings-remote-control-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-remote-control-section.component.ts b/apps/web/src/app/settings/settings-remote-control-section.component.ts index 5d243e36a..0d4d6d51d 100644 --- a/apps/web/src/app/settings/settings-remote-control-section.component.ts +++ b/apps/web/src/app/settings/settings-remote-control-section.component.ts @@ -28,7 +28,6 @@ import { QRCodeComponent } from 'angularx-qrcode'; }) export class SettingsRemoteControlSectionComponent { readonly form = input.required(); - readonly activeSection = input.required(); readonly localIpAddresses = input.required(); readonly visibleQrCodeIp = input(null); diff --git a/apps/web/src/app/settings/settings-reset-section.component.html b/apps/web/src/app/settings/settings-reset-section.component.html index 608dee007..18b4f441e 100644 --- a/apps/web/src/app/settings/settings-reset-section.component.html +++ b/apps/web/src/app/settings/settings-reset-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-reset-section.component.ts b/apps/web/src/app/settings/settings-reset-section.component.ts index 7e42e0f40..f9376a28b 100644 --- a/apps/web/src/app/settings/settings-reset-section.component.ts +++ b/apps/web/src/app/settings/settings-reset-section.component.ts @@ -18,7 +18,6 @@ import { SettingsPlaylistDeleteSummary } from './settings.models'; styles: [':host { display: contents; }'], }) export class SettingsResetSectionComponent { - readonly activeSection = input.required(); readonly isRemovingAllPlaylists = input(false); readonly canRemoveAllPlaylists = input(false); readonly playlistDeleteSummary = diff --git a/apps/web/src/app/settings/settings-section-scroll.directive.spec.ts b/apps/web/src/app/settings/settings-section-scroll.directive.spec.ts deleted file mode 100644 index f2c402094..000000000 --- a/apps/web/src/app/settings/settings-section-scroll.directive.spec.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; -import { By } from '@angular/platform-browser'; -import { EpgRuntimeBridgeService } from '@iptvnator/epg/data-access'; -import { SettingsContextService } from '@iptvnator/workspace/shell/util'; -import { SettingsComponent } from './settings.component'; -import { SettingsSectionScrollDirective } from './settings-section-scroll.directive'; -import { - configureSettingsComponentTestBed, - createElectronStub, - createEpgBridgeStub, - stubSettingsSideEffects, -} from './test-stubs/settings-test-harness.stub'; - -interface SettingsSectionScrollDirectiveTestApi { - getScrollRoot(): HTMLElement | null; -} - -/** - * The directive only makes sense against a real settings page, so this is an - * integration spec: it renders the component and drives the section - * navigation the workspace shell would trigger. - */ -describe('SettingsSectionScrollDirective', () => { - let fixture: ComponentFixture; - let epgBridge: Partial; - const originalElectron = window.electron; - - beforeEach(waitForAsync(() => { - epgBridge = createEpgBridgeStub(); - configureSettingsComponentTestBed(epgBridge); - })); - - beforeEach(() => { - window.electron = createElectronStub(); - }); - - afterEach(() => { - window.electron = originalElectron; - }); - - it('should scroll the selected navigation target within the workspace viewport', async () => { - jest.useFakeTimers(); - - try { - fixture = TestBed.createComponent(SettingsComponent); - const component = fixture.componentInstance; - const settingsContext = TestBed.inject(SettingsContextService); - const originalGetElementById = - document.getElementById.bind(document); - const scrollTo = jest.fn(); - const scrollRoot = { - scrollTop: 96, - clientHeight: 885, - scrollHeight: 2469, - getBoundingClientRect: () => - ({ - top: 56, - }) as DOMRect, - scrollTo, - } as unknown as HTMLElement; - - stubSettingsSideEffects(component); - fixture.detectChanges(); - const scrollDirective = fixture.debugElement - .query(By.directive(SettingsSectionScrollDirective)) - .injector.get(SettingsSectionScrollDirective); - jest.spyOn( - scrollDirective as unknown as SettingsSectionScrollDirectiveTestApi, - 'getScrollRoot' - ).mockReturnValue(scrollRoot); - - const getElementByIdSpy = jest - .spyOn(document, 'getElementById') - .mockImplementation((id: string) => { - if (id === 'about') { - return { - getBoundingClientRect: () => - ({ - top: 2050, - height: 159, - }) as DOMRect, - } as HTMLElement; - } - - return originalGetElementById(id); - }); - - await fixture.whenStable(); - fixture.detectChanges(); - settingsContext.navigateToSection('about'); - fixture.detectChanges(); - - expect(getElementByIdSpy).toHaveBeenCalledWith('about'); - expect(scrollTo).toHaveBeenCalledWith({ - behavior: 'smooth', - top: 1488, - }); - expect(settingsContext.pendingScrollTarget()).toBe('about'); - - jest.advanceTimersByTime(600); - - expect(settingsContext.pendingScrollTarget()).toBeNull(); - } finally { - jest.useRealTimers(); - } - }); -}); diff --git a/apps/web/src/app/settings/settings-section-scroll.directive.ts b/apps/web/src/app/settings/settings-section-scroll.directive.ts deleted file mode 100644 index d2207a61d..000000000 --- a/apps/web/src/app/settings/settings-section-scroll.directive.ts +++ /dev/null @@ -1,241 +0,0 @@ -import { - AfterViewInit, - Directive, - effect, - ElementRef, - inject, - Injector, - OnDestroy, -} from '@angular/core'; -import { SettingsContextService } from '@iptvnator/workspace/shell/util'; -import { ObservedSettingsSection } from './settings.models'; - -@Directive({ - selector: '[appSettingsSectionScroll]', -}) -export class SettingsSectionScrollDirective - implements AfterViewInit, OnDestroy -{ - private static readonly SECTION_SCROLL_TOP_GUTTER = 112; - private static readonly SECTION_SCROLL_BOTTOM_GUTTER = 124; - private static readonly PENDING_SCROLL_CLEAR_DELAY_MS = 600; - - private readonly elementRef = inject(ElementRef); - private readonly injector = inject(Injector); - private readonly settingsCtx = inject(SettingsContextService); - - private sectionObserver?: IntersectionObserver; - private pendingScrollClearTimer: ReturnType< - typeof window.setTimeout - > | null = null; - private pendingScrollClearRoot: HTMLElement | null = null; - private pendingScrollEndListener: (() => void) | null = null; - - constructor() { - effect( - () => { - const sectionId = this.settingsCtx.pendingScrollTarget(); - if (!sectionId || typeof document === 'undefined') { - return; - } - - const scrollRoot = this.scrollToSection(sectionId); - this.schedulePendingScrollTargetClear(scrollRoot); - }, - { injector: this.injector } - ); - - // The previous active-section change handler ran a 260ms box-shadow - // animation (inset 1px ring + soft glow) on whichever section - // became active during scroll. With the new flat layout (no card - // chrome, no static active ring) that pulse drew a brief 1px - // border around each block as the user scrolled past — what the - // user reported as "short border kind of highlight around blocks". - // The rail's left active state already announces the current - // section, so the inline pulse is redundant. Removed entirely. - } - - ngAfterViewInit(): void { - requestAnimationFrame(() => this.setupSectionObserver()); - } - - ngOnDestroy(): void { - this.cancelPendingScrollTargetClear(); - this.sectionObserver?.disconnect(); - } - - private setupSectionObserver(): void { - if (typeof IntersectionObserver === 'undefined') { - return; - } - - const scrollRoot = this.getScrollRoot(); - const contentSections = Array.from( - this.elementRef.nativeElement.querySelectorAll( - '.settings-group[id]' - ) - ) as HTMLElement[]; - const sections: ObservedSettingsSection[] = contentSections.map( - (section) => ({ - id: section.id, - element: section, - }) - ); - - if (sections.length === 0) { - return; - } - - this.sectionObserver?.disconnect(); - this.sectionObserver = new IntersectionObserver( - () => { - if (this.settingsCtx.pendingScrollTarget()) { - return; - } - - const activeSection = this.resolveActiveSection(sections); - if (activeSection) { - this.settingsCtx.setActiveSection(activeSection); - } - }, - { - root: scrollRoot, - threshold: [0.12, 0.24, 0.4, 0.6], - rootMargin: '-18% 0px -52% 0px', - } - ); - - sections.forEach((section) => - this.sectionObserver?.observe(section.element) - ); - - const initialSection = this.resolveActiveSection(sections); - if (initialSection) { - this.settingsCtx.setActiveSection(initialSection); - } - } - - private resolveActiveSection( - sections: ObservedSettingsSection[] - ): string | null { - const scrollRoot = this.getScrollRoot(); - const rootTop = scrollRoot?.getBoundingClientRect().top ?? 0; - const rootHeight = scrollRoot?.clientHeight ?? window.innerHeight; - const activationLine = rootTop + Math.min(rootHeight * 0.28, 220); - const sectionAtActivationLine = sections.find((section) => { - const rect = section.element.getBoundingClientRect(); - return rect.top <= activationLine && rect.bottom >= activationLine; - }); - - if (sectionAtActivationLine) { - return sectionAtActivationLine.id; - } - - const nearestSection = sections - .map((section) => ({ - id: section.id, - distance: Math.abs( - section.element.getBoundingClientRect().top - activationLine - ), - })) - .sort((a, b) => a.distance - b.distance)[0]; - - return nearestSection?.id ?? null; - } - - private getScrollRoot(): HTMLElement | null { - return this.elementRef.nativeElement.closest( - 'main.workspace-content' - ) as HTMLElement | null; - } - - private schedulePendingScrollTargetClear( - scrollRoot: HTMLElement | null - ): void { - const clearPendingScrollTarget = () => { - this.cancelPendingScrollTargetClear(); - this.settingsCtx.clearPendingScrollTarget(); - }; - - this.cancelPendingScrollTargetClear(); - this.pendingScrollClearTimer = window.setTimeout( - clearPendingScrollTarget, - SettingsSectionScrollDirective.PENDING_SCROLL_CLEAR_DELAY_MS - ); - this.pendingScrollClearRoot = scrollRoot; - this.pendingScrollEndListener = clearPendingScrollTarget; - scrollRoot?.addEventListener?.('scrollend', clearPendingScrollTarget, { - once: true, - }); - } - - private cancelPendingScrollTargetClear(): void { - if (this.pendingScrollClearTimer) { - clearTimeout(this.pendingScrollClearTimer); - this.pendingScrollClearTimer = null; - } - - if (this.pendingScrollClearRoot && this.pendingScrollEndListener) { - this.pendingScrollClearRoot.removeEventListener?.( - 'scrollend', - this.pendingScrollEndListener - ); - } - - this.pendingScrollClearRoot = null; - this.pendingScrollEndListener = null; - } - - private scrollToSection(sectionId: string): HTMLElement | null { - const sectionElement = document.getElementById(sectionId); - if (!sectionElement) { - return null; - } - - const scrollRoot = this.getScrollRoot(); - if (!scrollRoot) { - sectionElement.scrollIntoView({ - behavior: 'smooth', - block: 'start', - }); - return null; - } - - const rootRect = scrollRoot.getBoundingClientRect(); - const sectionRect = sectionElement.getBoundingClientRect(); - const sectionTop = - scrollRoot.scrollTop + (sectionRect.top - rootRect.top); - const sectionBottom = sectionTop + sectionRect.height; - const visibleTop = - scrollRoot.scrollTop + - SettingsSectionScrollDirective.SECTION_SCROLL_TOP_GUTTER; - const visibleBottom = - scrollRoot.scrollTop + - scrollRoot.clientHeight - - SettingsSectionScrollDirective.SECTION_SCROLL_BOTTOM_GUTTER; - let nextScrollTop = scrollRoot.scrollTop; - - if (sectionTop < visibleTop) { - nextScrollTop = - sectionTop - - SettingsSectionScrollDirective.SECTION_SCROLL_TOP_GUTTER; - } else if (sectionBottom > visibleBottom) { - nextScrollTop = - sectionBottom - - scrollRoot.clientHeight + - SettingsSectionScrollDirective.SECTION_SCROLL_BOTTOM_GUTTER; - } - - const maxScrollTop = Math.max( - 0, - scrollRoot.scrollHeight - scrollRoot.clientHeight - ); - - scrollRoot.scrollTo({ - top: Math.min(Math.max(nextScrollTop, 0), maxScrollTop), - behavior: 'smooth', - }); - - return scrollRoot; - } -} diff --git a/apps/web/src/app/settings/settings-tmdb-section.component.html b/apps/web/src/app/settings/settings-tmdb-section.component.html index 99e5fa6d5..a720c1832 100644 --- a/apps/web/src/app/settings/settings-tmdb-section.component.html +++ b/apps/web/src/app/settings/settings-tmdb-section.component.html @@ -1,6 +1,5 @@
diff --git a/apps/web/src/app/settings/settings-tmdb-section.component.spec.ts b/apps/web/src/app/settings/settings-tmdb-section.component.spec.ts index 9e09c60f3..b0c152a1b 100644 --- a/apps/web/src/app/settings/settings-tmdb-section.component.spec.ts +++ b/apps/web/src/app/settings/settings-tmdb-section.component.spec.ts @@ -27,14 +27,24 @@ describe('SettingsTmdbSectionComponent', () => { const clearButton = () => queryByTestId('tmdb-clear-cache') as HTMLButtonElement; - /** The stats effect only fires once the TMDB section is the active one */ - const activate = async (section = 'tmdb') => { - fixture.componentRef.setInput('activeSection', section); - fixture.detectChanges(); + /** Constructor kicks off the stats read; let it settle and render. */ + const settle = async () => { await fixture.whenStable(); fixture.detectChanges(); }; + /** + * The section component only exists while its settings page is open, so + * "reopening the section" means recreating the component. + */ + const reopenSection = async () => { + fixture.destroy(); + fixture = TestBed.createComponent(SettingsTmdbSectionComponent); + fixture.componentRef.setInput('form', createForm()); + fixture.detectChanges(); + await settle(); + }; + beforeEach(async () => { getStats = jest.fn().mockResolvedValue({ entries: 42, bytes: 2048 }); clear = jest.fn().mockResolvedValue(42); @@ -73,21 +83,18 @@ describe('SettingsTmdbSectionComponent', () => { fixture = TestBed.createComponent(SettingsTmdbSectionComponent); fixture.componentRef.setInput('form', createForm()); - fixture.componentRef.setInput('activeSection', 'general'); fixture.detectChanges(); }); - it('defers the full-table scan until the section is opened', async () => { - expect(getStats).not.toHaveBeenCalled(); - - await activate(); + it('sizes the cache as soon as the section page opens', async () => { + await settle(); expect(getStats).toHaveBeenCalledTimes(1); expect(queryByTestId('tmdb-cache-size')?.textContent).toContain('42'); }); it('clears the cache and re-reads the size', async () => { - await activate(); + await settle(); getStats.mockResolvedValue({ entries: 0, bytes: 0 }); clearButton().click(); @@ -101,7 +108,7 @@ describe('SettingsTmdbSectionComponent', () => { }); it('surfaces a failed clear instead of claiming an empty cache', async () => { - await activate(); + await settle(); clear.mockResolvedValue(null); clearButton().click(); @@ -116,9 +123,9 @@ describe('SettingsTmdbSectionComponent', () => { }); it('surfaces a failed size read the same way', async () => { + getStats.mockReset(); getStats.mockResolvedValue(null); - - await activate(); + await reopenSection(); expect(queryByTestId('tmdb-cache-size')?.textContent).toContain( CACHE_ERROR_LABEL @@ -126,17 +133,18 @@ describe('SettingsTmdbSectionComponent', () => { }); it('retries the size read next time the section is opened', async () => { + getStats.mockReset(); getStats.mockResolvedValueOnce(null); - await activate(); + getStats.mockResolvedValue({ entries: 42, bytes: 2048 }); + await reopenSection(); expect(queryByTestId('tmdb-cache-size')?.textContent).toContain( CACHE_ERROR_LABEL ); - await activate('general'); - await activate(); + // Otherwise a single transient failure sticks until the destructive + // Clear button shifts it — reopening the page must retry instead + await reopenSection(); - // Otherwise a single transient failure sticks for the life of the - // page, and only the destructive Clear button can shift it expect(getStats).toHaveBeenCalledTimes(2); expect(queryByTestId('tmdb-cache-size')?.textContent).toContain('42'); }); diff --git a/apps/web/src/app/settings/settings-tmdb-section.component.ts b/apps/web/src/app/settings/settings-tmdb-section.component.ts index e7a6f7e3c..f01087a17 100644 --- a/apps/web/src/app/settings/settings-tmdb-section.component.ts +++ b/apps/web/src/app/settings/settings-tmdb-section.component.ts @@ -1,10 +1,8 @@ import { Component, - effect, inject, input, signal, - untracked, ViewEncapsulation, } from '@angular/core'; import { FormGroup, ReactiveFormsModule } from '@angular/forms'; @@ -84,7 +82,6 @@ export class SettingsTmdbSectionComponent { private readonly tmdbCache = inject(TmdbCacheService); readonly form = input.required(); - readonly activeSection = input.required(); readonly keyTestState = signal('idle'); readonly cacheStats = signal(null); @@ -92,21 +89,13 @@ export class SettingsTmdbSectionComponent { readonly isClearing = signal(false); constructor() { - // Sizing the cache is a full table scan, so it waits until the - // user is actually looking at this section. - effect(() => { - if (this.activeSection() !== 'tmdb') { - return; - } - untracked(() => { - // A failed read leaves both signals in their "unknown" - // state, so reopening the section retries rather than - // showing the error until the page is rebuilt. - if (this.cacheStats() === null) { - void this.refreshCacheStats(); - } - }); - }); + // Sizing the cache is a full table scan, but this component only + // exists while its section page is open, so loading on construction + // preserves the old "wait until the user is actually looking" + // behaviour. A failed read leaves the signals in their "unknown" + // state and reopening the section recreates the component, which + // retries naturally. + void this.refreshCacheStats(); } get enteredApiKey(): string { diff --git a/apps/web/src/app/settings/settings-unsaved-changes-dialog.component.ts b/apps/web/src/app/settings/settings-unsaved-changes-dialog.component.ts new file mode 100644 index 000000000..37b8624d5 --- /dev/null +++ b/apps/web/src/app/settings/settings-unsaved-changes-dialog.component.ts @@ -0,0 +1,86 @@ +import { Component, inject } from '@angular/core'; +import { MatButtonModule } from '@angular/material/button'; +import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog'; +import { MatIconModule } from '@angular/material/icon'; +import { TranslateModule } from '@ngx-translate/core'; + +/** What the user picked; closing via backdrop/Esc yields `undefined` = stay. */ +export type SettingsUnsavedChangesChoice = 'save' | 'discard'; + +export interface SettingsUnsavedChangesDialogData { + /** Save-and-leave is offered only while the form can actually be saved. */ + canSave: boolean; +} + +/** + * Asked once, when the user is about to leave the settings area with staged + * edits. Section switches never show this — the shared form survives them. + * "Keep editing" carries the initial focus so Enter is always the safe + * choice. + */ +@Component({ + imports: [MatButtonModule, MatDialogModule, MatIconModule, TranslateModule], + styles: [ + ` + .unsaved-dialog__invalid-hint { + display: flex; + align-items: center; + gap: 8px; + margin: 12px 0 0; + color: var(--mat-sys-error); + font-size: 0.86rem; + + mat-icon { + font-size: 18px; + width: 18px; + height: 18px; + } + } + `, + ], + template: ` +

+ {{ 'SETTINGS.UNSAVED_DIALOG_TITLE' | translate }} +

+ +

{{ 'SETTINGS.UNSAVED_DIALOG_MESSAGE' | translate }}

+ @if (!data.canSave) { +

+ error_outline + {{ + 'SETTINGS.UNSAVED_DIALOG_INVALID_HINT' | translate + }} +

+ } +
+ + + + + + `, +}) +export class SettingsUnsavedChangesDialogComponent { + readonly data = inject(MAT_DIALOG_DATA); +} diff --git a/apps/web/src/app/settings/settings-unsaved-changes.guard.spec.ts b/apps/web/src/app/settings/settings-unsaved-changes.guard.spec.ts new file mode 100644 index 000000000..43fbd7683 --- /dev/null +++ b/apps/web/src/app/settings/settings-unsaved-changes.guard.spec.ts @@ -0,0 +1,58 @@ +import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { + SettingsLeaveConfirmation, + settingsUnsavedChangesGuard, +} from './settings-unsaved-changes.guard'; + +describe('settingsUnsavedChangesGuard', () => { + const runGuard = ( + nextUrl: string, + component: SettingsLeaveConfirmation + ): Promise | boolean => + settingsUnsavedChangesGuard( + component, + {} as ActivatedRouteSnapshot, + { url: '/workspace/settings/general' } as RouterStateSnapshot, + { url: nextUrl } as RouterStateSnapshot + ) as Promise | boolean; + + const componentSpy = (answer: boolean): SettingsLeaveConfirmation => ({ + confirmLeaveWithUnsavedChanges: jest.fn().mockResolvedValue(answer), + }); + + it.each([ + '/workspace/settings/playback', + '/workspace/settings/general?focus=theme', + '/workspace/settings', + ])('lets section-internal navigation to %s pass silently', (url) => { + const component = componentSpy(false); + + expect(runGuard(url, component)).toBe(true); + expect(component.confirmLeaveWithUnsavedChanges).not.toHaveBeenCalled(); + }); + + it('asks the component when actually leaving the settings area', async () => { + const component = componentSpy(false); + + await expect(runGuard('/workspace/dashboard', component)).resolves.toBe( + false + ); + expect(component.confirmLeaveWithUnsavedChanges).toHaveBeenCalledTimes( + 1 + ); + }); + + it('propagates an allowed leave', async () => { + await expect( + runGuard('/workspace/playlists/abc/all', componentSpy(true)) + ).resolves.toBe(true); + }); + + it('does not treat a lookalike prefix as inside the settings area', async () => { + const component = componentSpy(true); + + await runGuard('/workspace/settingsish', component); + + expect(component.confirmLeaveWithUnsavedChanges).toHaveBeenCalled(); + }); +}); diff --git a/apps/web/src/app/settings/settings-unsaved-changes.guard.ts b/apps/web/src/app/settings/settings-unsaved-changes.guard.ts new file mode 100644 index 000000000..3283ef2e4 --- /dev/null +++ b/apps/web/src/app/settings/settings-unsaved-changes.guard.ts @@ -0,0 +1,34 @@ +import { CanDeactivateFn } from '@angular/router'; + +/** + * Structural contract instead of importing the (lazy-loaded) settings + * component into the eager route config. + */ +export interface SettingsLeaveConfirmation { + confirmLeaveWithUnsavedChanges(): Promise | boolean; +} + +function isInsideSettingsArea(url: string): boolean { + const path = url.split('?')[0]; + return ( + path === '/workspace/settings' || + path.startsWith('/workspace/settings/') + ); +} + +/** + * Guards only the EXIT from the settings area. Section switches + * (`/settings/general` → `/settings/playback`) re-run deactivation checks + * because the route's `:section` param changes, but they share the one + * settings form and can never lose staged edits — asking there would be + * pure nagging, so they pass unconditionally. + */ +export const settingsUnsavedChangesGuard: CanDeactivateFn< + SettingsLeaveConfirmation +> = (component, _currentRoute, _currentState, nextState) => { + if (isInsideSettingsArea(nextState.url)) { + return true; + } + + return component.confirmLeaveWithUnsavedChanges(); +}; diff --git a/apps/web/src/app/settings/settings.component.form.spec.ts b/apps/web/src/app/settings/settings.component.form.spec.ts index c11db5c82..50508f394 100644 --- a/apps/web/src/app/settings/settings.component.form.spec.ts +++ b/apps/web/src/app/settings/settings.component.form.spec.ts @@ -18,6 +18,7 @@ import { DEFAULT_SETTINGS, MatSnackBarStub, MockSettingsStore, + setSettingsSection, stubSettingsSideEffects, } from './test-stubs/settings-test-harness.stub'; @@ -111,7 +112,7 @@ describe('SettingsComponent form', () => { expect(component.settingsForm.dirty).toBeTruthy(); }); - it('updates cover size through the general section output', () => { + it('stages cover size without writing to the store until Save', () => { const largeCoverButton = ( fixture.nativeElement as HTMLElement ).querySelector( @@ -122,12 +123,15 @@ describe('SettingsComponent form', () => { fixture.detectChanges(); expect(component.settingsForm.value.coverSize).toBe('large'); - expect(settingsStore.updateSettings).toHaveBeenCalledWith({ - coverSize: 'large', - }); + expect(component.settingsForm.dirty).toBe(true); + // An eager write here would make Discard unable to revert it + expect(settingsStore.updateSettings).not.toHaveBeenCalled(); }); - it('updates the EPG view mode through the epg section output', () => { + it('stages the EPG view mode without writing to the store until Save', () => { + setSettingsSection('epg'); + fixture.detectChanges(); + const listButton = ( fixture.nativeElement as HTMLElement ).querySelector( @@ -138,14 +142,16 @@ describe('SettingsComponent form', () => { fixture.detectChanges(); expect(component.settingsForm.value.epgViewMode).toBe('list'); - expect(settingsStore.updateSettings).toHaveBeenCalledWith({ - epgViewMode: 'list', - }); + expect(component.settingsForm.dirty).toBe(true); + expect(settingsStore.updateSettings).not.toHaveBeenCalled(); }); }); describe('Dashboard controls', () => { it('renders dashboard controls with the expected defaults', () => { + setSettingsSection('dashboard'); + fixture.detectChanges(); + const nativeElement = fixture.nativeElement as HTMLElement; expect( @@ -208,6 +214,78 @@ describe('SettingsComponent form', () => { }); }); + describe('Unsaved-changes bar', () => { + const unsavedBar = () => + (fixture.nativeElement as HTMLElement).querySelector( + '[data-test-id="settings-unsaved-bar"]' + ); + + it('stays hidden while the form is pristine', () => { + expect(unsavedBar()).toBeNull(); + }); + + it('appears once an edit lands and survives a section switch', () => { + component.settingsForm.get('theme')?.setValue(Theme.DarkTheme); + component.settingsForm.markAsDirty(); + fixture.detectChanges(); + + expect(unsavedBar()).not.toBeNull(); + + // The form lives on the page component, not the section pages — + // moving to another section must not swallow the pending edit. + setSettingsSection('about'); + fixture.detectChanges(); + + expect(unsavedBar()).not.toBeNull(); + expect(component.settingsForm.dirty).toBe(true); + }); + + it('hides again after a successful save', async () => { + settingsStore.updateSettings.mockResolvedValue(undefined); + component.settingsForm.get('theme')?.setValue(Theme.DarkTheme); + component.settingsForm.markAsDirty(); + fixture.detectChanges(); + + component.onSubmit(); + await fixture.whenStable(); + fixture.detectChanges(); + + expect(component.settingsForm.pristine).toBe(true); + expect(unsavedBar()).toBeNull(); + }); + + it('discard reverts a staged cover size (regression: eager persist made it stick)', () => { + const largeCoverButton = ( + fixture.nativeElement as HTMLElement + ).querySelector( + '[data-test-id="cover-size-large"]' + ) as HTMLButtonElement; + largeCoverButton.click(); + fixture.detectChanges(); + expect(component.settingsForm.value.coverSize).toBe('large'); + + component.discardChanges(); + + expect(component.settingsForm.value.coverSize).toBe('medium'); + expect(component.settingsForm.pristine).toBe(true); + expect(settingsStore.updateSettings).not.toHaveBeenCalled(); + }); + + it('discard reverts to the stored values and hides the bar', () => { + const storedTheme = component.settingsForm.value.theme; + component.settingsForm.get('theme')?.setValue(Theme.DarkTheme); + component.settingsForm.markAsDirty(); + fixture.detectChanges(); + + component.discardChanges(); + fixture.detectChanges(); + + expect(component.settingsForm.value.theme).toBe(storedTheme); + expect(component.settingsForm.pristine).toBe(true); + expect(unsavedBar()).toBeNull(); + }); + }); + describe('Saving', () => { it('shows the save confirmation snackbar at the bottom center with the settings offset class', () => { jest.spyOn(translate, 'instant').mockReturnValue('Settings saved'); diff --git a/apps/web/src/app/settings/settings.component.html b/apps/web/src/app/settings/settings.component.html index 6170972ad..fc4b3843f 100644 --- a/apps/web/src/app/settings/settings.component.html +++ b/apps/web/src/app/settings/settings.component.html @@ -1,13 +1,4 @@ -@if (isDialog) { -

{{ 'SETTINGS.GENERAL' | translate }}

-} - -
+
- @if (!isDialog) { - - - {{ 'SETTINGS.TITLE' | translate }} - - } + section below provides its own h3 + subtitle. --> + + {{ 'SETTINGS.TITLE' | translate }} +
- - - - - @if (supportsEpg) { - + + @switch (activeSection()) { + @case ('playback') { + + } + @case ('epg') { + + } + @case ('dashboard') { + + } + @case ('remote-control') { + + } + @case ('tmdb') { + + } + @case ('backup') { + + } + @case ('reset') { + + } + @case ('about') { + + } + @default { + + } } +
- - - @if (supportsRemoteControl) { - - } - - - - - - - - - -
- @if (isDialog) { + + @if (!settingsForm.pristine) { +
+
+ edit + {{ 'SETTINGS.UNSAVED_CHANGES' | translate }} +
+
- } - + +
-
+ }
diff --git a/apps/web/src/app/settings/settings.component.scss b/apps/web/src/app/settings/settings.component.scss index a29be1497..30522f62f 100644 --- a/apps/web/src/app/settings/settings.component.scss +++ b/apps/web/src/app/settings/settings.component.scss @@ -8,13 +8,6 @@ padding: 18px 20px calc(36px + var(--settings-safe-bottom)); } -.settings-container.dialog-mode { - height: auto; - max-height: none; - overflow: visible; - padding: 12px 8px calc(24px + var(--settings-safe-bottom)); -} - .settings-layout { display: flex; flex-direction: column; @@ -27,36 +20,6 @@ ); } -.settings-container.dialog-mode .settings-layout { - padding-bottom: 0; -} - -.settings-page-header { - padding: 14px 18px 8px; - background: transparent; - border: 0; - box-shadow: none; -} - -.settings-page-header__text { - max-width: 56ch; - - h1 { - margin: 0; - font-size: clamp(1.35rem, 2vw, 1.75rem); - line-height: 1.08; - letter-spacing: -0.03em; - font-weight: 700; - } - - p { - margin: 4px 0 0; - color: var(--settings-muted); - font-size: 0.86rem; - line-height: 1.45; - } -} - .settings-content { min-width: 0; display: flex; @@ -86,16 +49,6 @@ } } -// The active section no longer gets a ring/shadow — the rail's active -// state on the left already announces "you are here". Title still -// colours to the accent so users scanning the right pane don't lose the -// anchor. -.settings-group--active { - .settings-group__header-text h3 { - color: var(--app-selection-color); - } -} - .settings-group__header { display: flex; align-items: flex-start; @@ -738,13 +691,11 @@ ); } -// Sticky-footer Save bar — full content width so it never overlaps form -// rows. The previous chip-style bar (border-radius:18px, margin-left:auto) -// floated in the bottom-right corner and clipped fields underneath; the -// UX audit called this out as the worst of three available patterns. -// Now the bar acts as a proper footer: spans the column, separator line -// on top, sits flush with the bottom edge while still sticking on scroll. -.action-bar { +// Unsaved-changes bar — only present while the form is dirty, so unlike the +// previous always-visible footer Save button it doubles as the "you edited +// something on another section page" reminder. Sticky rather than fixed so +// it stays inside the settings column and never covers the shell rail. +.unsaved-bar { position: sticky; bottom: calc( var(--settings-action-bar-offset) + var(--settings-safe-bottom) @@ -756,7 +707,7 @@ box-sizing: border-box; z-index: 100; display: flex; - justify-content: flex-end; + justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; @@ -769,17 +720,45 @@ background: var(--settings-action-bar-bg); backdrop-filter: blur(12px); box-shadow: var(--settings-action-bar-shadow); + animation: unsaved-bar-enter 0.2s cubic-bezier(0.16, 1, 0.3, 1); + + @media (prefers-reduced-motion: reduce) { + animation: none; + } } -.settings-container.dialog-mode .action-bar { - position: static; - margin-top: 12px; - margin-bottom: 2px; - box-shadow: none; - border-radius: 16px; - padding: 12px; - border-top: 1px solid var(--settings-action-bar-border); - justify-content: space-between; +@keyframes unsaved-bar-enter { + from { + opacity: 0; + transform: translateY(8px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.unsaved-bar__message { + display: inline-flex; + align-items: center; + gap: 8px; + color: var(--settings-muted); + font-size: 0.88rem; + + mat-icon { + font-size: 18px; + width: 18px; + height: 18px; + } +} + +.unsaved-bar__actions { + display: inline-flex; + align-items: center; + gap: 8px; + margin-left: auto; + flex-wrap: wrap; } .settings-save-button.mat-mdc-button-base { @@ -882,13 +861,15 @@ flex-wrap: wrap; } - .action-bar { - position: static; - flex-direction: column-reverse; + .unsaved-bar { + flex-direction: column; align-items: stretch; border-radius: 16px; - box-shadow: none; - width: 100%; + } + + .unsaved-bar__actions { + flex-direction: column-reverse; + align-items: stretch; margin-left: 0; button { diff --git a/apps/web/src/app/settings/settings.component.spec.ts b/apps/web/src/app/settings/settings.component.spec.ts index 72442aec9..cc643487d 100644 --- a/apps/web/src/app/settings/settings.component.spec.ts +++ b/apps/web/src/app/settings/settings.component.spec.ts @@ -1,5 +1,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { MatDialog } from '@angular/material/dialog'; import { Router } from '@angular/router'; +import { of } from 'rxjs'; import { EpgRuntimeBridgeService } from '@iptvnator/epg/data-access'; import { selectAllPlaylistsMeta } from '@iptvnator/m3u-state'; import { @@ -15,15 +17,17 @@ import { createEpgBridgeStub, createPlaylistMeta, DEFAULT_SETTINGS, + MockRouter, + setSettingsSection, stubSettingsSideEffects, } from './test-stubs/settings-test-harness.stub'; /** - * Page-shell behaviour: chrome, the facade lifecycle and the runtime - * capabilities that decide which sections and players are offered. Form - * editing and saving live in `settings.component.form.spec.ts`, section - * scrolling in `settings-section-scroll.directive.spec.ts`, and the - * per-section behaviour in the matching `*.facade.spec.ts` files. + * Page-shell behaviour: chrome, the `:section` page routing, the facade + * lifecycle and the runtime capabilities that decide which sections and + * players are offered. Form editing and saving live in + * `settings.component.form.spec.ts`, and the per-section behaviour in the + * matching `*.facade.spec.ts` files. */ describe('SettingsComponent', () => { let component: SettingsComponent; @@ -102,7 +106,7 @@ describe('SettingsComponent', () => { expect(appUpdateDispose).toHaveBeenCalledTimes(1); }); - it('should render a compact page header outside dialog mode', () => { + it('should render the hidden page header hook', () => { const nativeElement = fixture.nativeElement as HTMLElement; expect( @@ -111,32 +115,117 @@ describe('SettingsComponent', () => { expect(nativeElement.querySelector('.settings-intro')).toBeNull(); }); - it('should not render the page header in dialog mode', () => { - fixture.destroy(); + describe('Section pages', () => { + it('renders only the section named by the route param', () => { + const nativeElement = fixture.nativeElement as HTMLElement; - const dialogFixture = TestBed.createComponent(SettingsComponent); - const dialogComponent = dialogFixture.componentInstance; + expect( + nativeElement.querySelector('app-settings-general-section') + ).not.toBeNull(); + expect( + nativeElement.querySelector('app-settings-playback-section') + ).toBeNull(); - stubSettingsSideEffects(dialogComponent); - dialogComponent.isDialog = true; - dialogFixture.detectChanges(); + setSettingsSection('playback'); + fixture.detectChanges(); - const nativeElement = dialogFixture.nativeElement as HTMLElement; - expect( - nativeElement.querySelector('[data-test-id="settings-page-header"]') - ).toBeNull(); - expect( - nativeElement.querySelector('h2[mat-dialog-title]') - ).not.toBeNull(); + expect( + nativeElement.querySelector('app-settings-general-section') + ).toBeNull(); + expect( + nativeElement.querySelector('app-settings-playback-section') + ).not.toBeNull(); + }); + + it('falls back to the general page and rewrites unknown section URLs', () => { + const navigate = (router as unknown as MockRouter).navigate; + + setSettingsSection('nonsense'); + fixture.detectChanges(); + + expect(component.activeSection()).toBe('general'); + expect(navigate).toHaveBeenCalledWith( + ['/workspace/settings', 'general'], + { replaceUrl: true } + ); + expect( + (fixture.nativeElement as HTMLElement).querySelector( + 'app-settings-general-section' + ) + ).not.toBeNull(); + }); }); - it('should navigate back to home page', () => { - jest.spyOn(router, 'navigateByUrl'); - component.backToHome(); - expect(router.navigateByUrl).toHaveBeenCalledWith('/'); + describe('Leaving with unsaved changes', () => { + const answerDialogWith = ( + choice: 'save' | 'discard' | undefined + ): jest.Mock => { + const open = TestBed.inject(MatDialog).open as jest.Mock; + open.mockReturnValue({ afterClosed: () => of(choice) }); + return open; + }; + + it('lets a pristine form leave without asking', async () => { + const open = answerDialogWith(undefined); + + await expect( + component.confirmLeaveWithUnsavedChanges() + ).resolves.toBe(true); + expect(open).not.toHaveBeenCalled(); + }); + + it('stays when the dialog is dismissed', async () => { + component.settingsForm.markAsDirty(); + answerDialogWith(undefined); + + await expect( + component.confirmLeaveWithUnsavedChanges() + ).resolves.toBe(false); + expect(component.settingsForm.dirty).toBe(true); + }); + + it('discard-and-leave reverts the staged edits', async () => { + component.settingsForm.get('theme')?.setValue('DARK_THEME'); + component.settingsForm.markAsDirty(); + answerDialogWith('discard'); + + await expect( + component.confirmLeaveWithUnsavedChanges() + ).resolves.toBe(true); + expect(component.settingsForm.pristine).toBe(true); + }); + + it('save-and-leave persists before allowing the navigation', async () => { + component.settingsForm.markAsDirty(); + jest.spyOn(component.epg, 'fetchConfiguredEpg').mockImplementation(); + answerDialogWith('save'); + + await expect( + component.confirmLeaveWithUnsavedChanges() + ).resolves.toBe(true); + expect(component.settingsForm.pristine).toBe(true); + }); + + it('offers save-and-leave only while the form is valid', async () => { + component.settingsForm.markAsDirty(); + component.settingsForm.setErrors({ invalid: true }); + const open = answerDialogWith(undefined); + + await component.confirmLeaveWithUnsavedChanges(); + + expect(open).toHaveBeenCalledWith( + expect.anything(), + expect.objectContaining({ + data: { canSave: false }, + }) + ); + }); }); it('enables the global wipe action only once a playlist exists', () => { + setSettingsSection('reset'); + fixture.detectChanges(); + const deleteButton = () => (fixture.nativeElement as HTMLElement).querySelector( '.danger-zone__button' diff --git a/apps/web/src/app/settings/settings.component.storage-failure.spec.ts b/apps/web/src/app/settings/settings.component.storage-failure.spec.ts index 94fe3a9a6..9213f1a97 100644 --- a/apps/web/src/app/settings/settings.component.storage-failure.spec.ts +++ b/apps/web/src/app/settings/settings.component.storage-failure.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar } from '@angular/material/snack-bar'; +import { of } from 'rxjs'; import { EpgRuntimeBridgeService } from '@iptvnator/epg/data-access'; import { SettingsStore } from '../services/settings-store.service'; import { SettingsComponent } from './settings.component'; @@ -18,14 +19,6 @@ const ERROR_SNACKBAR_CONFIG = expect.objectContaining({ panelClass: ['settings-snackbar', 'settings-snackbar--error'], }); -/** - * Assertions target the MatDialog the component actually calls: spying on the - * one returned by `TestBed.inject(MatDialog)` does not observe it. - */ -interface SettingsComponentPrivateTestApi { - matDialog: MatDialog; -} - /** * Settings live in the renderer's IndexedDB, and both halves of the round trip * can fail while the UI keeps looking healthy: a failed read shows defaults as @@ -39,8 +32,6 @@ describe('SettingsComponent storage failures', () => { let snackBar: MatSnackBarStub; let epgBridge: Partial; const originalElectron = window.electron; - const componentMatDialog = (): MatDialog => - (component as unknown as SettingsComponentPrivateTestApi).matDialog; beforeEach(waitForAsync(() => { epgBridge = createEpgBridgeStub(); @@ -77,12 +68,11 @@ describe('SettingsComponent storage failures', () => { ); }); - it('warns and keeps the dialog open when the settings write fails', async () => { + it('warns and keeps the form dirty when the settings write fails', async () => { settingsStore.updateSettings.mockRejectedValue( new Error('storage unavailable') ); - const closeAll = jest.spyOn(componentMatDialog(), 'closeAll'); - component.isDialog = true; + component.settingsForm.markAsDirty(); component.onSubmit(); await fixture.whenStable(); @@ -92,37 +82,47 @@ describe('SettingsComponent storage failures', () => { 'CLOSE', ERROR_SNACKBAR_CONFIG ); - expect(closeAll).not.toHaveBeenCalled(); + // The unsaved-changes bar keys off the dirty state, so the failed + // write must not mark the form pristine — that is what keeps the + // retry path on screen. + expect(component.settingsForm.dirty).toBe(true); }); - it('closes the dialog only after the settings write succeeded', async () => { + it('marks the form pristine only after the settings write succeeded', async () => { settingsStore.updateSettings.mockResolvedValue(undefined); - const closeAll = jest.spyOn(componentMatDialog(), 'closeAll'); jest.spyOn(component.epg, 'fetchConfiguredEpg').mockImplementation(); - component.isDialog = true; + component.settingsForm.markAsDirty(); component.onSubmit(); // save() resolves a tick after the store write: the callback and - // the Electron mirror run first, so the close lands on the next - // turn of the microtask queue. + // the Electron mirror run first, so the pristine flip lands on the + // next turn of the microtask queue. await fixture.whenStable(); await fixture.whenStable(); - expect(closeAll).toHaveBeenCalledTimes(1); + expect(component.settingsForm.pristine).toBe(true); }); - it('warns when a section write fails without leaving an unhandled rejection', async () => { + it('keeps the user in settings when save-and-leave cannot persist', async () => { settingsStore.updateSettings.mockRejectedValue( new Error('storage unavailable') ); + component.settingsForm.markAsDirty(); + (TestBed.inject(MatDialog).open as jest.Mock).mockReturnValue({ + afterClosed: () => of('save'), + }); - component.form.selectCoverSize('large'); - await fixture.whenStable(); - + // Allowing the navigation here would silently drop the edits the + // dialog just promised to save. + await expect(component.confirmLeaveWithUnsavedChanges()).resolves.toBe( + false + ); expect(snackBar.open).toHaveBeenCalledWith( 'SETTINGS.SETTINGS_SAVE_FAILED', 'CLOSE', ERROR_SNACKBAR_CONFIG ); + expect(component.settingsForm.dirty).toBe(true); }); + }); diff --git a/apps/web/src/app/settings/settings.component.ts b/apps/web/src/app/settings/settings.component.ts index c6be7539e..e136cc871 100644 --- a/apps/web/src/app/settings/settings.component.ts +++ b/apps/web/src/app/settings/settings.component.ts @@ -1,27 +1,25 @@ -import { CommonModule } from '@angular/common'; import { Component, computed, + effect, + ElementRef, inject, - Input, OnDestroy, OnInit, ViewEncapsulation, } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { ReactiveFormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; -import { - MAT_DIALOG_DATA, - MatDialog, - MatDialogModule, -} from '@angular/material/dialog'; +import { MatDialog } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; -import { Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { SettingsContextService } from '@iptvnator/workspace/shell/util'; import { TranslateModule, TranslateService } from '@ngx-translate/core'; import { RuntimeCapabilitiesService } from '@iptvnator/services'; import { VodSourceDiscoveryService } from '@iptvnator/portal/shared/data-access'; import { Language, StreamFormat } from '@iptvnator/shared/interfaces'; +import { firstValueFrom, map } from 'rxjs'; import { BUILD_COMMIT } from '../../environments/build-commit'; import { SettingsAboutSectionComponent } from './settings-about-section.component'; import { SettingsAppUpdateFacade } from './settings-app-update.facade'; @@ -45,17 +43,28 @@ import { SettingsPlaybackSectionComponent } from './settings-playback-section.co import { SettingsRemoteControlFacade } from './settings-remote-control.facade'; import { SettingsRemoteControlSectionComponent } from './settings-remote-control-section.component'; import { SettingsResetSectionComponent } from './settings-reset-section.component'; -import { SettingsSectionScrollDirective } from './settings-section-scroll.directive'; import { SettingsTmdbSectionComponent } from './settings-tmdb-section.component'; +import { + SettingsUnsavedChangesChoice, + SettingsUnsavedChangesDialogComponent, +} from './settings-unsaved-changes-dialog.component'; +import { SettingsLeaveConfirmation } from './settings-unsaved-changes.guard'; import { SettingsBackupFacade } from './settings-backup.facade'; import { SettingsPlaylistResetFacade } from './settings-playlist-reset.facade'; import { SettingsSnackbarService } from './settings-snackbar.service'; +export const SETTINGS_DEFAULT_SECTION = 'general'; + /** * Thin coordinator for the settings page. The behaviour of each section lives * in a dedicated facade the template binds to directly; what stays here is the - * page-level wiring: environment capabilities, section navigation, and the - * save/close flow that spans several facades. + * page-level wiring: environment capabilities, the `:section` route param that + * selects which section page renders, and the save/discard flow that spans + * several facades. + * + * Routed as `/workspace/settings/:section`. Navigating between sections only + * changes the param — the component instance (and with it the form and its + * dirty state) survives until the user leaves settings entirely. */ @Component({ templateUrl: './settings.component.html', @@ -65,12 +74,10 @@ import { SettingsSnackbarService } from './settings-snackbar.service'; }, encapsulation: ViewEncapsulation.None, imports: [ - CommonModule, MatButtonModule, MatIconModule, ReactiveFormsModule, TranslateModule, - MatDialogModule, SettingsAboutSectionComponent, SettingsBackupSectionComponent, SettingsDashboardSectionComponent, @@ -79,7 +86,6 @@ import { SettingsSnackbarService } from './settings-snackbar.service'; SettingsPlaybackSectionComponent, SettingsRemoteControlSectionComponent, SettingsResetSectionComponent, - SettingsSectionScrollDirective, SettingsTmdbSectionComponent, ], providers: [ @@ -93,7 +99,9 @@ import { SettingsSnackbarService } from './settings-snackbar.service'; SettingsSnackbarService, ], }) -export class SettingsComponent implements OnInit, OnDestroy { +export class SettingsComponent + implements OnInit, OnDestroy, SettingsLeaveConfirmation +{ readonly appUpdate = inject(SettingsAppUpdateFacade); readonly backup = inject(SettingsBackupFacade); readonly embeddedMpv = inject(SettingsEmbeddedMpvFacade); @@ -107,14 +115,10 @@ export class SettingsComponent implements OnInit, OnDestroy { private readonly runtime = inject(RuntimeCapabilitiesService); private readonly vodSourceDiscovery = inject(VodSourceDiscoveryService); private readonly matDialog = inject(MatDialog); + private readonly route = inject(ActivatedRoute); private readonly router = inject(Router); private readonly translate = inject(TranslateService); - private readonly dialogData = inject<{ isDialog: boolean } | null>( - MAT_DIALOG_DATA, - { optional: true } - ); - - @Input() isDialog = this.dialogData?.isDialog ?? false; + private readonly hostElement = inject(ElementRef); /** List with available languages as enum */ readonly languageEnum = Language; @@ -134,8 +138,6 @@ export class SettingsComponent implements OnInit, OnDestroy { readonly supportsVodMultiSource = this.vodSourceDiscovery.isAvailable; readonly supportsRemoteControl = this.runtime.supportsRemoteControl; - readonly activeSection = this.settingsCtx.activeSection; - /** Settings form object */ readonly settingsForm = this.form.form; @@ -164,6 +166,49 @@ export class SettingsComponent implements OnInit, OnDestroy { return this.sectionNavItems.filter((section) => section.visible); } + private readonly sectionParam = toSignal( + this.route.paramMap.pipe(map((params) => params.get('section'))), + { initialValue: null } + ); + + /** + * Section page currently rendered. Unknown or capability-gated params + * fall back to the default section while the redirect effect below + * rewrites the URL to match. + */ + readonly activeSection = computed(() => { + const section = this.sectionParam(); + return section && this.isNavigableSection(section) + ? section + : SETTINGS_DEFAULT_SECTION; + }); + + constructor() { + // A stale or hand-typed URL (`/settings/epg` in a runtime without + // EPG support, `/settings/nonsense`) must not leave the address bar + // lying about what is on screen. + effect(() => { + const section = this.sectionParam(); + if (section && !this.isNavigableSection(section)) { + void this.router.navigate( + ['/workspace/settings', SETTINGS_DEFAULT_SECTION], + { replaceUrl: true } + ); + } + }); + + // Section pages share one scroll container (`main.workspace-content`); + // without this, opening a long section, scrolling, and switching to a + // short one strands the viewport past the new page's content. Instant + // on purpose — this is navigation, not an animated transition. + effect(() => { + this.activeSection(); + this.hostElement.nativeElement + .closest('main.workspace-content') + ?.scrollTo({ top: 0 }); + }); + } + /** * Reads the config object from the browsers * storage (indexed db) @@ -178,9 +223,7 @@ export class SettingsComponent implements OnInit, OnDestroy { this.appUpdate.init(); void this.remoteControl.fetchLocalIpAddresses(); - if (!this.isDialog) { - this.settingsCtx.setSections(this.sectionNav); - } + this.settingsCtx.setSections(this.sectionNav); } ngOnDestroy(): void { @@ -202,26 +245,78 @@ export class SettingsComponent implements OnInit, OnDestroy { * the indexed db store */ onSubmit(): void { - this.form - .save(() => this.applyChangedSettings()) - .then(() => { - if (this.isDialog) { - this.matDialog.closeAll(); - } - }) - .catch(() => { - // The store already applied the change in memory, so without - // this the save looks successful until the next restart. The - // dialog stays open so it can be retried. - // - // The Electron-side pushes in SettingsFormFacade.save() stay in - // the success branch on purpose: main keeps its own copy of the - // player paths and remote-control state, and applying half the - // form while telling the user nothing was saved is worse than - // applying none of it. Once settings live in the main process - // (issue #1273) this split disappears. - this.settingsSnackbar.storageFailure('save'); - }); + void this.persistSettings(); + } + + /** + * Exit gate for `settingsUnsavedChangesGuard`: silently allows leaving + * while the form is pristine, otherwise lets the user save, discard, or + * stay. A failed save keeps the user in settings — navigating away on a + * write that did not land would silently lose the edits the dialog just + * promised to keep. + */ + async confirmLeaveWithUnsavedChanges(): Promise { + if (this.settingsForm.pristine) { + return true; + } + + const choice = await firstValueFrom( + this.matDialog + .open< + SettingsUnsavedChangesDialogComponent, + { canSave: boolean }, + SettingsUnsavedChangesChoice + >(SettingsUnsavedChangesDialogComponent, { + width: '440px', + data: { canSave: this.settingsForm.valid }, + }) + .afterClosed() + ); + + if (choice === 'save') { + return this.persistSettings(); + } + + if (choice === 'discard') { + // Also reverts the live theme preview — leaving must not keep a + // theme the store never saved. + this.discardChanges(); + return true; + } + + return false; + } + + /** @returns whether the write actually landed */ + private async persistSettings(): Promise { + try { + await this.form.save(() => this.applyChangedSettings()); + return true; + } catch { + // The store already applied the change in memory, so without + // this the save looks successful until the next restart. The + // unsaved-changes bar stays visible so it can be retried. + // + // The Electron-side pushes in SettingsFormFacade.save() stay in + // the success branch on purpose: main keeps its own copy of the + // player paths and remote-control state, and applying half the + // form while telling the user nothing was saved is worse than + // applying none of it. Once settings live in the main process + // (issue #1273) this split disappears. + this.settingsSnackbar.storageFailure('save'); + return false; + } + } + + /** + * Throws away every staged form edit and returns to the persisted + * settings. `applySavedSettings` also reverts the live theme preview + * (`selectTheme` applies immediately) and marks the form pristine, which + * hides the unsaved-changes bar. + */ + discardChanges(): void { + this.form.hydrateFromStore(); + this.form.applySavedSettings(); } /** @@ -235,17 +330,6 @@ export class SettingsComponent implements OnInit, OnDestroy { ); } - /** - * Navigates back to the applications homepage - */ - backToHome(): void { - if (this.isDialog) { - this.matDialog.closeAll(); - } else { - this.router.navigateByUrl('/'); - } - } - async exportData(): Promise { await this.backup.exportData(() => this.waitForUiFeedbackFrame()); } @@ -260,6 +344,10 @@ export class SettingsComponent implements OnInit, OnDestroy { ); } + private isNavigableSection(sectionId: string): boolean { + return this.sectionNav.some((section) => section.id === sectionId); + } + /** * Lets the browser paint the pending busy state before a long running * task blocks the main thread. diff --git a/apps/web/src/app/settings/settings.models.ts b/apps/web/src/app/settings/settings.models.ts index 36f4d18b4..2bfc8db82 100644 --- a/apps/web/src/app/settings/settings.models.ts +++ b/apps/web/src/app/settings/settings.models.ts @@ -13,11 +13,6 @@ export interface SettingsSection { visible: boolean; } -export interface ObservedSettingsSection { - id: string; - element: HTMLElement; -} - export interface ThemeOption { value: Theme; icon: string; diff --git a/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts b/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts index 5249bd628..2dd8cd1c5 100644 --- a/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts +++ b/apps/web/src/app/settings/test-stubs/settings-test-harness.stub.ts @@ -16,7 +16,12 @@ import { MatSelectModule } from '@angular/material/select'; import { MatSnackBar } from '@angular/material/snack-bar'; import { MatTooltipModule } from '@angular/material/tooltip'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { Router } from '@angular/router'; +import { + ActivatedRoute, + convertToParamMap, + ParamMap, + Router, +} from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { EpgRuntimeBridgeService, @@ -47,7 +52,7 @@ import { provideMockStore } from '@ngrx/store/testing'; import { TranslateModule } from '@ngx-translate/core'; import { MockModule, MockProvider } from 'ng-mocks'; import { NgxIndexedDBService } from 'ngx-indexed-db'; -import { from, of } from 'rxjs'; +import { BehaviorSubject, from, of } from 'rxjs'; import { ElectronServiceStub } from '../../services/electron.service.stub'; import { SettingsStorageFailure } from '@iptvnator/services'; import { SettingsStore } from '../../services/settings-store.service'; @@ -121,11 +126,36 @@ export class MatSnackBarStub { } export class MockRouter { + navigate = jest.fn().mockResolvedValue(true); + navigateByUrl(url: string): string { return url; } } +/** + * Stands in for the `:section` route param the settings page renders from. + * Specs switch section pages with `setSettingsSection` below. + */ +export class MockActivatedRoute { + private readonly params = new BehaviorSubject( + convertToParamMap({ section: 'general' }) + ); + + readonly paramMap = this.params.asObservable(); + + setSection(section: string): void { + this.params.next(convertToParamMap({ section })); + } +} + +/** Routes the rendered settings page to the given section page. */ +export function setSettingsSection(section: string): void { + ( + TestBed.inject(ActivatedRoute) as unknown as MockActivatedRoute + ).setSection(section); +} + export class MockSettingsStore { private _settings = signal(DEFAULT_SETTINGS); @@ -273,6 +303,7 @@ export function settingsTestProviders( { provide: MatSnackBar, useClass: MatSnackBarStub }, { provide: DataService, useClass: ElectronServiceStub }, { provide: Router, useClass: MockRouter }, + { provide: ActivatedRoute, useClass: MockActivatedRoute }, provideMockStore({ selectors: [ { selector: selectAllPlaylistsMeta, value: [] }, diff --git a/apps/web/src/assets/i18n/ar.json b/apps/web/src/assets/i18n/ar.json index f89ff8043..62e2a9df2 100644 --- a/apps/web/src/assets/i18n/ar.json +++ b/apps/web/src/assets/i18n/ar.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "اختر خيارًا", "VERSION": "الإصدار", "SAVE_CHANGES": "حفظ التغييرات", + "UNSAVED_CHANGES": "لديك تغييرات غير محفوظة", + "DISCARD_CHANGES": "تجاهل", + "UNSAVED_DIALOG_TITLE": "تغييرات غير محفوظة", + "UNSAVED_DIALOG_MESSAGE": "لديك تغييرات غير محفوظة في الإعدادات. هل تريد حفظها قبل المغادرة؟", + "UNSAVED_DIALOG_SAVE": "احفظ وغادر", + "UNSAVED_DIALOG_DISCARD": "غادر دون حفظ", + "UNSAVED_DIALOG_STAY": "متابعة التحرير", + "UNSAVED_DIALOG_INVALID_HINT": "بعض الحقول غير صالحة، لذلك لا يمكن حفظ التغييرات بعد.", "BACK_TO_HOME": "العودة للرئيسية", "NEW_VERSION_AVAILABLE": "إصدار جديد متاح", "LATEST_VERSION": "أنت تستخدم الإصدار الأحدث", diff --git a/apps/web/src/assets/i18n/ary.json b/apps/web/src/assets/i18n/ary.json index 0badb1c0e..00f80f3f0 100644 --- a/apps/web/src/assets/i18n/ary.json +++ b/apps/web/src/assets/i18n/ary.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "اختار خيار", "VERSION": "الإصدار", "SAVE_CHANGES": "حفظ التغييرات", + "UNSAVED_CHANGES": "عندك تغييرات ماتسجلوش", + "DISCARD_CHANGES": "تجاهل", + "UNSAVED_DIALOG_TITLE": "تغييرات ماتسجلاتش", + "UNSAVED_DIALOG_MESSAGE": "عندك تغييرات ماتسجلاتش فالإعدادات. بغيتي تسجلهم قبل ما تخرج؟", + "UNSAVED_DIALOG_SAVE": "سجّل و خرج", + "UNSAVED_DIALOG_DISCARD": "خرج بلا ما تسجل", + "UNSAVED_DIALOG_STAY": "كمّل التعديل", + "UNSAVED_DIALOG_INVALID_HINT": "شي خانات ماشي صحيحين، علاش مايمكنش تسجل التغييرات دابا.", "BACK_TO_HOME": "رجوع", "NEW_VERSION_AVAILABLE": "كاين إصدار جديد متوفر", "LATEST_VERSION": "راك تستعمل أحدث إصدار", diff --git a/apps/web/src/assets/i18n/by.json b/apps/web/src/assets/i18n/by.json index 178614b53..61c1f25b4 100644 --- a/apps/web/src/assets/i18n/by.json +++ b/apps/web/src/assets/i18n/by.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Выберыце са спісу", "VERSION": "Версія праграмы", "SAVE_CHANGES": "Захаваць", + "UNSAVED_CHANGES": "У вас ёсць незахаваныя змены", + "DISCARD_CHANGES": "Адмяніць змены", + "UNSAVED_DIALOG_TITLE": "Незахаваныя змены", + "UNSAVED_DIALOG_MESSAGE": "У вас ёсць незахаваныя змены налад. Захаваць іх перад выхадам?", + "UNSAVED_DIALOG_SAVE": "Захаваць і выйсці", + "UNSAVED_DIALOG_DISCARD": "Выйсці без захавання", + "UNSAVED_DIALOG_STAY": "Працягнуць рэдагаванне", + "UNSAVED_DIALOG_INVALID_HINT": "Некаторыя палі запоўнены няправільна, таму змены пакуль нельга захаваць.", "BACK_TO_HOME": "Назад", "NEW_VERSION_AVAILABLE": "Даступная новая версія праграмы", "LATEST_VERSION": "Вы выкарыстоўваеце апошнюю версію праграмы", diff --git a/apps/web/src/assets/i18n/de.json b/apps/web/src/assets/i18n/de.json index 0ba4fc7af..187bdc275 100644 --- a/apps/web/src/assets/i18n/de.json +++ b/apps/web/src/assets/i18n/de.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Option auswählen", "VERSION": "Version", "SAVE_CHANGES": "Änderungen speichern", + "UNSAVED_CHANGES": "Du hast ungespeicherte Änderungen", + "DISCARD_CHANGES": "Verwerfen", + "UNSAVED_DIALOG_TITLE": "Ungespeicherte Änderungen", + "UNSAVED_DIALOG_MESSAGE": "Du hast ungespeicherte Änderungen an den Einstellungen. Möchtest du sie vor dem Verlassen speichern?", + "UNSAVED_DIALOG_SAVE": "Speichern und verlassen", + "UNSAVED_DIALOG_DISCARD": "Verlassen ohne zu speichern", + "UNSAVED_DIALOG_STAY": "Weiter bearbeiten", + "UNSAVED_DIALOG_INVALID_HINT": "Einige Felder sind ungültig, daher können die Änderungen noch nicht gespeichert werden.", "BACK_TO_HOME": "Zurück", "NEW_VERSION_AVAILABLE": "EIne neue Version der Anwendung ist verfügbar", "LATEST_VERSION": "Sie nutzen die neueste Version der Anwendung", diff --git a/apps/web/src/assets/i18n/el.json b/apps/web/src/assets/i18n/el.json index 7c2548fb6..aa0b2d911 100644 --- a/apps/web/src/assets/i18n/el.json +++ b/apps/web/src/assets/i18n/el.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Επιλέξτε μια επιλογή", "VERSION": "Έκδοση", "SAVE_CHANGES": "Αποθήκευση αλλαγών", + "UNSAVED_CHANGES": "Έχετε μη αποθηκευμένες αλλαγές", + "DISCARD_CHANGES": "Απόρριψη", + "UNSAVED_DIALOG_TITLE": "Μη αποθηκευμένες αλλαγές", + "UNSAVED_DIALOG_MESSAGE": "Έχετε μη αποθηκευμένες αλλαγές στις ρυθμίσεις. Θέλετε να τις αποθηκεύσετε πριν φύγετε;", + "UNSAVED_DIALOG_SAVE": "Αποθήκευση και έξοδος", + "UNSAVED_DIALOG_DISCARD": "Έξοδος χωρίς αποθήκευση", + "UNSAVED_DIALOG_STAY": "Συνέχεια επεξεργασίας", + "UNSAVED_DIALOG_INVALID_HINT": "Ορισμένα πεδία δεν είναι έγκυρα, επομένως οι αλλαγές δεν μπορούν να αποθηκευτούν ακόμη.", "BACK_TO_HOME": "Πίσω", "NEW_VERSION_AVAILABLE": "Υπάρχει διαθέσιμη μια νέα έκδοση", "LATEST_VERSION": "Χρησιμοποιείτε την πιο πρόσφατη έκδοση", diff --git a/apps/web/src/assets/i18n/en.json b/apps/web/src/assets/i18n/en.json index d8f3c3c99..7d3a7fa5b 100644 --- a/apps/web/src/assets/i18n/en.json +++ b/apps/web/src/assets/i18n/en.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Select an option", "VERSION": "Version", "SAVE_CHANGES": "Save changes", + "UNSAVED_CHANGES": "You have unsaved changes", + "DISCARD_CHANGES": "Discard", + "UNSAVED_DIALOG_TITLE": "Unsaved changes", + "UNSAVED_DIALOG_MESSAGE": "You have unsaved settings changes. Do you want to save them before leaving?", + "UNSAVED_DIALOG_SAVE": "Save and leave", + "UNSAVED_DIALOG_DISCARD": "Leave without saving", + "UNSAVED_DIALOG_STAY": "Keep editing", + "UNSAVED_DIALOG_INVALID_HINT": "Some fields are invalid, so the changes cannot be saved yet.", "BACK_TO_HOME": "Back", "NEW_VERSION_AVAILABLE": "There is a new version available", "LATEST_VERSION": "You are using the latest version", diff --git a/apps/web/src/assets/i18n/es.json b/apps/web/src/assets/i18n/es.json index 305b93ac0..ece8c7c0f 100644 --- a/apps/web/src/assets/i18n/es.json +++ b/apps/web/src/assets/i18n/es.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Selecciona una opción", "VERSION": "Versión", "SAVE_CHANGES": "Guardar cambios", + "UNSAVED_CHANGES": "Tienes cambios sin guardar", + "DISCARD_CHANGES": "Descartar", + "UNSAVED_DIALOG_TITLE": "Cambios sin guardar", + "UNSAVED_DIALOG_MESSAGE": "Tienes cambios sin guardar en los ajustes. ¿Quieres guardarlos antes de salir?", + "UNSAVED_DIALOG_SAVE": "Guardar y salir", + "UNSAVED_DIALOG_DISCARD": "Salir sin guardar", + "UNSAVED_DIALOG_STAY": "Seguir editando", + "UNSAVED_DIALOG_INVALID_HINT": "Algunos campos no son válidos, por lo que los cambios aún no se pueden guardar.", "BACK_TO_HOME": "Volver al inicio", "NEW_VERSION_AVAILABLE": "Hay una nueva versión disponible", "LATEST_VERSION": "Estás usando la versión reciente", diff --git a/apps/web/src/assets/i18n/fr.json b/apps/web/src/assets/i18n/fr.json index 60dbb3e7c..41632f8d3 100644 --- a/apps/web/src/assets/i18n/fr.json +++ b/apps/web/src/assets/i18n/fr.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Choisir une option", "VERSION": "Version", "SAVE_CHANGES": "Enregistrer les modifications", + "UNSAVED_CHANGES": "Vous avez des modifications non enregistrées", + "DISCARD_CHANGES": "Annuler les modifications", + "UNSAVED_DIALOG_TITLE": "Modifications non enregistrées", + "UNSAVED_DIALOG_MESSAGE": "Vous avez des modifications non enregistrées dans les paramètres. Voulez-vous les enregistrer avant de quitter ?", + "UNSAVED_DIALOG_SAVE": "Enregistrer et quitter", + "UNSAVED_DIALOG_DISCARD": "Quitter sans enregistrer", + "UNSAVED_DIALOG_STAY": "Continuer la modification", + "UNSAVED_DIALOG_INVALID_HINT": "Certains champs sont invalides, les modifications ne peuvent donc pas encore être enregistrées.", "BACK_TO_HOME": "Retourner à l'accueil", "NEW_VERSION_AVAILABLE": "Une nouvelle version est disponible", "LATEST_VERSION": "Vous utilisez la dernière version", diff --git a/apps/web/src/assets/i18n/hu.json b/apps/web/src/assets/i18n/hu.json index 4e58d90cb..024f84bb2 100644 --- a/apps/web/src/assets/i18n/hu.json +++ b/apps/web/src/assets/i18n/hu.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Válasszon egy lehetőséget", "VERSION": "Verzió", "SAVE_CHANGES": "Változtatások mentése", + "UNSAVED_CHANGES": "Nem mentett módosításaid vannak", + "DISCARD_CHANGES": "Elvetés", + "UNSAVED_DIALOG_TITLE": "Nem mentett módosítások", + "UNSAVED_DIALOG_MESSAGE": "Nem mentett módosításaid vannak a beállításokban. Szeretnéd menteni őket, mielőtt kilépsz?", + "UNSAVED_DIALOG_SAVE": "Mentés és kilépés", + "UNSAVED_DIALOG_DISCARD": "Kilépés mentés nélkül", + "UNSAVED_DIALOG_STAY": "Szerkesztés folytatása", + "UNSAVED_DIALOG_INVALID_HINT": "Néhány mező érvénytelen, ezért a módosítások még nem menthetők.", "BACK_TO_HOME": "Vissza", "NEW_VERSION_AVAILABLE": "Új verzió érhető el", "LATEST_VERSION": "A legújabb verziót használja", diff --git a/apps/web/src/assets/i18n/it.json b/apps/web/src/assets/i18n/it.json index 6cf7f5076..f61efee1e 100644 --- a/apps/web/src/assets/i18n/it.json +++ b/apps/web/src/assets/i18n/it.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Seleziona una opzione", "VERSION": "Versione", "SAVE_CHANGES": "Salva modifiche", + "UNSAVED_CHANGES": "Hai modifiche non salvate", + "DISCARD_CHANGES": "Annulla modifiche", + "UNSAVED_DIALOG_TITLE": "Modifiche non salvate", + "UNSAVED_DIALOG_MESSAGE": "Hai modifiche alle impostazioni non salvate. Vuoi salvarle prima di uscire?", + "UNSAVED_DIALOG_SAVE": "Salva ed esci", + "UNSAVED_DIALOG_DISCARD": "Esci senza salvare", + "UNSAVED_DIALOG_STAY": "Continua a modificare", + "UNSAVED_DIALOG_INVALID_HINT": "Alcuni campi non sono validi, quindi le modifiche non possono ancora essere salvate.", "BACK_TO_HOME": "Indietro", "NEW_VERSION_AVAILABLE": "È disponibile una nuova versione", "LATEST_VERSION": "Questa versione è aggiornata", diff --git a/apps/web/src/assets/i18n/ja.json b/apps/web/src/assets/i18n/ja.json index f1b232f65..95001906d 100644 --- a/apps/web/src/assets/i18n/ja.json +++ b/apps/web/src/assets/i18n/ja.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "オプションを選択", "VERSION": "バージョン", "SAVE_CHANGES": "変更を保存", + "UNSAVED_CHANGES": "保存されていない変更があります", + "DISCARD_CHANGES": "破棄", + "UNSAVED_DIALOG_TITLE": "未保存の変更", + "UNSAVED_DIALOG_MESSAGE": "設定に未保存の変更があります。移動する前に保存しますか?", + "UNSAVED_DIALOG_SAVE": "保存して移動", + "UNSAVED_DIALOG_DISCARD": "保存せずに移動", + "UNSAVED_DIALOG_STAY": "編集を続ける", + "UNSAVED_DIALOG_INVALID_HINT": "一部の項目が無効なため、変更をまだ保存できません。", "BACK_TO_HOME": "戻る", "NEW_VERSION_AVAILABLE": "新しいバージョンが利用可能です", "LATEST_VERSION": "最新バージョンを使用中です", diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json index 1ce444e63..5df70bf5c 100644 --- a/apps/web/src/assets/i18n/ko.json +++ b/apps/web/src/assets/i18n/ko.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "옵션을 선택하세요", "VERSION": "버전", "SAVE_CHANGES": "변경 사항 저장", + "UNSAVED_CHANGES": "저장되지 않은 변경 사항이 있습니다", + "DISCARD_CHANGES": "취소", + "UNSAVED_DIALOG_TITLE": "저장되지 않은 변경 사항", + "UNSAVED_DIALOG_MESSAGE": "설정에 저장되지 않은 변경 사항이 있습니다. 나가기 전에 저장하시겠습니까?", + "UNSAVED_DIALOG_SAVE": "저장하고 나가기", + "UNSAVED_DIALOG_DISCARD": "저장하지 않고 나가기", + "UNSAVED_DIALOG_STAY": "계속 편집", + "UNSAVED_DIALOG_INVALID_HINT": "일부 항목이 유효하지 않아 변경 사항을 아직 저장할 수 없습니다.", "BACK_TO_HOME": "홈으로", "NEW_VERSION_AVAILABLE": "새로운 버전이 있습니다", "LATEST_VERSION": "최신 버전을 사용하고 있습니다", diff --git a/apps/web/src/assets/i18n/nl.json b/apps/web/src/assets/i18n/nl.json index 25394c72f..e7794a7ee 100644 --- a/apps/web/src/assets/i18n/nl.json +++ b/apps/web/src/assets/i18n/nl.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Selecteer een optie", "VERSION": "Versie", "SAVE_CHANGES": "Wijzigingen opslaan", + "UNSAVED_CHANGES": "Je hebt niet-opgeslagen wijzigingen", + "DISCARD_CHANGES": "Verwerpen", + "UNSAVED_DIALOG_TITLE": "Niet-opgeslagen wijzigingen", + "UNSAVED_DIALOG_MESSAGE": "Je hebt niet-opgeslagen wijzigingen in de instellingen. Wil je ze opslaan voordat je vertrekt?", + "UNSAVED_DIALOG_SAVE": "Opslaan en verlaten", + "UNSAVED_DIALOG_DISCARD": "Verlaten zonder opslaan", + "UNSAVED_DIALOG_STAY": "Verder bewerken", + "UNSAVED_DIALOG_INVALID_HINT": "Sommige velden zijn ongeldig, dus de wijzigingen kunnen nog niet worden opgeslagen.", "BACK_TO_HOME": "Terug", "NEW_VERSION_AVAILABLE": "Een nieuwe versie is beschikbaar", "LATEST_VERSION": "Je gebruikt de nieuwste versie", diff --git a/apps/web/src/assets/i18n/pl.json b/apps/web/src/assets/i18n/pl.json index 277d699b0..0e7d6d2cb 100644 --- a/apps/web/src/assets/i18n/pl.json +++ b/apps/web/src/assets/i18n/pl.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Wybierz opcję", "VERSION": "Wersja", "SAVE_CHANGES": "Zapisz zmiany", + "UNSAVED_CHANGES": "Masz niezapisane zmiany", + "DISCARD_CHANGES": "Odrzuć", + "UNSAVED_DIALOG_TITLE": "Niezapisane zmiany", + "UNSAVED_DIALOG_MESSAGE": "Masz niezapisane zmiany ustawień. Czy chcesz je zapisać przed wyjściem?", + "UNSAVED_DIALOG_SAVE": "Zapisz i wyjdź", + "UNSAVED_DIALOG_DISCARD": "Wyjdź bez zapisywania", + "UNSAVED_DIALOG_STAY": "Kontynuuj edycję", + "UNSAVED_DIALOG_INVALID_HINT": "Niektóre pola są nieprawidłowe, więc zmian nie można jeszcze zapisać.", "BACK_TO_HOME": "Wróć", "NEW_VERSION_AVAILABLE": "Dostępna jest nowa wersja", "LATEST_VERSION": "Używasz najnowszej wersji", diff --git a/apps/web/src/assets/i18n/pt.json b/apps/web/src/assets/i18n/pt.json index 6ae7c2086..d10b91f97 100644 --- a/apps/web/src/assets/i18n/pt.json +++ b/apps/web/src/assets/i18n/pt.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Selecione uma opção", "VERSION": "Versão", "SAVE_CHANGES": "Salvar alterações", + "UNSAVED_CHANGES": "Você tem alterações não salvas", + "DISCARD_CHANGES": "Descartar", + "UNSAVED_DIALOG_TITLE": "Alterações não salvas", + "UNSAVED_DIALOG_MESSAGE": "Você tem alterações não salvas nas configurações. Deseja salvá-las antes de sair?", + "UNSAVED_DIALOG_SAVE": "Salvar e sair", + "UNSAVED_DIALOG_DISCARD": "Sair sem salvar", + "UNSAVED_DIALOG_STAY": "Continuar editando", + "UNSAVED_DIALOG_INVALID_HINT": "Alguns campos são inválidos, então as alterações ainda não podem ser salvas.", "BACK_TO_HOME": "Voltar", "NEW_VERSION_AVAILABLE": "Há uma nova versão disponível", "LATEST_VERSION": "Você está usando a versão mais recente", diff --git a/apps/web/src/assets/i18n/ru.json b/apps/web/src/assets/i18n/ru.json index a21a0a70e..902ade781 100644 --- a/apps/web/src/assets/i18n/ru.json +++ b/apps/web/src/assets/i18n/ru.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Выберите из списка", "VERSION": "Версия приложения", "SAVE_CHANGES": "Сохранить", + "UNSAVED_CHANGES": "У вас есть несохранённые изменения", + "DISCARD_CHANGES": "Отменить изменения", + "UNSAVED_DIALOG_TITLE": "Несохранённые изменения", + "UNSAVED_DIALOG_MESSAGE": "У вас есть несохранённые изменения настроек. Сохранить их перед выходом?", + "UNSAVED_DIALOG_SAVE": "Сохранить и выйти", + "UNSAVED_DIALOG_DISCARD": "Выйти без сохранения", + "UNSAVED_DIALOG_STAY": "Продолжить редактирование", + "UNSAVED_DIALOG_INVALID_HINT": "Некоторые поля заполнены неверно, поэтому изменения пока нельзя сохранить.", "BACK_TO_HOME": "Назад", "NEW_VERSION_AVAILABLE": "Доступна новая версия приложения", "LATEST_VERSION": "Вы используете последнюю версию приложения", diff --git a/apps/web/src/assets/i18n/tr.json b/apps/web/src/assets/i18n/tr.json index 1fd641464..d56b44e63 100644 --- a/apps/web/src/assets/i18n/tr.json +++ b/apps/web/src/assets/i18n/tr.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "Bir seçenek belirleyin", "VERSION": "Sürüm", "SAVE_CHANGES": "Değişiklikleri kaydet", + "UNSAVED_CHANGES": "Kaydedilmemiş değişiklikleriniz var", + "DISCARD_CHANGES": "Vazgeç", + "UNSAVED_DIALOG_TITLE": "Kaydedilmemiş değişiklikler", + "UNSAVED_DIALOG_MESSAGE": "Ayarlarda kaydedilmemiş değişiklikleriniz var. Çıkmadan önce kaydetmek ister misiniz?", + "UNSAVED_DIALOG_SAVE": "Kaydet ve çık", + "UNSAVED_DIALOG_DISCARD": "Kaydetmeden çık", + "UNSAVED_DIALOG_STAY": "Düzenlemeye devam et", + "UNSAVED_DIALOG_INVALID_HINT": "Bazı alanlar geçersiz olduğundan değişiklikler henüz kaydedilemiyor.", "BACK_TO_HOME": "Ana sayfaya dön", "NEW_VERSION_AVAILABLE": "Yeni bir sürüm mevcut", "LATEST_VERSION": "En son sürümü kullanıyorsunuz", diff --git a/apps/web/src/assets/i18n/zh.json b/apps/web/src/assets/i18n/zh.json index 6d0b5e1cb..f6f2b3453 100644 --- a/apps/web/src/assets/i18n/zh.json +++ b/apps/web/src/assets/i18n/zh.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "选择一个选项", "VERSION": "版本", "SAVE_CHANGES": "保存更改", + "UNSAVED_CHANGES": "您有未保存的更改", + "DISCARD_CHANGES": "放弃更改", + "UNSAVED_DIALOG_TITLE": "未保存的更改", + "UNSAVED_DIALOG_MESSAGE": "设置中有未保存的更改。要在离开前保存吗?", + "UNSAVED_DIALOG_SAVE": "保存并离开", + "UNSAVED_DIALOG_DISCARD": "不保存直接离开", + "UNSAVED_DIALOG_STAY": "继续编辑", + "UNSAVED_DIALOG_INVALID_HINT": "部分字段无效,因此暂时无法保存更改。", "BACK_TO_HOME": "回到主页", "NEW_VERSION_AVAILABLE": "有新版本可用 ", "LATEST_VERSION": "您使用的是最新版本", diff --git a/apps/web/src/assets/i18n/zhtw.json b/apps/web/src/assets/i18n/zhtw.json index 211b53c88..28db11407 100644 --- a/apps/web/src/assets/i18n/zhtw.json +++ b/apps/web/src/assets/i18n/zhtw.json @@ -298,6 +298,14 @@ "VIDEO_PLAYER_PLACEHOLDER": "選擇一個選項", "VERSION": "版本", "SAVE_CHANGES": "儲存變更", + "UNSAVED_CHANGES": "您有未儲存的變更", + "DISCARD_CHANGES": "捨棄變更", + "UNSAVED_DIALOG_TITLE": "未儲存的變更", + "UNSAVED_DIALOG_MESSAGE": "設定中有未儲存的變更。要在離開前儲存嗎?", + "UNSAVED_DIALOG_SAVE": "儲存並離開", + "UNSAVED_DIALOG_DISCARD": "不儲存直接離開", + "UNSAVED_DIALOG_STAY": "繼續編輯", + "UNSAVED_DIALOG_INVALID_HINT": "部分欄位無效,因此暫時無法儲存變更。", "BACK_TO_HOME": "返回主頁", "NEW_VERSION_AVAILABLE": "有新版本可用", "LATEST_VERSION": "您正在使用最新版本", diff --git a/docs/architecture/nx-workspace-boundaries.md b/docs/architecture/nx-workspace-boundaries.md index 60286913f..d55cd9356 100644 --- a/docs/architecture/nx-workspace-boundaries.md +++ b/docs/architecture/nx-workspace-boundaries.md @@ -52,7 +52,7 @@ resulting PR runs the full CI pipeline. ## Vite Dev-Server Patch -Angular's development builder currently resolves Vite `7.3.5`. That release's +Angular's development builder currently resolves Vite `7.3.6`. That release's asset and worker transform prefilters can catastrophically backtrack on a large generated chunk containing unrelated `new URL...` expressions while searching for a valid `new URL(..., import.meta.url)` construct. The Electron development @@ -60,12 +60,12 @@ server can then fail a lazy chunk request with `Maximum call stack size exceeded`, even though static builds succeed because they do not pass emitted chunks through Vite's request-time plugin container. -`patches/vite@7.3.5.patch` backports Vite's upstream precise-matcher fix from +`patches/vite@7.3.6.patch` backports Vite's upstream precise-matcher fix from [vitejs/vite#21800](https://github.com/vitejs/vite/pull/21800). Bounded prefilters keep the request-time scan linear while allowing comment-bearing asset and worker expressions to reach the precise matcher after Vite strips comments. Keep the patch while the supported Angular toolchain resolves Vite -`7.3.5`; remove it only after the resolved Vite contains the upstream fix. Run +`7.3.6`; remove it only after the resolved Vite contains the upstream fix. Run the regression check after any related manifest or lockfile update: ```bash diff --git a/docs/architecture/workspace-shell.md b/docs/architecture/workspace-shell.md index 9b984e897..cb84a7dd4 100644 --- a/docs/architecture/workspace-shell.md +++ b/docs/architecture/workspace-shell.md @@ -51,7 +51,8 @@ Current workspace routes: 7. `/workspace/global-recent` 8. `/workspace/search` 9. `/workspace/downloads` -10. `/workspace/settings` +10. `/workspace/settings/:section` (`/workspace/settings` redirects to + `general`; the settings context panel links each section page) 11. `/workspace/xtreams/:id/...` 12. `/workspace/stalker/:id/...` @@ -130,7 +131,7 @@ The shell decides which secondary panel to show from the current route: 1. `WorkspaceContextPanelComponent` 3. Stalker category sections (`itv`, `radio`, `vod`, `series`) 1. `WorkspaceContextPanelComponent` -4. `/workspace/settings` +4. `/workspace/settings/:section` 1. `WorkspaceSettingsContextPanelComponent` 5. Downloads sections 1. `WorkspaceCollectionContextPanelComponent` diff --git a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.html b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.html index 3e50589e0..7e52028da 100644 --- a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.html +++ b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.html @@ -125,6 +125,7 @@ " [summary]="liveEpgPanelSummary()" [summaryLabelKey]="liveEpgPanelSummaryLabelKey()" + [emptyReason]="liveEpgEmptyReason()" (programActivated)=" onTimelineProgramActivated($event) " @@ -135,6 +136,7 @@ (collapsedChange)=" onLiveEpgPanelCollapsedChange($event) " + (openEpgSettings)="openEpgSettings()" /> } @else { } diff --git a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.spec.ts b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.spec.ts index 7bd2ab596..cb3bdc3f4 100644 --- a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.spec.ts +++ b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.spec.ts @@ -196,6 +196,7 @@ describe('VideoPlayerComponent', () => { const showCaptions = signal(false); const stripCountryPrefix = signal(false); const epgViewMode = signal<'timeline' | 'list'>('timeline'); + const epgUrlSetting = signal([]); const originalElectron = window.electron; const overlayRef = { @@ -397,6 +398,7 @@ describe('VideoPlayerComponent', () => { showCaptions, stripCountryPrefix, resolvedEpgViewMode: epgViewMode, + epgUrl: epgUrlSetting, }, }, { @@ -1174,6 +1176,45 @@ describe('VideoPlayerComponent', () => { EpgActions.resetActiveEpgProgram() ); }); + + describe('EPG needs-setup empty state', () => { + beforeEach(() => { + // Earlier tests leave programmes in the shared subject; the + // component keeps a live subscription, so this reset reaches it. + epgUrlSetting.set([]); + epgPrograms$.next([]); + }); + + afterEach(() => { + epgUrlSetting.set([]); + epgPrograms$.next([]); + }); + + it('claims needs-setup only while no EPG source exists anywhere', () => { + expect(component.liveEpgEmptyReason()).toBe('m3u-needs-setup'); + + epgUrlSetting.set(['https://example.org/guide.xml']); + + expect(component.liveEpgEmptyReason()).toBe('none'); + }); + + it('never overrides a channel that actually has programmes', () => { + // Uploaded XMLTV files produce programmes without any + // configured source URL — the ribbon must win over the hint. + epgPrograms$.next([buildProgram('Morning Bulletin')]); + + expect(component.liveEpgEmptyReason()).toBe('none'); + }); + + it('deep links the empty-state button to the EPG settings page', () => { + component.openEpgSettings(); + + expect(routerMock.navigate).toHaveBeenCalledWith([ + '/workspace/settings', + 'epg', + ]); + }); + }); }); function buildProgram(title: string): EpgProgram { diff --git a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts index 72714b01c..b014929ae 100644 --- a/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts +++ b/libs/playlist/m3u/feature-player/src/lib/video-player/video-player.component.ts @@ -37,6 +37,7 @@ import { EpgListViewComponent, EpgProgramActivationEvent, EpgTimelineComponent, + EpgTimelineEmptyReason, getTodayEpgDateKey, MultiEpgContainerComponent, shiftEpgDateKey, @@ -51,6 +52,7 @@ import { selectActive, selectActiveEpgProgram, selectActivePlaybackUrl, + selectActivePlaylist, selectChannels, selectChannelsLoading, selectCurrentEpgProgram, @@ -358,6 +360,34 @@ export class VideoPlayerComponent implements OnInit, OnDestroy { ? 'EPG.ARCHIVE_PLAYBACK' : 'EPG.CURRENT_PROGRAM' ); + private readonly activePlaylistForEpg = + this.store.selectSignal(selectActivePlaylist); + /** + * Without a single configured XMLTV source the whole playlist has no EPG, + * so the panel's empty state should point at the EPG settings page + * instead of implying that just this channel is unmapped. Only claims + * "needs setup" when nothing contradicts it: no programmes for the + * channel (uploaded XMLTV files produce programmes without any URL), no + * global source in settings (legacy values may be a plain string), and no + * playlist-scoped `url-tvg` source either. + */ + readonly liveEpgEmptyReason = computed(() => { + if (this.epgPrograms().length > 0) { + return 'none'; + } + + const globalSources = this.settingsStore.epgUrl?.() ?? []; + const hasGlobalSources = Array.isArray(globalSources) + ? globalSources.some((url) => Boolean(url?.trim?.())) + : Boolean(globalSources); + const hasPlaylistSources = ( + this.activePlaylistForEpg()?.epgUrls ?? [] + ).some((url) => Boolean(url?.trim?.())); + + return hasGlobalSources || hasPlaylistSources + ? 'none' + : 'm3u-needs-setup'; + }); readonly showReturnToLive = computed( () => this.activeEpgProgramOrNull() !== null ); @@ -705,6 +735,11 @@ export class VideoPlayerComponent implements OnInit, OnDestroy { this.store.dispatch(EpgActions.returnToLivePlayback()); } + /** Deep link from the EPG panel's "needs setup" empty state */ + openEpgSettings(): void { + void this.router.navigate(['/workspace/settings', 'epg']); + } + onTimelineProgramActivated(event: EpgProgramActivationEvent): void { if (event.type === 'live') { this.returnToLivePlayback(); diff --git a/libs/playlist/shared/util/src/index.ts b/libs/playlist/shared/util/src/index.ts index 317f2d1c9..7fc8eefe5 100644 --- a/libs/playlist/shared/util/src/index.ts +++ b/libs/playlist/shared/util/src/index.ts @@ -1,3 +1,2 @@ -export * from './lib/playlist-player-actions'; export * from './lib/playlist-context.facade'; export * from './lib/playlist-file-import.service'; diff --git a/libs/playlist/shared/util/src/lib/playlist-player-actions.ts b/libs/playlist/shared/util/src/lib/playlist-player-actions.ts deleted file mode 100644 index 2e52f330b..000000000 --- a/libs/playlist/shared/util/src/lib/playlist-player-actions.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { InjectionToken } from '@angular/core'; - -export interface PlaylistPlayerActions { - openSettings(): void; -} - -export const PLAYLIST_PLAYER_ACTIONS = - new InjectionToken('PLAYLIST_PLAYER_ACTIONS'); diff --git a/libs/portal/shared/util/src/index.ts b/libs/portal/shared/util/src/index.ts index 2ab7e80d7..ef9d78bc8 100644 --- a/libs/portal/shared/util/src/index.ts +++ b/libs/portal/shared/util/src/index.ts @@ -8,7 +8,6 @@ export * from './lib/portal-external-playback'; export * from './lib/portal-player'; export * from './lib/portal-playback-positions'; export * from './lib/series-quick-start'; -export * from './lib/portal-navigation-actions'; export * from './lib/portal-shell-actions'; export * from './lib/portal-collection-context'; export * from './lib/portal-collection-context.service'; diff --git a/libs/portal/shared/util/src/lib/portal-navigation-actions.ts b/libs/portal/shared/util/src/lib/portal-navigation-actions.ts deleted file mode 100644 index ed80f0a49..000000000 --- a/libs/portal/shared/util/src/lib/portal-navigation-actions.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { InjectionToken } from '@angular/core'; -import { Playlist } from '@iptvnator/shared/interfaces'; - -export interface PortalNavigationActions { - openAccountInfo(): void; - openPlaylistInfo(playlist: Playlist | null | undefined): void; - openSettings(): void; -} - -export const PORTAL_NAVIGATION_ACTIONS = - new InjectionToken('PORTAL_NAVIGATION_ACTIONS'); diff --git a/libs/workspace/shell/feature/src/lib/workspace-context-panel/workspace-settings-context-panel.component.ts b/libs/workspace/shell/feature/src/lib/workspace-context-panel/workspace-settings-context-panel.component.ts index 7e13edd56..568695847 100644 --- a/libs/workspace/shell/feature/src/lib/workspace-context-panel/workspace-settings-context-panel.component.ts +++ b/libs/workspace/shell/feature/src/lib/workspace-context-panel/workspace-settings-context-panel.component.ts @@ -1,31 +1,37 @@ import { Location } from '@angular/common'; import { Component, inject } from '@angular/core'; import { MatIconModule } from '@angular/material/icon'; +import { RouterLink, RouterLinkActive } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { WorkspaceShellContextDrawerService, - SettingsContextService + SettingsContextService, } from '@iptvnator/workspace/shell/util'; @Component({ selector: 'app-workspace-settings-context-panel', - imports: [MatIconModule, TranslateModule], + imports: [MatIconModule, RouterLink, RouterLinkActive, TranslateModule], styleUrls: ['./workspace-settings-context-panel.component.scss'], template: `

{{ 'SETTINGS.TITLE' | translate }}

@@ -44,15 +50,15 @@ import { export class WorkspaceSettingsContextPanelComponent { readonly ctx = inject(SettingsContextService); private readonly location = inject(Location); - // Root-provided; optional keeps standalone unit tests light. Section clicks - // scroll the settings page without navigating, so the phone drawer's - // NavigationEnd auto-close never fires for them. + // Root-provided; optional keeps standalone unit tests light. Section + // links are real navigations now, so the phone drawer's NavigationEnd + // auto-close fires too — the explicit close just makes the drawer react + // immediately instead of waiting for the navigation to settle. private readonly contextDrawer = inject(WorkspaceShellContextDrawerService, { optional: true, }); - onSectionClicked(sectionId: string) { - this.ctx.navigateToSection(sectionId); + onSectionClicked() { this.contextDrawer?.close(); } diff --git a/libs/workspace/shell/util/src/lib/settings-context.service.ts b/libs/workspace/shell/util/src/lib/settings-context.service.ts index ead1e906d..c1029547b 100644 --- a/libs/workspace/shell/util/src/lib/settings-context.service.ts +++ b/libs/workspace/shell/util/src/lib/settings-context.service.ts @@ -6,32 +6,22 @@ export interface SettingsNavItem { icon: string; } +/** + * Bridge between the routed settings page and the workspace context panel: + * the page publishes which section pages exist for the current runtime, the + * panel renders them as router links to `/workspace/settings/:section`. + * Active-state highlighting comes from the router (`routerLinkActive`), not + * from this service. + */ @Injectable({ providedIn: 'root' }) export class SettingsContextService { readonly sections = signal([]); - readonly activeSection = signal('general'); - readonly pendingScrollTarget = signal(null); setSections(items: SettingsNavItem[]): void { this.sections.set(items); } - setActiveSection(id: string): void { - this.activeSection.set(id); - } - - navigateToSection(id: string): void { - this.activeSection.set(id); - this.pendingScrollTarget.set(id); - } - - clearPendingScrollTarget(): void { - this.pendingScrollTarget.set(null); - } - reset(): void { this.sections.set([]); - this.activeSection.set('general'); - this.pendingScrollTarget.set(null); } } diff --git a/package.json b/package.json index dafc5a355..4b463d05b 100644 --- a/package.json +++ b/package.json @@ -81,16 +81,16 @@ "private": true, "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319", "dependencies": { - "@angular/animations": "21.2.17", + "@angular/animations": "21.2.19", "@angular/cdk": "21.2.14", - "@angular/common": "21.2.17", - "@angular/compiler": "21.2.17", - "@angular/core": "21.2.17", - "@angular/forms": "21.2.17", + "@angular/common": "21.2.19", + "@angular/compiler": "21.2.19", + "@angular/core": "21.2.19", + "@angular/forms": "21.2.19", "@angular/material": "21.2.14", - "@angular/platform-browser": "21.2.17", - "@angular/platform-browser-dynamic": "21.2.17", - "@angular/router": "21.2.17", + "@angular/platform-browser": "21.2.19", + "@angular/platform-browser-dynamic": "21.2.19", + "@angular/router": "21.2.19", "@ngrx/effects": "21.1.1", "@ngrx/entity": "21.1.1", "@ngrx/router-store": "21.1.1", @@ -125,25 +125,25 @@ "zone.js": "~0.16.2" }, "devDependencies": { - "@angular-devkit/core": "21.2.17", - "@angular-devkit/schematics": "21.2.17", + "@angular-devkit/core": "21.2.19", + "@angular-devkit/schematics": "21.2.19", "@angular-eslint/builder": "21.3.1", "@angular-eslint/eslint-plugin": "21.3.1", "@angular-eslint/eslint-plugin-template": "21.3.1", "@angular-eslint/schematics": "21.3.1", "@angular-eslint/template-parser": "21.3.1", - "@angular/build": "21.2.17", - "@angular/cli": "21.2.17", - "@angular/common": "21.2.17", - "@angular/compiler": "21.2.17", - "@angular/compiler-cli": "21.2.17", - "@angular/core": "21.2.17", - "@angular/forms": "21.2.17", - "@angular/language-service": "21.2.17", - "@angular/platform-browser": "21.2.17", - "@angular/platform-browser-dynamic": "21.2.17", - "@angular/router": "21.2.17", - "@angular/service-worker": "21.2.17", + "@angular/build": "21.2.19", + "@angular/cli": "21.2.19", + "@angular/common": "21.2.19", + "@angular/compiler": "21.2.19", + "@angular/compiler-cli": "21.2.19", + "@angular/core": "21.2.19", + "@angular/forms": "21.2.19", + "@angular/language-service": "21.2.19", + "@angular/platform-browser": "21.2.19", + "@angular/platform-browser-dynamic": "21.2.19", + "@angular/router": "21.2.19", + "@angular/service-worker": "21.2.19", "@astrojs/mdx": "4.3.13", "@astrojs/sitemap": "3.7.3", "@astrojs/tailwind": "6.0.2", @@ -169,7 +169,7 @@ "@nx/web": "22.7.2", "@nx/workspace": "22.7.2", "@playwright/test": "^1.62.0", - "@schematics/angular": "21.2.9", + "@schematics/angular": "21.2.19", "@swc-node/register": "1.12.1", "@swc/core": "1.15.46", "@swc/helpers": "0.5.23", @@ -252,7 +252,7 @@ }, "patchedDependencies": { "nx-electron@22.0.0": "patches/nx-electron@22.0.0.patch", - "vite@7.3.5": "patches/vite@7.3.5.patch" + "vite@7.3.6": "patches/vite@7.3.6.patch" } } } diff --git a/patches/vite@7.3.5.patch b/patches/vite@7.3.6.patch similarity index 96% rename from patches/vite@7.3.5.patch rename to patches/vite@7.3.6.patch index 060f7642d..7990eb340 100644 --- a/patches/vite@7.3.5.patch +++ b/patches/vite@7.3.6.patch @@ -1,5 +1,4 @@ diff --git a/dist/node/chunks/config.js b/dist/node/chunks/config.js -index 9a45043275249a25101fd7991ffcfc316478840e..5435b17de9ca65b64a8abacb609b75587226b106 100644 --- a/dist/node/chunks/config.js +++ b/dist/node/chunks/config.js @@ -27667,7 +27667,8 @@ async function getWorkerType(raw, clean, i$1) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d73e4ea23..be275c863 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,71 +35,71 @@ patchedDependencies: nx-electron@22.0.0: hash: f4bbde1778360c4c462b255bec47a337c0465d59cdcab14ecb601161f3467002 path: patches/nx-electron@22.0.0.patch - vite@7.3.5: - hash: b3a8f88ab420b6504a61ffb0f8e402f112c7fda7f3f3e802d21272da7969882d - path: patches/vite@7.3.5.patch + vite@7.3.6: + hash: 215b6585a9c92fa68c096d500f4676983200307b1e64c1321e20ccbd50bbc8f3 + path: patches/vite@7.3.6.patch importers: .: dependencies: '@angular/animations': - specifier: 21.2.17 - version: 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + specifier: 21.2.19 + version: 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) '@angular/cdk': specifier: 21.2.14 - version: 21.2.14(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + version: 21.2.14(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/common': - specifier: 21.2.17 - version: 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + specifier: 21.2.19 + version: 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@angular/compiler': - specifier: 21.2.17 - version: 21.2.17 + specifier: 21.2.19 + version: 21.2.19 '@angular/core': - specifier: 21.2.17 - version: 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + specifier: 21.2.19 + version: 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) '@angular/forms': - specifier: 21.2.17 - version: 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 21.2.19 + version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@angular/material': specifier: 21.2.14 - version: 21.2.14(43172ba04e47f305707a39eaf8cab87a) + version: 21.2.14(e62c7210bef08c270f76f8032e5d0530) '@angular/platform-browser': - specifier: 21.2.17 - version: 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + specifier: 21.2.19 + version: 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) '@angular/platform-browser-dynamic': - specifier: 21.2.17 - version: 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@21.2.17)(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))) + specifier: 21.2.19 + version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))) '@angular/router': - specifier: 21.2.17 - version: 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + specifier: 21.2.19 + version: 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) '@ngrx/effects': specifier: 21.1.1 - version: 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) + version: 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) '@ngrx/entity': specifier: 21.1.1 - version: 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) + version: 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) '@ngrx/router-store': specifier: 21.1.1 - version: 21.1.1(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/router@21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) + version: 21.1.1(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/router@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) '@ngrx/signals': specifier: 21.1.1 - version: 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + version: 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@ngrx/store': specifier: 21.1.1 - version: 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + version: 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@ngrx/store-devtools': specifier: 21.1.1 - version: 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) + version: 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2) '@ngx-pwa/local-storage': specifier: 21.0.0 - version: 21.0.0(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + version: 21.0.0(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@yangkghjh/videojs-aspect-ratio-panel': specifier: 0.0.1 version: 0.0.1 angularx-qrcode: specifier: 21.0.5 - version: 21.0.5(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + version: 21.0.5(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) artplayer: specifier: 5.4.0 version: 5.4.0 @@ -144,10 +144,10 @@ importers: version: 2.1.3 ngx-indexed-db: specifier: 21.0.0 - version: 21.0.0(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + version: 21.0.0(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) ngx-skeleton-loader: specifier: 11.3.0 - version: 11.3.0(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + version: 11.3.0(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) rxjs: specifier: 7.8.2 version: 7.8.2 @@ -171,14 +171,14 @@ importers: version: 0.16.2 devDependencies: '@angular-devkit/core': - specifier: 21.2.17 - version: 21.2.17(chokidar@5.0.0) + specifier: 21.2.19 + version: 21.2.19(chokidar@5.0.0) '@angular-devkit/schematics': - specifier: 21.2.17 - version: 21.2.17(chokidar@5.0.0) + specifier: 21.2.19 + version: 21.2.19(chokidar@5.0.0) '@angular-eslint/builder': specifier: 21.3.1 - version: 21.3.1(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + version: 21.3.1(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/eslint-plugin': specifier: 21.3.1 version: 21.3.1(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) @@ -187,25 +187,25 @@ importers: version: 21.3.1(@angular-eslint/template-parser@21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/schematics': specifier: 21.3.1 - version: 21.3.1(@angular-eslint/template-parser@21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + version: 21.3.1(@angular-eslint/template-parser@21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/template-parser': specifier: 21.3.1 version: 21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular/build': - specifier: 21.2.17 - version: 21.2.17(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3))(@angular/compiler@21.2.17)(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/service-worker@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@types/node@20.19.9)(chokidar@5.0.0)(jiti@1.21.7)(less@4.5.1)(postcss@8.5.6)(sass-embedded@1.97.1)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0) + specifier: 21.2.19 + version: 21.2.19(@angular/compiler-cli@21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/service-worker@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3)(@types/node@20.19.9)(chokidar@5.0.0)(jiti@1.21.7)(less@4.5.1)(postcss@8.5.6)(sass-embedded@1.97.1)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0) '@angular/cli': - specifier: 21.2.17 - version: 21.2.17(@types/node@20.19.9)(chokidar@5.0.0) + specifier: 21.2.19 + version: 21.2.19(@types/node@20.19.9)(chokidar@5.0.0) '@angular/compiler-cli': - specifier: 21.2.17 - version: 21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3) + specifier: 21.2.19 + version: 21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3) '@angular/language-service': - specifier: 21.2.17 - version: 21.2.17 + specifier: 21.2.19 + version: 21.2.19 '@angular/service-worker': - specifier: 21.2.17 - version: 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + specifier: 21.2.19 + version: 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) '@astrojs/mdx': specifier: 4.3.13 version: 4.3.13(astro@5.18.1(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(rollup@4.59.0)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0)) @@ -244,37 +244,37 @@ importers: version: 21.1.1(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript-eslint@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(typescript@5.9.3) '@ngx-translate/core': specifier: 16.0.4 - version: 16.0.4(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + version: 16.0.4(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) '@ngx-translate/http-loader': specifier: 16.0.1 - version: 16.0.1(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + version: 16.0.1(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) '@nx/angular': specifier: 22.7.2 - version: 22.7.2(5435397b23ab524463bbc1574adf9264) + version: 22.7.2(e218af65d764a685aba0bafd0ced9f6d) '@nx/devkit': specifier: 22.7.2 version: 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@nx/esbuild': specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + version: 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@nx/eslint': specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + version: 22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@nx/eslint-plugin': specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@typescript-eslint/parser@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3) + version: 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@typescript-eslint/parser@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3) '@nx/jest': specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3) + version: 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3) '@nx/js': specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + version: 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@nx/playwright': specifier: 22.7.2 - version: 22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@playwright/test@1.62.0)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + version: 22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@playwright/test@1.62.0)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@nx/web': specifier: 22.7.2 - version: 22.7.2(888f284af7850e1ced4d654d87699281) + version: 22.7.2(0222b886c58439e845e61058a381daaa) '@nx/workspace': specifier: 22.7.2 version: 22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)) @@ -282,8 +282,8 @@ importers: specifier: ^1.62.0 version: 1.62.0 '@schematics/angular': - specifier: 21.2.9 - version: 21.2.9(chokidar@5.0.0) + specifier: 21.2.19 + version: 21.2.19(chokidar@5.0.0) '@swc-node/register': specifier: 1.12.1 version: 1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3) @@ -328,7 +328,7 @@ importers: version: 8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) angular-eslint: specifier: 21.4.0 - version: 21.4.0(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript-eslint@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(typescript@5.9.3) + version: 21.4.0(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript-eslint@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(typescript@5.9.3) astro: specifier: 5.18.1 version: 5.18.1(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(rollup@4.59.0)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0) @@ -388,7 +388,7 @@ importers: version: 30.4.1 jest-preset-angular: specifier: ~15.0.0 - version: 15.0.3(c4e4d73a3616691068af99860e93e092) + version: 15.0.3(98452fae979b413e96b064b581c4172d) jest-util: specifier: ^30.4.1 version: 30.4.1 @@ -400,7 +400,7 @@ importers: version: 6.7.0 ng-mocks: specifier: 14.15.3 - version: 14.15.3(1918f1ef5f9f83bc2aab38921c00c721) + version: 14.15.3(b285834fe0000b6ade3305b52068a4d2) nx: specifier: 22.7.2 version: 22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)) @@ -512,16 +512,16 @@ packages: engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular-devkit/architect@0.2102.17': - resolution: {integrity: sha512-+lkmpEfKXuPZaGZRCCT/B2JGSnafudEVMLeolAW0G7de28bwJIwTE5nmr/rcKTy4NnEDX/8B53tWTXGENuQvmg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - hasBin: true - '@angular-devkit/architect@0.2102.19': resolution: {integrity: sha512-cj4tzUMiloLTg5rNf17E8MsvIxCWYoBiBsaj7ns6dgXqT9XCeG+J0TA2t1M+N9uuqfeLd22U/rYoCkADmcircQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true + '@angular-devkit/architect@0.2102.20': + resolution: {integrity: sha512-s7wPFCMrt9mWMr+NWs4T8849snnOE4DcmLb9Set7KtbhV6Z8E7ZASs/wqPOS3KPxLjxTqM6CnkwKhc3Th6DniA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} + hasBin: true + '@angular-devkit/core@21.1.4': resolution: {integrity: sha512-ObPTI5gYCB1jGxTRhcqZ6oQVUBFVJ8GH4LksVuAiz0nFX7xxpzARWvlhq943EtnlovVlUd9I8fM3RQqjfGVVAQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} @@ -531,15 +531,6 @@ packages: chokidar: optional: true - '@angular-devkit/core@21.2.17': - resolution: {integrity: sha512-JbGWwFX1Nv4Np0S9b4HP2SUKhR2bz6l/S8zBXnam95+RXzDaqXJDmQHOHZGS+4La06SjlcXwFyrgSI0rm50A1A==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - chokidar: ^5.0.0 - peerDependenciesMeta: - chokidar: - optional: true - '@angular-devkit/core@21.2.19': resolution: {integrity: sha512-dtpJMQBz5nhkcIogPmXP/aT2Ak8m/wLRPOSTI/g4vSJSuGiI53PgtWq4/wfQga6E6wdM2XWsblAE89d8w5heQQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} @@ -549,8 +540,8 @@ packages: chokidar: optional: true - '@angular-devkit/core@21.2.9': - resolution: {integrity: sha512-04rdOGEzjLWFHlyAwqtuikginFeQ2jfXS5HqqKNP0VtG6Uu9NUDAEW5UDvXgqkEMfCDwGZbmg2iRHxp3AmAKVw==} + '@angular-devkit/core@21.2.20': + resolution: {integrity: sha512-QViRAYFj3jcElWND79hM6y4vTSYhMlJSOjy9nby9JsQaPgetkf039jI2u9Lp+PduE6lysewzf85d1UGsm3eI0A==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: chokidar: ^5.0.0 @@ -558,12 +549,8 @@ packages: chokidar: optional: true - '@angular-devkit/schematics@21.2.17': - resolution: {integrity: sha512-IMsbo/OBG0mdCRxezbq/CLo6JxUJBOAHZfbUDzxbSRwJm8FT5AbXO7rW+Z3haoqcb+WrC5Pr+DQ6WolX2x2brQ==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - - '@angular-devkit/schematics@21.2.9': - resolution: {integrity: sha512-Gyyuq2Vet70AMkbC+e0L6rjzjZWjSOyKTlOJvd99GjjyWQf6eezjd8IcF17ppKJsML6YUagO2I6AlWROq5yJmg==} + '@angular-devkit/schematics@21.2.19': + resolution: {integrity: sha512-AG3Fzh9wJCmKBfxUQOUWaEHMj5Gq2O+Msf1z52aDSxbVhs5/iSQcXGPv/DLdAXu7d4xmQhLouNe9Glaq2omDyw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@angular-eslint/builder@21.3.1': @@ -654,15 +641,15 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '*' - '@angular/animations@21.2.17': - resolution: {integrity: sha512-zOW8FFa9qfbVkZ5TulxDkl1C3+gEjWfAAD5Z2MycA6pjVJQlLYPiTAGq+flOQ3yZfTT0z6kd5rejQMXWI81Dvg==} + '@angular/animations@21.2.19': + resolution: {integrity: sha512-qC0mviselvpKq2ID9bT+USnCsHKfwZAifkUr5A4h/WCzXvUvpVNWp/RPhGcKeOR+seg3EO5GtIZyblwiRlhzrA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} deprecated: '@angular/animations is deprecated. Use `animate.enter` and `animate.leave` instead. For more information see: https://v22.angular.dev/guide/animations.' peerDependencies: - '@angular/core': 21.2.17 + '@angular/core': 21.2.19 - '@angular/build@21.2.17': - resolution: {integrity: sha512-1tKQoRH8/21lf3Z1+ezaHmzdhAmeJx34wVW69DU+NuumsjDHDuq2YdUbiC936SnI33tDXov5UOBMqzjHe8qUTg==} + '@angular/build@21.2.19': + resolution: {integrity: sha512-emy9mqrTXAwhZzcvx8MaHyz+cUR06PVGxnqy91+bpDxPP9S5x67sPoOkY9y/ETFFhRpB5ULlUxyq0eN/pi6QOg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} peerDependencies: '@angular/compiler': ^21.0.0 @@ -672,7 +659,7 @@ packages: '@angular/platform-browser': ^21.0.0 '@angular/platform-server': ^21.0.0 '@angular/service-worker': ^21.0.0 - '@angular/ssr': ^21.2.17 + '@angular/ssr': ^21.2.19 karma: ^6.4.0 less: ^4.2.0 ng-packagr: ^21.0.0 @@ -715,38 +702,38 @@ packages: '@angular/platform-browser': ^21.0.0 || ^22.0.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/cli@21.2.17': - resolution: {integrity: sha512-wyEPOszxza7kUa1BWyERUqSDmAC/DF5Iun0YJ1sN22jDriOuOlYh9hXSk1EHs06fQ1JcTYLml+timHVHg4V1/w==} + '@angular/cli@21.2.19': + resolution: {integrity: sha512-i78NzvoNonAY17QgzSmqrYnXHmEfraLv4wZ/o/m3efxuz61ZJ+5X/PsCeAhbwBvQfRrPRQaJV2tK9vGjHa+U6w==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} hasBin: true - '@angular/common@21.2.17': - resolution: {integrity: sha512-hqAQxRfi5ldFE42suAXRcY+JCANrUh7fuSQ/DtZ7L896id5BT/exuv6dWNBC1PyAfQmRbpD5Pt6/pd+tNLyhDQ==} + '@angular/common@21.2.19': + resolution: {integrity: sha512-Rvo/VXI0kUmfQT7+OeAjv526OJlf/WrLnJq1Tz84Jkyv9bs9SOMTCT6m4+boo8gxVNdrcxvGU3Q0o2jZzKceSg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/core': 21.2.17 + '@angular/core': 21.2.19 rxjs: ^6.5.3 || ^7.4.0 - '@angular/compiler-cli@21.2.17': - resolution: {integrity: sha512-KithZ3b0HBFH0NbUcswBcjpN9y09vLbarMD7qmGWTnGUBk4W8cn4sbT8zJyv9CRKg9ZcuUBeJYKUfUPn/u/5OQ==} + '@angular/compiler-cli@21.2.19': + resolution: {integrity: sha512-QxWqUvhTWgyYPPkfpupOUIEa3Y5cbzMilaFgRNpkvFy6teARw5Izsd7RxUbj3Tp3xJOi1MtumNmkxLxmv3iv7A==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/compiler': 21.2.17 + '@angular/compiler': 21.2.19 typescript: '>=5.9 <6.1' peerDependenciesMeta: typescript: optional: true - '@angular/compiler@21.2.17': - resolution: {integrity: sha512-p+NdjYiwAz9Zmu2yul0LlMXaFjMISVVa24+/MVMoKFeQeI82QE8jDywPlnOSHQHvdCcQVpS7saeEriZzX3JuBQ==} + '@angular/compiler@21.2.19': + resolution: {integrity: sha512-vuF5i1t14ftJiHXVVLgDYLWkT99QuajphcUHy1VZaMX3FiqSGXRV62g+R2RMxL0OJ5C1ai8xTHKPx9n1lQFyFg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} - '@angular/core@21.2.17': - resolution: {integrity: sha512-wYHpwIdnUnjQFOJJNqRcGx7LS3u64jT+R9L0TnMR/ViBM9dQgGYImlSikkftg2yrFCNo5aKRxhG2LLskQurVdg==} + '@angular/core@21.2.19': + resolution: {integrity: sha512-PVoXD1kBexOJLkFzKx2zBY/0oZJXGru0eGn2hu0q5n3vkZlYsR1yRolfGenK1gZE48Qibiw/ttg/X/pAIPEZGg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/compiler': 21.2.17 + '@angular/compiler': 21.2.19 rxjs: ^6.5.3 || ^7.4.0 zone.js: ~0.15.0 || ~0.16.0 peerDependenciesMeta: @@ -755,17 +742,17 @@ packages: zone.js: optional: true - '@angular/forms@21.2.17': - resolution: {integrity: sha512-WKu8XeRSNZo+a+aDDZ3M5OtReF7KYqR/PmZ2l1lSf6N5EEAmc+Ky4aqbRhTL/mTSfHrO4+TDJ4C5A2tFmuwIeA==} + '@angular/forms@21.2.19': + resolution: {integrity: sha512-tEw8cz2UU6VSB+ReJN86k87nRdLRXGi+8SZhoRl2dFu2iReIO3S6kJAVTH7Y9kdrokqTPhWG+KNEzWgqhdjXOg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.17 - '@angular/core': 21.2.17 - '@angular/platform-browser': 21.2.17 + '@angular/common': 21.2.19 + '@angular/core': 21.2.19 + '@angular/platform-browser': 21.2.19 rxjs: ^6.5.3 || ^7.4.0 - '@angular/language-service@21.2.17': - resolution: {integrity: sha512-Pq0V7VBkShQThA6QME2FjZgHLuxFpsioEoppx1i8rHFTGoJuXtBJK8iaArF7XuYaMzMRInUGfMQzsXc2WE+rmg==} + '@angular/language-service@21.2.19': + resolution: {integrity: sha512-ockDnVB9drvrx1WXPd3n+0mDT0iBAMJsmjBDUijGTOCy4oc+iXPeC2Q+bpiRuM2+rtpo6Z939ZLgvNdh7KrRzQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} '@angular/material@21.2.14': @@ -778,42 +765,42 @@ packages: '@angular/platform-browser': ^21.0.0 || ^22.0.0 rxjs: ^6.5.3 || ^7.4.0 - '@angular/platform-browser-dynamic@21.2.17': - resolution: {integrity: sha512-r/BU/T8bOTghP3fIXhzYf5wcMcAmhWnAFv3p4asCCPXomaktoas70wYcMaDH+pK1LAFBxLwzBWHm36MpFlTMFg==} + '@angular/platform-browser-dynamic@21.2.19': + resolution: {integrity: sha512-Ns+0D4S8A6Bypxgeba0QSDdIIVosOUfSfxDxiC0oN/VrgMBiLAbOROTnoNfOaFRgkV2gUzPNPFdHD2Ciflq+bQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} deprecated: '@angular/platform-browser-dynamic is deprecated. Use `@angular/platform-browser` instead.' peerDependencies: - '@angular/common': 21.2.17 - '@angular/compiler': 21.2.17 - '@angular/core': 21.2.17 - '@angular/platform-browser': 21.2.17 + '@angular/common': 21.2.19 + '@angular/compiler': 21.2.19 + '@angular/core': 21.2.19 + '@angular/platform-browser': 21.2.19 - '@angular/platform-browser@21.2.17': - resolution: {integrity: sha512-ROdSliejY37g1EphYmweYdm5cHM8HY3X4tbWt4ubxmhTyYgfN3nxrxfGQ/n7Mz5tDY9VXVLIGDgjLOGYOo4uTQ==} + '@angular/platform-browser@21.2.19': + resolution: {integrity: sha512-YMguYVhdkV8tr9MvbN+VpMjbdmsYq6g12M9WPvAYM51BkL2iREbWeoXDGmfCw9G0it6+0pMdgrSPFFUFuOqpAQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/animations': 21.2.17 - '@angular/common': 21.2.17 - '@angular/core': 21.2.17 + '@angular/animations': 21.2.19 + '@angular/common': 21.2.19 + '@angular/core': 21.2.19 peerDependenciesMeta: '@angular/animations': optional: true - '@angular/router@21.2.17': - resolution: {integrity: sha512-RSCtK5ppAV6y6wfRLHSK2a9Wc/vm8j0wsC+/j9PH9yQmppWFVXDWsg5E39MKOIpnoYVx2+hI6eak6+wYtZTe1A==} + '@angular/router@21.2.19': + resolution: {integrity: sha512-cKO/aq1xEMvgS29jFUc/Y3KsgEzHnwOw6sEL+UQZkZTmGD5YrYv8Yvj05GDMEUYbvDxBd5DixVVEbH38lyQKqA==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} peerDependencies: - '@angular/common': 21.2.17 - '@angular/core': 21.2.17 - '@angular/platform-browser': 21.2.17 + '@angular/common': 21.2.19 + '@angular/core': 21.2.19 + '@angular/platform-browser': 21.2.19 rxjs: ^6.5.3 || ^7.4.0 - '@angular/service-worker@21.2.17': - resolution: {integrity: sha512-6/uKwxBA3udngVHuIVqD8kdMV1whfym9ESB1UyjoNINx+2zj7A749X89tiV0TW2CvWpUYUE7VxpoapEiv5lvfw==} + '@angular/service-worker@21.2.19': + resolution: {integrity: sha512-GG9SoZgY5FRi6VlRZYU5lNue1WT+6CoTka7FLpRkdOJs3OG+ivkgAxPExHNXxvuPbHrOyN1cQoRKaTgDBIvIiw==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} hasBin: true peerDependencies: - '@angular/core': 21.2.17 + '@angular/core': 21.2.19 rxjs: ^6.5.3 || ^7.4.0 '@asamuzakjp/css-color@3.2.0': @@ -861,44 +848,32 @@ packages: resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} - '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.3': - resolution: {integrity: sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==} - engines: {node: '>=6.9.0'} - '@babel/compat-data@7.29.7': resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} engines: {node: '>=6.9.0'} - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} - engines: {node: '>=6.9.0'} - '@babel/core@7.29.7': resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.29.7': resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} engines: {node: '>=6.9.0'} + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.27.3': resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + '@babel/helper-annotate-as-pure@7.29.7': + resolution: {integrity: sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.29.7': @@ -922,10 +897,6 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - '@babel/helper-globals@7.29.7': resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} engines: {node: '>=6.9.0'} @@ -934,20 +905,10 @@ packages: resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.29.7': resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} engines: {node: '>=6.9.0'} - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-module-transforms@7.29.7': resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} engines: {node: '>=6.9.0'} @@ -998,10 +959,6 @@ packages: resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.29.7': resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} engines: {node: '>=6.9.0'} @@ -1010,10 +967,6 @@ packages: resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.2': - resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} - engines: {node: '>=6.9.0'} - '@babel/helpers@7.29.7': resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} engines: {node: '>=6.9.0'} @@ -1028,6 +981,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} engines: {node: '>=6.9.0'} @@ -1518,22 +1476,18 @@ packages: resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} - '@babel/traverse@7.29.7': resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + engines: {node: '>=6.9.0'} + '@babel/types@7.29.0': resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} @@ -1542,6 +1496,10 @@ packages: resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} @@ -2830,6 +2788,10 @@ packages: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} + '@istanbuljs/schema@0.1.6': + resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} + engines: {node: '>=8'} + '@jest/console@30.4.1': resolution: {integrity: sha512-v3bhyxUh9Hgmo5p6hAOXe14/R3ZxZDOsvHleh4B07z3m/x4/ngPUXEm9XwK4sF4u+f+P2ORb0Ge+MgpaqRMVDA==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -3280,33 +3242,33 @@ packages: '@module-federation/webpack-bundler-runtime@2.4.0': resolution: {integrity: sha512-Ntx0+QsgcwtXlpGjL/Vf2PMdPjUHl07b3yM4kBc1kbRogW3Ee84QneBRi/X3w4/jlz4JKbHjD+CMXaqi2W6hgw==} - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': - resolution: {integrity: sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==} + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': + resolution: {integrity: sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ==} cpu: [arm64] os: [darwin] - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': - resolution: {integrity: sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==} + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': + resolution: {integrity: sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w==} cpu: [x64] os: [darwin] - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': - resolution: {integrity: sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==} + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': + resolution: {integrity: sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw==} cpu: [arm64] os: [linux] - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': - resolution: {integrity: sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==} + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': + resolution: {integrity: sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw==} cpu: [arm] os: [linux] - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': - resolution: {integrity: sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==} + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': + resolution: {integrity: sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ==} cpu: [x64] os: [linux] - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': - resolution: {integrity: sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==} + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': + resolution: {integrity: sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ==} cpu: [x64] os: [win32] @@ -3435,6 +3397,13 @@ packages: '@napi-rs/wasm-runtime@1.1.1': resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + '@napi-rs/wasm-runtime@1.2.2': + resolution: {integrity: sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.3 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.3 + '@ngrx/effects@21.1.1': resolution: {integrity: sha512-JQUv2tYyjkbdsE40WYtJDsiI+3qtn4V5m0Ybr2CYw9zKpVQshDV5MLLAni+SuijlHAWJkw8x4wwnYmNyG/Rmng==} peerDependencies: @@ -3610,8 +3579,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@npmcli/agent@4.0.0': - resolution: {integrity: sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA==} + '@npmcli/agent@4.0.2': + resolution: {integrity: sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg==} engines: {node: ^20.17.0 || >=22.9.0} '@npmcli/fs@2.1.2': @@ -3622,8 +3591,8 @@ packages: resolution: {integrity: sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og==} engines: {node: ^20.17.0 || >=22.9.0} - '@npmcli/git@7.0.1': - resolution: {integrity: sha512-+XTFxK2jJF/EJJ5SoAzXk3qwIDfvFc5/g+bD274LZ7uY7LE8sTfG6Z8rOanPl2ZEvZWqNvmEdtXC25cE54VcoA==} + '@npmcli/git@7.0.2': + resolution: {integrity: sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg==} engines: {node: ^20.17.0 || >=22.9.0} '@npmcli/installed-package-contents@4.0.0': @@ -3652,8 +3621,8 @@ packages: resolution: {integrity: sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q==} engines: {node: ^20.17.0 || >=22.9.0} - '@npmcli/run-script@10.0.3': - resolution: {integrity: sha512-ER2N6itRkzWbbtVmZ9WKaWxVlKlOeBFF1/7xx+KA5J1xKa4JjUwBdb6tDpk0v1qA+d+VDwHI9qmLcXSWcmi+Rw==} + '@npmcli/run-script@10.0.4': + resolution: {integrity: sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg==} engines: {node: ^20.17.0 || >=22.9.0} '@nx/angular@22.7.2': @@ -3933,92 +3902,86 @@ packages: cpu: [x64] os: [win32] - '@parcel/watcher-android-arm64@2.5.1': - resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + '@parcel/watcher-android-arm64@2.6.0': + resolution: {integrity: sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] - '@parcel/watcher-darwin-arm64@2.5.1': - resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + '@parcel/watcher-darwin-arm64@2.6.0': + resolution: {integrity: sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] - '@parcel/watcher-darwin-x64@2.5.1': - resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + '@parcel/watcher-darwin-x64@2.6.0': + resolution: {integrity: sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] - '@parcel/watcher-freebsd-x64@2.5.1': - resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + '@parcel/watcher-freebsd-x64@2.6.0': + resolution: {integrity: sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] - '@parcel/watcher-linux-arm-glibc@2.5.1': - resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + '@parcel/watcher-linux-arm-glibc@2.6.0': + resolution: {integrity: sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] libc: [glibc] - '@parcel/watcher-linux-arm-musl@2.5.1': - resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + '@parcel/watcher-linux-arm-musl@2.6.0': + resolution: {integrity: sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] libc: [musl] - '@parcel/watcher-linux-arm64-glibc@2.5.1': - resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + '@parcel/watcher-linux-arm64-glibc@2.6.0': + resolution: {integrity: sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - '@parcel/watcher-linux-arm64-musl@2.5.1': - resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + '@parcel/watcher-linux-arm64-musl@2.6.0': + resolution: {integrity: sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] libc: [musl] - '@parcel/watcher-linux-x64-glibc@2.5.1': - resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + '@parcel/watcher-linux-x64-glibc@2.6.0': + resolution: {integrity: sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] libc: [glibc] - '@parcel/watcher-linux-x64-musl@2.5.1': - resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + '@parcel/watcher-linux-x64-musl@2.6.0': + resolution: {integrity: sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] libc: [musl] - '@parcel/watcher-win32-arm64@2.5.1': - resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + '@parcel/watcher-win32-arm64@2.6.0': + resolution: {integrity: sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] - '@parcel/watcher-win32-ia32@2.5.1': - resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} - engines: {node: '>= 10.0.0'} - cpu: [ia32] - os: [win32] - - '@parcel/watcher-win32-x64@2.5.1': - resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + '@parcel/watcher-win32-x64@2.6.0': + resolution: {integrity: sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] - '@parcel/watcher@2.5.1': - resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + '@parcel/watcher@2.6.0': + resolution: {integrity: sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==} engines: {node: '>= 10.0.0'} '@phenomnomnominal/tsquery@6.2.0': @@ -4356,12 +4319,8 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@schematics/angular@21.2.17': - resolution: {integrity: sha512-rKHz2//1S3j4MKfsRDtJjnNoCfqSj2dNJDN27pLT9h4oLfBs2wJinfRTQywo2fVGdUcDd+mXBnltqdLJlcoFNw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - - '@schematics/angular@21.2.9': - resolution: {integrity: sha512-1renEbBZz9Yw3A0GUOJ6x6E1jd2Vu/fX5tEGiFNbIoWaNwa71SlFTvKKqaYxiYQkrpc7oexVJ2ymuvOfgTbI1w==} + '@schematics/angular@21.2.19': + resolution: {integrity: sha512-eL+UU9eizoadhDB4YEctRmmo0A5iwrSmGzeuEa6akrq8nLGVWM8zO91HTJutkPqGQjelF+UOiOShsQSZAU9SIQ==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} '@shikijs/core@3.22.0': @@ -4389,24 +4348,24 @@ packages: resolution: {integrity: sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==} engines: {node: ^20.17.0 || >=22.9.0} - '@sigstore/core@3.1.0': - resolution: {integrity: sha512-o5cw1QYhNQ9IroioJxpzexmPjfCe7gzafd2RY3qnMpxr4ZEja+Jad/U8sgFpaue6bOaF+z7RVkyKVV44FN+N8A==} + '@sigstore/core@3.2.1': + resolution: {integrity: sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g==} engines: {node: ^20.17.0 || >=22.9.0} - '@sigstore/protobuf-specs@0.5.0': - resolution: {integrity: sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA==} + '@sigstore/protobuf-specs@0.5.1': + resolution: {integrity: sha512-/ScWUhhoFasJsSRGTVBwId1loQjjnjAfE4djL6ZhrXRpNCmPTnUKF5Jokd58ILseOMjzET3UrMOtJPS9sYeI0g==} engines: {node: ^18.17.0 || >=20.5.0} - '@sigstore/sign@4.1.0': - resolution: {integrity: sha512-Vx1RmLxLGnSUqx/o5/VsCjkuN5L7y+vxEEwawvc7u+6WtX2W4GNa7b9HEjmcRWohw/d6BpATXmvOwc78m+Swdg==} + '@sigstore/sign@4.1.1': + resolution: {integrity: sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ==} engines: {node: ^20.17.0 || >=22.9.0} - '@sigstore/tuf@4.0.1': - resolution: {integrity: sha512-OPZBg8y5Vc9yZjmWCHrlWPMBqW5yd8+wFNl+thMdtcWz3vjVSoJQutF8YkrzI0SLGnkuFof4HSsWUhXrf219Lw==} + '@sigstore/tuf@4.0.2': + resolution: {integrity: sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ==} engines: {node: ^20.17.0 || >=22.9.0} - '@sigstore/verify@3.1.0': - resolution: {integrity: sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag==} + '@sigstore/verify@3.1.1': + resolution: {integrity: sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA==} engines: {node: ^20.17.0 || >=22.9.0} '@sinclair/typebox@0.34.46': @@ -4580,6 +4539,9 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -5182,8 +5144,8 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@7.2.0: - resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==} + ansi-escapes@7.3.0: + resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==} engines: {node: '>=18'} ansi-html-community@0.0.8: @@ -5423,6 +5385,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + baseline-browser-mapping@2.11.12: + resolution: {integrity: sha512-r7WnVImvVCeFpf2DOXfy41aPWzeNg3H/A2X4dKmy1QL0MSyyk/e7z8ihJ3N6Nn2PsdhkVlqnEfnUE4a05P2aTA==} + engines: {node: '>=6.0.0'} + hasBin: true + baseline-browser-mapping@2.9.11: resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} hasBin: true @@ -5508,6 +5475,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + bs-logger@0.2.6: resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} engines: {node: '>= 6'} @@ -5552,8 +5524,8 @@ packages: resolution: {integrity: sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - cacache@20.0.3: - resolution: {integrity: sha512-3pUp4e8hv07k1QlijZu6Kn7c9+ZpWWk4j3F8N3xPuCExULobqJydKYOTj1FTq58srkJsXvO7LbGAH4C0ZU3WGw==} + cacache@20.0.4: + resolution: {integrity: sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA==} engines: {node: ^20.17.0 || >=22.9.0} cacheable-lookup@5.0.4: @@ -5605,6 +5577,9 @@ packages: caniuse-lite@1.0.30001792: resolution: {integrity: sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==} + caniuse-lite@1.0.30001809: + resolution: {integrity: sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==} + ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -5636,8 +5611,8 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - chardet@2.1.1: - resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + chardet@2.2.0: + resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==} chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} @@ -5712,8 +5687,8 @@ packages: resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} engines: {node: '>=8'} - cli-truncate@5.1.1: - resolution: {integrity: sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A==} + cli-truncate@5.2.0: + resolution: {integrity: sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==} engines: {node: '>=20'} cli-width@4.1.0: @@ -6189,11 +6164,6 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - detect-libc@1.0.3: - resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} - engines: {node: '>=0.10'} - hasBin: true - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -6434,6 +6404,9 @@ packages: electron-to-chromium@1.5.353: resolution: {integrity: sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==} + electron-to-chromium@1.5.402: + resolution: {integrity: sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA==} + electron-updater@6.8.9: resolution: {integrity: sha512-ZhVxM9iGONUpZGI1FxdMRgJjUFXi7AYGVa5PwKlO1tV1/4zDxQmfKpXOHVztKrd6L9rLcFjERvi1Mf2vxyTkig==} @@ -6489,6 +6462,14 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + entities@7.0.1: + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} + + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -6764,12 +6745,15 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - eventsource-parser@3.0.6: - resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} + eventsource-parser@3.1.0: + resolution: {integrity: sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg==} engines: {node: '>=18.0.0'} eventsource@3.0.7: @@ -7055,8 +7039,8 @@ packages: resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} engines: {node: '>=18'} - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} get-intrinsic@1.3.0: @@ -7273,8 +7257,8 @@ packages: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} - hosted-git-info@9.0.2: - resolution: {integrity: sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg==} + hosted-git-info@9.0.3: + resolution: {integrity: sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg==} engines: {node: ^20.17.0 || >=22.9.0} hpack.js@2.1.6: @@ -7300,8 +7284,8 @@ packages: html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - htmlparser2@10.0.0: - resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==} + htmlparser2@10.1.0: + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} http-assert@1.5.0: resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} @@ -7977,8 +7961,8 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true - jose@6.1.3: - resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} + jose@6.2.8: + resolution: {integrity: sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -8221,6 +8205,10 @@ packages: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -8263,10 +8251,6 @@ packages: resolution: {integrity: sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - make-fetch-happen@15.0.3: - resolution: {integrity: sha512-iyyEpDty1mwW3dGlYXAJqC/azFn5PPvgKVwXayOGBSmKLxhKZ9fg4qIan2ePpp1vJIwfFiO34LAPZgq9SZW9Aw==} - engines: {node: ^20.17.0 || >=22.9.0} - make-fetch-happen@15.0.6: resolution: {integrity: sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -8591,10 +8575,6 @@ packages: resolution: {integrity: sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - minipass-fetch@5.0.1: - resolution: {integrity: sha512-yHK8pb0iCGat0lDrs/D6RZmCdaBT64tULXjdxjSMAqoDi18Q3qKEUTHypHQZQd9+FYpIS+lkvpq6C/R6SbUeRw==} - engines: {node: ^20.17.0 || >=22.9.0} - minipass-fetch@5.0.2: resolution: {integrity: sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ==} engines: {node: ^20.17.0 || >=22.9.0} @@ -8668,12 +8648,12 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - msgpackr-extract@3.0.3: - resolution: {integrity: sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==} + msgpackr-extract@3.0.4: + resolution: {integrity: sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw==} hasBin: true - msgpackr@1.11.8: - resolution: {integrity: sha512-bC4UGzHhVvgDNS7kn9tV8fAucIYUBuGojcaLiz7v+P63Lmtm0Xeji8B/8tYKddALXxJLpwIeBmUN3u64C4YkRA==} + msgpackr@1.12.1: + resolution: {integrity: sha512-4EUH9tQHnMmEgzW/MdAP0KIfa1T9AF+htl0ffe2n5vb2EKn9y2co8ccpgWko6S52Jy1PQZKwRnx5/KkYjtd9MQ==} multicast-dns@7.2.5: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} @@ -8701,6 +8681,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + napi-build-utils@2.0.0: resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} @@ -8798,8 +8783,8 @@ packages: resolution: {integrity: sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==} hasBin: true - node-gyp@12.2.0: - resolution: {integrity: sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ==} + node-gyp@12.4.0: + resolution: {integrity: sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==} engines: {node: ^20.17.0 || >=22.9.0} hasBin: true @@ -8815,6 +8800,10 @@ packages: node-releases@2.0.38: resolution: {integrity: sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==} + node-releases@2.0.53: + resolution: {integrity: sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==} + engines: {node: '>=18'} + node-schedule@2.1.1: resolution: {integrity: sha512-OXdegQq03OmXEjt2hZP33W2YPs/E5BcFQks46+G2gAxs4gHOIVD1u7EqlYLYSKsaIpyKCK9Gbk0ta1/gjRSMRQ==} engines: {node: '>=6'} @@ -8853,8 +8842,8 @@ packages: resolution: {integrity: sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA==} engines: {node: ^20.17.0 || >=22.9.0} - npm-packlist@10.0.3: - resolution: {integrity: sha512-zPukTwJMOu5X5uvm0fztwS5Zxyvmk38H/LfidkOMt3gbZVCyro2cD/ETzwzVPcWZA3JOyPznfUN/nkyFiyUbxg==} + npm-packlist@10.0.4: + resolution: {integrity: sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng==} engines: {node: ^20.17.0 || >=22.9.0} npm-pick-manifest@11.0.3: @@ -9037,8 +9026,8 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} - p-map@7.0.4: - resolution: {integrity: sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ==} + p-map@7.0.6: + resolution: {integrity: sha512-I4Prw6ivkd6p8PiYR1tXASOAOBzIJwu0TB7fqaX0c/8c3QAehNYmX57EijyGGGBt3c/BIowGwV03RVBtXvHEVg==} engines: {node: '>=18'} p-queue@8.1.1: @@ -9105,6 +9094,9 @@ packages: parse5@8.0.0: resolution: {integrity: sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -9172,6 +9164,10 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} + picomatch@4.0.5: + resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -9507,6 +9503,10 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + postcss@8.5.26: + resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==} + engines: {node: ^10 || ^12 || >=14} + postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -9684,8 +9684,8 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} - readdirp@5.0.0: - resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} + readdirp@5.1.1: + resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==} engines: {node: '>= 20.19.0'} recma-build-jsx@1.0.0: @@ -10199,7 +10199,6 @@ packages: shaka-player@5.2.2: resolution: {integrity: sha512-1Z5Sxqz7nEAtvp4zlZKAHQSEq6cUlw5CKAdUxqmuMNeZgu23090VXMcEDdiSLU5qtMn1skFOzq+KKCVX71bHqw==} - engines: {node: '>=18'} shallow-clone@3.0.1: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} @@ -10264,8 +10263,8 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - sigstore@4.1.0: - resolution: {integrity: sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==} + sigstore@4.1.1: + resolution: {integrity: sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w==} engines: {node: ^20.17.0 || >=22.9.0} simple-concat@1.0.1: @@ -10302,6 +10301,10 @@ packages: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} + slice-ansi@8.0.0: + resolution: {integrity: sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==} + engines: {node: '>=20'} + smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} @@ -10364,8 +10367,8 @@ packages: spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} - spdx-license-ids@3.0.22: - resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + spdx-license-ids@3.0.23: + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} spdy-transport@3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} @@ -10435,8 +10438,8 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} - string-width@8.2.0: - resolution: {integrity: sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==} + string-width@8.2.2: + resolution: {integrity: sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg==} engines: {node: '>=20'} string.prototype.trim@1.2.10: @@ -10577,8 +10580,8 @@ packages: engines: {node: '>=10'} deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - tar@7.5.9: - resolution: {integrity: sha512-BTLcK0xsDh2+PUe9F6c2TlRp4zOOBMTkoQHQIWSIzI0R7KG46uEwq4OPk2W7bZcprBMsuaeFsqwYr7pjh6CuHg==} + tar@7.5.22: + resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==} engines: {node: '>=18'} temp-file@3.4.0: @@ -10646,6 +10649,10 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} @@ -10901,14 +10908,18 @@ packages: undici-types@7.18.2: resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici@7.24.4: - resolution: {integrity: sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==} - engines: {node: '>=20.18.1'} + undici@6.28.0: + resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} + engines: {node: '>=18.17'} undici@7.24.7: resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==} engines: {node: '>=20.18.1'} + undici@7.28.0: + resolution: {integrity: sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==} + engines: {node: '>=20.18.1'} + undici@7.29.0: resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} engines: {node: '>=20.18.1'} @@ -10947,18 +10958,10 @@ packages: resolution: {integrity: sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - unique-filename@5.0.0: - resolution: {integrity: sha512-2RaJTAvAb4owyjllTfXzFClJ7WsGxlykkPvCr9pA//LD9goVq+m4PPAeBgNodGZ7nSrntT/auWpJ6Y5IFXcfjg==} - engines: {node: ^20.17.0 || >=22.9.0} - unique-slug@3.0.0: resolution: {integrity: sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - unique-slug@6.0.0: - resolution: {integrity: sha512-4Lup7Ezn8W3d52/xBhZBVdx323ckxa7DEvd9kPQHppTkLoJXw6ltrBCyj5pnrxj0qKDxYMJ56CoxNuFCscdTiw==} - engines: {node: ^20.17.0 || >=22.9.0} - unist-util-find-after@5.0.0: resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} @@ -11076,6 +11079,12 @@ packages: peerDependencies: browserslist: '>= 4.21.0' + update-browserslist-db@1.3.0: + resolution: {integrity: sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -11196,8 +11205,8 @@ packages: yaml: optional: true - vite@7.3.5: - resolution: {integrity: sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==} + vite@7.3.6: + resolution: {integrity: sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -11536,10 +11545,18 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} + engines: {node: '>=12'} + yargs@18.0.0: resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yargs@18.1.0: + resolution: {integrity: sha512-2rAgRKu54VsHkqI0/tYkmluGXHD4KW7yZoycuqDQ15QOTnc2VVfy0nN/1eMhnQLO00A+dwtK20xuCnc1YGeUyg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -11564,11 +11581,20 @@ packages: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} + yoctocolors@2.2.0: + resolution: {integrity: sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg==} + engines: {node: '>=18'} + zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: zod: ^3.25 || ^4 + zod-to-json-schema@3.25.2: + resolution: {integrity: sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==} + peerDependencies: + zod: ^3.25.28 || ^4 + zod-to-ts@1.2.0: resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} peerDependencies: @@ -11689,16 +11715,16 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular-devkit/architect@0.2102.17(chokidar@5.0.0)': + '@angular-devkit/architect@0.2102.19(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar - '@angular-devkit/architect@0.2102.19(chokidar@5.0.0)': + '@angular-devkit/architect@0.2102.20(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/core': 21.2.20(chokidar@5.0.0) rxjs: 7.8.2 transitivePeerDependencies: - chokidar @@ -11714,17 +11740,6 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/core@21.2.17(chokidar@5.0.0)': - dependencies: - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) - jsonc-parser: 3.3.1 - picomatch: 4.0.4 - rxjs: 7.8.2 - source-map: 0.7.6 - optionalDependencies: - chokidar: 5.0.0 - '@angular-devkit/core@21.2.19(chokidar@5.0.0)': dependencies: ajv: 8.18.0 @@ -11736,7 +11751,7 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/core@21.2.9(chokidar@5.0.0)': + '@angular-devkit/core@21.2.20(chokidar@5.0.0)': dependencies: ajv: 8.18.0 ajv-formats: 3.0.1(ajv@8.18.0) @@ -11747,9 +11762,9 @@ snapshots: optionalDependencies: chokidar: 5.0.0 - '@angular-devkit/schematics@21.2.17(chokidar@5.0.0)': + '@angular-devkit/schematics@21.2.19(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) jsonc-parser: 3.3.1 magic-string: 0.30.21 ora: 9.3.0 @@ -11757,31 +11772,21 @@ snapshots: transitivePeerDependencies: - chokidar - '@angular-devkit/schematics@21.2.9(chokidar@5.0.0)': - dependencies: - '@angular-devkit/core': 21.2.9(chokidar@5.0.0) - jsonc-parser: 3.3.1 - magic-string: 0.30.21 - ora: 9.3.0 - rxjs: 7.8.2 - transitivePeerDependencies: - - chokidar - - '@angular-eslint/builder@21.3.1(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@angular-eslint/builder@21.3.1(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@angular-devkit/architect': 0.2101.4(chokidar@5.0.0) - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular/cli': 21.2.17(@types/node@20.19.9)(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular/cli': 21.2.19(@types/node@20.19.9)(chokidar@5.0.0) eslint: 9.39.2(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: - chokidar - '@angular-eslint/builder@21.4.0(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@angular-eslint/builder@21.4.0(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@angular-devkit/architect': 0.2102.19(chokidar@5.0.0) - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular/cli': 21.2.17(@types/node@20.19.9)(chokidar@5.0.0) + '@angular-devkit/architect': 0.2102.20(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular/cli': 21.2.19(@types/node@20.19.9)(chokidar@5.0.0) eslint: 9.39.2(jiti@1.21.7) typescript: 5.9.3 transitivePeerDependencies: @@ -11833,13 +11838,13 @@ snapshots: ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 - '@angular-eslint/schematics@21.3.1(@angular-eslint/template-parser@21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@angular-eslint/schematics@21.3.1(@angular-eslint/template-parser@21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.19(chokidar@5.0.0) '@angular-eslint/eslint-plugin': 21.3.1(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/eslint-plugin-template': 21.3.1(@angular-eslint/template-parser@21.3.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@angular/cli': 21.2.17(@types/node@20.19.9)(chokidar@5.0.0) + '@angular/cli': 21.2.19(@types/node@20.19.9)(chokidar@5.0.0) ignore: 7.0.5 semver: 7.7.4 strip-json-comments: 3.1.1 @@ -11851,13 +11856,13 @@ snapshots: - eslint - typescript - '@angular-eslint/schematics@21.4.0(@angular-eslint/template-parser@21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + '@angular-eslint/schematics@21.4.0(@angular-eslint/template-parser@21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.19(chokidar@5.0.0) '@angular-eslint/eslint-plugin': 21.4.0(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/eslint-plugin-template': 21.4.0(@angular-eslint/template-parser@21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@angular/cli': 21.2.17(@types/node@20.19.9)(chokidar@5.0.0) + '@angular/cli': 21.2.19(@types/node@20.19.9)(chokidar@5.0.0) ignore: 7.0.5 semver: 7.7.4 strip-json-comments: 3.1.1 @@ -11897,24 +11902,24 @@ snapshots: eslint: 9.39.2(jiti@1.21.7) typescript: 5.9.3 - '@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))': + '@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 - '@angular/build@21.2.17(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3))(@angular/compiler@21.2.17)(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/service-worker@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@types/node@20.19.9)(chokidar@5.0.0)(jiti@1.21.7)(less@4.5.1)(postcss@8.5.6)(sass-embedded@1.97.1)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0)': + '@angular/build@21.2.19(@angular/compiler-cli@21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/service-worker@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3)(@types/node@20.19.9)(chokidar@5.0.0)(jiti@1.21.7)(less@4.5.1)(postcss@8.5.6)(sass-embedded@1.97.1)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0)': dependencies: '@ampproject/remapping': 2.3.0 - '@angular-devkit/architect': 0.2102.17(chokidar@5.0.0) - '@angular/compiler': 21.2.17 - '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3) + '@angular-devkit/architect': 0.2102.19(chokidar@5.0.0) + '@angular/compiler': 21.2.19 + '@angular/compiler-cli': 21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3) '@babel/core': 7.29.7 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-split-export-declaration': 7.24.7 '@inquirer/confirm': 5.1.21(@types/node@20.19.9) - '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.5(patch_hash=b3a8f88ab420b6504a61ffb0f8e402f112c7fda7f3f3e802d21272da7969882d)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0)) + '@vitejs/plugin-basic-ssl': 2.1.4(vite@7.3.6(patch_hash=215b6585a9c92fa68c096d500f4676983200307b1e64c1321e20ccbd50bbc8f3)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0)) beasties: 0.4.1 - browserslist: 4.28.2 + browserslist: 4.28.7 esbuild: 0.28.1 https-proxy-agent: 7.0.6 istanbul-lib-instrument: 6.0.3 @@ -11925,25 +11930,27 @@ snapshots: parse5-html-rewriting-stream: 8.0.0 picomatch: 4.0.4 piscina: 5.2.0 - rolldown: 1.0.0-rc.4 + rolldown: 1.0.0-rc.4(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3) sass: 1.97.3 semver: 7.7.4 source-map-support: 0.5.21 tinyglobby: 0.2.15 tslib: 2.8.1 typescript: 5.9.3 - undici: 7.24.4 - vite: 7.3.5(patch_hash=b3a8f88ab420b6504a61ffb0f8e402f112c7fda7f3f3e802d21272da7969882d)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0) + undici: 7.28.0 + vite: 7.3.6(patch_hash=215b6585a9c92fa68c096d500f4676983200307b1e64c1321e20ccbd50bbc8f3)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0) watchpack: 2.5.1 optionalDependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) - '@angular/service-worker': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/service-worker': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) less: 4.5.1 lmdb: 3.5.1 postcss: 8.5.6 tailwindcss: 3.4.19(tsx@4.23.1)(yaml@2.9.0) transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' - '@types/node' - chokidar - jiti @@ -11956,24 +11963,24 @@ snapshots: - tsx - yaml - '@angular/cdk@21.2.14(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/cdk@21.2.14(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) parse5: 8.0.0 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0)': + '@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0)': dependencies: - '@angular-devkit/architect': 0.2102.17(chokidar@5.0.0) - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) + '@angular-devkit/architect': 0.2102.19(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.19(chokidar@5.0.0) '@inquirer/prompts': 7.10.1(@types/node@20.19.9) '@listr2/prompt-adapter-inquirer': 3.0.5(@inquirer/prompts@7.10.1(@types/node@20.19.9))(@types/node@20.19.9)(listr2@9.0.5) '@modelcontextprotocol/sdk': 1.26.0(zod@4.3.6) - '@schematics/angular': 21.2.17(chokidar@5.0.0) + '@schematics/angular': 21.2.19(chokidar@5.0.0) '@yarnpkg/lockfile': 1.1.0 algoliasearch: 5.48.1 ini: 6.0.0 @@ -11991,88 +11998,88 @@ snapshots: - chokidar - supports-color - '@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3)': + '@angular/compiler-cli@21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3)': dependencies: - '@angular/compiler': 21.2.17 - '@babel/core': 7.29.0 + '@angular/compiler': 21.2.19 + '@babel/core': 7.29.7 '@jridgewell/sourcemap-codec': 1.5.5 chokidar: 5.0.0 convert-source-map: 1.9.0 reflect-metadata: 0.2.2 - semver: 7.7.4 + semver: 7.8.5 tslib: 2.8.1 - yargs: 18.0.0 + yargs: 18.1.0 optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@angular/compiler@21.2.17': + '@angular/compiler@21.2.19': dependencies: tslib: 2.8.1 - '@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)': + '@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)': dependencies: rxjs: 7.8.2 tslib: 2.8.1 optionalDependencies: - '@angular/compiler': 21.2.17 + '@angular/compiler': 21.2.19 zone.js: 0.16.2 - '@angular/forms@21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/forms@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) '@standard-schema/spec': 1.1.0 rxjs: 7.8.2 tslib: 2.8.1 - '@angular/language-service@21.2.17': {} + '@angular/language-service@21.2.19': {} - '@angular/material@21.2.14(43172ba04e47f305707a39eaf8cab87a)': + '@angular/material@21.2.14(e62c7210bef08c270f76f8032e5d0530)': dependencies: - '@angular/cdk': 21.2.14(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/forms': 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/cdk': 21.2.14(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/forms': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/platform-browser-dynamic@21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@21.2.17)(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))': + '@angular/platform-browser-dynamic@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/compiler': 21.2.17 - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/compiler': 21.2.19 + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) tslib: 2.8.1 - '@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))': + '@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 optionalDependencies: - '@angular/animations': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/animations': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) - '@angular/router@21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': + '@angular/router@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) rxjs: 7.8.2 tslib: 2.8.1 - '@angular/service-worker@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@angular/service-worker@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) rxjs: 7.8.2 tslib: 2.8.1 @@ -12199,53 +12206,25 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 - '@babel/compat-data@7.29.3': {} - '@babel/compat-data@7.29.7': {} - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/core@7.29.7': dependencies: '@babel/code-frame': 7.29.7 - '@babel/generator': 7.29.7 + '@babel/generator': 7.29.8 '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) '@babel/helpers': 7.29.7 - '@babel/parser': 7.29.7 + '@babel/parser': 7.29.8 '@babel/template': 7.29.7 - '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -12255,14 +12234,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - '@babel/generator@7.29.7': dependencies: '@babel/parser': 7.29.7 @@ -12271,23 +12242,27 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.8 - '@babel/helper-compilation-targets@7.28.6': + '@babel/helper-annotate-as-pure@7.29.7': dependencies: - '@babel/compat-data': 7.29.3 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.2 - lru-cache: 5.1.1 - semver: 6.3.1 + '@babel/types': 7.29.8 '@babel/helper-compilation-targets@7.29.7': dependencies: '@babel/compat-data': 7.29.7 '@babel/helper-validator-option': 7.29.7 - browserslist: 4.28.2 + browserslist: 4.28.7 lru-cache: 5.1.1 semver: 6.3.1 @@ -12307,7 +12282,7 @@ snapshots: '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-annotate-as-pure': 7.29.7 regexpu-core: 6.4.0 semver: 6.3.1 @@ -12322,21 +12297,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-globals@7.28.0': {} - '@babel/helper-globals@7.29.7': {} '@babel/helper-member-expression-to-functions@7.28.5': dependencies: '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-imports@7.28.6': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color @@ -12347,15 +12313,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -12367,14 +12324,14 @@ snapshots: '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/helper-plugin-utils@7.27.1': {} '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-wrap-function': 7.28.3 '@babel/traverse': 7.29.7 transitivePeerDependencies: @@ -12392,13 +12349,13 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color '@babel/helper-split-export-declaration@7.24.7': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.8 '@babel/helper-string-parser@7.27.1': {} @@ -12408,27 +12365,20 @@ snapshots: '@babel/helper-validator-identifier@7.29.7': {} - '@babel/helper-validator-option@7.27.1': {} - '@babel/helper-validator-option@7.29.7': {} '@babel/helper-wrap-function@7.28.3': dependencies: '@babel/template': 7.29.7 '@babel/traverse': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 transitivePeerDependencies: - supports-color - '@babel/helpers@7.29.2': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - '@babel/helpers@7.29.7': dependencies: '@babel/template': 7.29.7 - '@babel/types': 7.29.7 + '@babel/types': 7.29.8 '@babel/parser@7.29.0': dependencies: @@ -12438,6 +12388,10 @@ snapshots: dependencies: '@babel/types': 7.29.7 + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 @@ -12639,7 +12593,7 @@ snapshots: '@babel/plugin-transform-classes@7.28.4(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-compilation-targets': 7.29.7 '@babel/helper-globals': 7.29.7 '@babel/helper-plugin-utils': 7.27.1 @@ -12842,7 +12796,7 @@ snapshots: '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: @@ -12912,7 +12866,7 @@ snapshots: '@babel/plugin-transform-typescript@7.28.5(@babel/core@7.29.7)': dependencies: '@babel/core': 7.29.7 - '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-annotate-as-pure': 7.29.7 '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.29.7) '@babel/helper-plugin-utils': 7.27.1 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 @@ -13039,30 +12993,12 @@ snapshots: '@babel/runtime@7.28.4': {} - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 '@babel/parser': 7.29.7 '@babel/types': 7.29.7 - '@babel/traverse@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.0 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - '@babel/traverse@7.29.7': dependencies: '@babel/code-frame': 7.29.7 @@ -13075,6 +13011,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -13085,6 +13033,11 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@bcoe/v8-coverage@0.2.3': {} '@bufbuild/protobuf@2.10.2': {} @@ -13904,8 +13857,8 @@ snapshots: '@inquirer/external-editor@1.0.3(@types/node@20.19.9)': dependencies: - chardet: 2.1.1 - iconv-lite: 0.7.1 + chardet: 2.2.0 + iconv-lite: 0.7.3 optionalDependencies: '@types/node': 20.19.9 @@ -14008,6 +13961,8 @@ snapshots: '@istanbuljs/schema@0.1.3': {} + '@istanbuljs/schema@0.1.6': {} + '@jest/console@30.4.1': dependencies: '@jest/types': 30.4.1 @@ -14397,16 +14352,16 @@ snapshots: cors: 2.8.6 cross-spawn: 7.0.6 eventsource: 3.0.7 - eventsource-parser: 3.0.6 + eventsource-parser: 3.1.0 express: 5.2.1 express-rate-limit: 8.3.0(express@5.2.1) hono: 4.12.14 - jose: 6.1.3 + jose: 6.2.8 json-schema-typed: 8.0.2 pkce-challenge: 5.0.1 raw-body: 3.0.2 zod: 4.3.6 - zod-to-json-schema: 3.25.1(zod@4.3.6) + zod-to-json-schema: 3.25.2(zod@4.3.6) transitivePeerDependencies: - supports-color @@ -14759,22 +14714,22 @@ snapshots: transitivePeerDependencies: - node-fetch - '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.3': + '@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4': optional: true - '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': + '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4': optional: true '@napi-rs/nice-android-arm-eabi@1.1.1': @@ -14876,17 +14831,24 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true - '@ngrx/effects@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': + '@napi-rs/wasm-runtime@1.2.2(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@ngrx/store': 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@emnapi/core': 1.8.1 + '@emnapi/runtime': 1.11.3 + '@tybys/wasm-util': 0.10.3 + optional: true + + '@ngrx/effects@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': + dependencies: + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@ngrx/store': 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 - '@ngrx/entity@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': + '@ngrx/entity@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@ngrx/store': 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@ngrx/store': 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 @@ -14898,52 +14860,52 @@ snapshots: typescript: 5.9.3 typescript-eslint: 8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@ngrx/router-store@21.1.1(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/router@21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': + '@ngrx/router-store@21.1.1(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/router@21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/router': 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) - '@ngrx/store': 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/router': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@ngrx/store': 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 - '@ngrx/signals@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@ngrx/signals@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 optionalDependencies: rxjs: 7.8.2 - '@ngrx/store-devtools@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': + '@ngrx/store-devtools@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@ngrx/store': 21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@ngrx/store': 21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) rxjs: 7.8.2 tslib: 2.8.1 - '@ngrx/store@21.1.1(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@ngrx/store@21.1.1(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) rxjs: 7.8.2 tslib: 2.8.1 - '@ngx-pwa/local-storage@21.0.0(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': + '@ngx-pwa/local-storage@21.0.0(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2)': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) rxjs: 7.8.2 tslib: 2.8.1 - '@ngx-translate/core@16.0.4(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))': + '@ngx-translate/core@16.0.4(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 - '@ngx-translate/http-loader@16.0.1(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))': + '@ngx-translate/http-loader@16.0.1(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))': dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 '@node-rs/xxhash-android-arm-eabi@1.7.6': @@ -15019,12 +14981,12 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@npmcli/agent@4.0.0': + '@npmcli/agent@4.0.2': dependencies: agent-base: 7.1.4 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 - lru-cache: 11.2.4 + lru-cache: 11.5.2 socks-proxy-agent: 8.0.5 transitivePeerDependencies: - supports-color @@ -15036,17 +14998,17 @@ snapshots: '@npmcli/fs@5.0.0': dependencies: - semver: 7.8.5 + semver: 7.7.4 - '@npmcli/git@7.0.1': + '@npmcli/git@7.0.2': dependencies: + '@gar/promise-retry': 1.0.3 '@npmcli/promise-spawn': 9.0.1 ini: 6.0.0 - lru-cache: 11.2.4 + lru-cache: 11.5.2 npm-pick-manifest: 11.0.3 proc-log: 6.1.0 - promise-retry: 2.0.1 - semver: 7.8.5 + semver: 7.7.4 which: 6.0.1 '@npmcli/installed-package-contents@4.0.0': @@ -15063,12 +15025,12 @@ snapshots: '@npmcli/package-json@7.0.5': dependencies: - '@npmcli/git': 7.0.1 + '@npmcli/git': 7.0.2 glob: 13.0.6 - hosted-git-info: 9.0.2 + hosted-git-info: 9.0.3 json-parse-even-better-errors: 5.0.0 proc-log: 6.1.0 - semver: 7.8.5 + semver: 7.7.4 spdx-expression-parse: 4.0.0 '@npmcli/promise-spawn@9.0.1': @@ -15077,31 +15039,28 @@ snapshots: '@npmcli/redact@4.0.0': {} - '@npmcli/run-script@10.0.3': + '@npmcli/run-script@10.0.4': dependencies: '@npmcli/node-gyp': 5.0.0 '@npmcli/package-json': 7.0.5 '@npmcli/promise-spawn': 9.0.1 - node-gyp: 12.2.0 + node-gyp: 12.4.0 proc-log: 6.1.0 - which: 6.0.1 - transitivePeerDependencies: - - supports-color - '@nx/angular@22.7.2(5435397b23ab524463bbc1574adf9264)': + '@nx/angular@22.7.2(e218af65d764a685aba0bafd0ced9f6d)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.19(chokidar@5.0.0) '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/eslint': 22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/module-federation': 22.7.2(71acb53b38112c0893e6c056e8943136) - '@nx/rspack': 22.7.2(2f8e7c6b2dfd976b2f08f03cf47b966f) - '@nx/web': 22.7.2(888f284af7850e1ced4d654d87699281) - '@nx/webpack': 22.7.2(@babel/traverse@7.29.7)(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3) + '@nx/eslint': 22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/module-federation': 22.7.2(b0dcdc95bb0ed63b676cadeba88952fd) + '@nx/rspack': 22.7.2(745e8cc09db8b72c25a2adfc8e9f3271) + '@nx/web': 22.7.2(0222b886c58439e845e61058a381daaa) + '@nx/webpack': 22.7.2(@babel/traverse@7.29.8)(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3) '@nx/workspace': 22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)) '@phenomnomnominal/tsquery': 6.2.0(typescript@5.9.3) - '@schematics/angular': 21.2.9(chokidar@5.0.0) + '@schematics/angular': 21.2.19(chokidar@5.0.0) '@typescript-eslint/type-utils': 8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) enquirer: 2.3.6 magic-string: 0.30.21 @@ -15112,7 +15071,7 @@ snapshots: tslib: 2.8.1 webpack-merge: 5.10.0 optionalDependencies: - '@angular/build': 21.2.17(@angular/compiler-cli@21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3))(@angular/compiler@21.2.17)(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/service-worker@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@types/node@20.19.9)(chokidar@5.0.0)(jiti@1.21.7)(less@4.5.1)(postcss@8.5.6)(sass-embedded@1.97.1)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0) + '@angular/build': 21.2.19(@angular/compiler-cli@21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/service-worker@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3)(@types/node@20.19.9)(chokidar@5.0.0)(jiti@1.21.7)(less@4.5.1)(postcss@8.5.6)(sass-embedded@1.97.1)(tailwindcss@3.4.19(tsx@4.23.1)(yaml@2.9.0))(terser@5.44.1)(tslib@2.8.1)(tsx@4.23.1)(typescript@5.9.3)(yaml@2.9.0) transitivePeerDependencies: - '@babel/traverse' - '@module-federation/enhanced' @@ -15165,10 +15124,10 @@ snapshots: tslib: 2.8.1 yargs-parser: 21.1.1 - '@nx/esbuild@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': + '@nx/esbuild@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': dependencies: '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) picocolors: 1.1.1 tinyglobby: 0.2.15 tsconfig-paths: 4.2.0 @@ -15184,10 +15143,10 @@ snapshots: - supports-color - verdaccio - '@nx/eslint-plugin@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@typescript-eslint/parser@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3)': + '@nx/eslint-plugin@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@typescript-eslint/parser@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@1.21.7)))(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3)': dependencies: '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@phenomnomnominal/tsquery': 6.2.0(typescript@5.9.3) '@typescript-eslint/parser': 8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/type-utils': 8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) @@ -15211,16 +15170,16 @@ snapshots: - typescript - verdaccio - '@nx/eslint@22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': + '@nx/eslint@22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': dependencies: '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) eslint: 9.39.2(jiti@1.21.7) semver: 7.8.5 tslib: 2.8.1 typescript: 5.9.3 optionalDependencies: - '@nx/jest': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3) + '@nx/jest': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3) '@zkochan/js-yaml': 0.0.7 transitivePeerDependencies: - '@babel/traverse' @@ -15231,12 +15190,12 @@ snapshots: - supports-color - verdaccio - '@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3)': + '@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3)': dependencies: '@jest/reporters': 30.4.1 '@jest/test-result': 30.4.1 '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@phenomnomnominal/tsquery': 6.2.0(typescript@5.9.3) identity-obj-proxy: 3.0.0 jest-config: 30.4.2(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3)) @@ -15263,7 +15222,7 @@ snapshots: - typescript - verdaccio - '@nx/js@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': + '@nx/js@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': dependencies: '@babel/core': 7.29.7 '@babel/plugin-proposal-decorators': 7.28.0(@babel/core@7.29.7) @@ -15277,7 +15236,7 @@ snapshots: '@zkochan/js-yaml': 0.0.7 babel-plugin-const-enum: 1.2.0(@babel/core@7.29.7) babel-plugin-macros: 3.1.0 - babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.29.7)(@babel/traverse@7.29.7) + babel-plugin-transform-typescript-metadata: 0.3.2(@babel/core@7.29.7)(@babel/traverse@7.29.8) chalk: 4.1.2 columnify: 1.6.0 detect-port: 2.1.0 @@ -15299,14 +15258,14 @@ snapshots: - nx - supports-color - '@nx/module-federation@22.7.2(71acb53b38112c0893e6c056e8943136)': + '@nx/module-federation@22.7.2(b0dcdc95bb0ed63b676cadeba88952fd)': dependencies: '@module-federation/enhanced': 2.4.0(@rspack/core@1.6.8(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)) '@module-federation/node': 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.23))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)) '@module-federation/sdk': 2.4.0(node-fetch@2.7.0(encoding@0.1.13)) '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/web': 22.7.2(888f284af7850e1ced4d654d87699281) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/web': 22.7.2(0222b886c58439e845e61058a381daaa) '@rspack/core': 1.6.8(@swc/helpers@0.5.23) express: 4.22.1 http-proxy-middleware: 3.0.5 @@ -15370,11 +15329,11 @@ snapshots: '@nx/nx-win32-x64-msvc@22.7.2': optional: true - '@nx/playwright@22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@playwright/test@1.62.0)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': + '@nx/playwright@22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@playwright/test@1.62.0)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))': dependencies: '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/eslint': 22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/eslint': 22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) minimatch: 10.2.5 tslib: 2.8.1 optionalDependencies: @@ -15391,14 +15350,14 @@ snapshots: - supports-color - verdaccio - '@nx/rspack@22.7.2(2f8e7c6b2dfd976b2f08f03cf47b966f)': + '@nx/rspack@22.7.2(745e8cc09db8b72c25a2adfc8e9f3271)': dependencies: '@module-federation/enhanced': 2.4.0(@rspack/core@1.6.8(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)) '@module-federation/node': 2.7.26(@rspack/core@1.6.8(@swc/helpers@0.5.23))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)) '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/module-federation': 22.7.2(71acb53b38112c0893e6c056e8943136) - '@nx/web': 22.7.2(888f284af7850e1ced4d654d87699281) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/module-federation': 22.7.2(b0dcdc95bb0ed63b676cadeba88952fd) + '@nx/web': 22.7.2(0222b886c58439e845e61058a381daaa) '@phenomnomnominal/tsquery': 6.2.0(typescript@5.9.3) '@rspack/core': 1.6.8(@swc/helpers@0.5.23) '@rspack/dev-server': 1.1.5(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@types/express@5.0.6)(webpack@5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)) @@ -15458,19 +15417,19 @@ snapshots: - webpack-cli - webpack-hot-middleware - '@nx/web@22.7.2(888f284af7850e1ced4d654d87699281)': + '@nx/web@22.7.2(0222b886c58439e845e61058a381daaa)': dependencies: '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) detect-port: 2.1.0 http-server: 14.1.1 picocolors: 1.1.1 tslib: 2.8.1 optionalDependencies: - '@nx/eslint': 22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/jest': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3) - '@nx/playwright': 22.7.2(@babel/traverse@7.29.7)(@nx/jest@22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@playwright/test@1.62.0)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/webpack': 22.7.2(@babel/traverse@7.29.7)(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3) + '@nx/eslint': 22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/jest': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3) + '@nx/playwright': 22.7.2(@babel/traverse@7.29.8)(@nx/jest@22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3))(typescript@5.9.3))(@playwright/test@1.62.0)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(@zkochan/js-yaml@0.0.7)(eslint@9.39.2(jiti@1.21.7))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/webpack': 22.7.2(@babel/traverse@7.29.8)(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3) transitivePeerDependencies: - '@babel/traverse' - '@swc-node/register' @@ -15480,11 +15439,11 @@ snapshots: - supports-color - verdaccio - '@nx/webpack@22.7.2(@babel/traverse@7.29.7)(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3)': + '@nx/webpack@22.7.2(@babel/traverse@7.29.8)(@rspack/core@1.6.8(@swc/helpers@0.5.23))(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1)(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23)))(typescript@5.9.3)': dependencies: '@babel/core': 7.29.7 '@nx/devkit': 22.7.2(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) - '@nx/js': 22.7.2(@babel/traverse@7.29.7)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) + '@nx/js': 22.7.2(@babel/traverse@7.29.8)(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))(nx@22.7.2(@swc-node/register@1.12.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(@swc/types@0.1.27)(typescript@5.9.3))(@swc/core@1.15.46(@swc/helpers@0.5.23))) '@phenomnomnominal/tsquery': 6.2.0(typescript@5.9.3) ajv: 8.18.0 autoprefixer: 10.4.23(postcss@8.5.6) @@ -15623,65 +15582,61 @@ snapshots: '@oxc-resolver/binding-win32-x64-msvc@11.17.1': optional: true - '@parcel/watcher-android-arm64@2.5.1': + '@parcel/watcher-android-arm64@2.6.0': optional: true - '@parcel/watcher-darwin-arm64@2.5.1': + '@parcel/watcher-darwin-arm64@2.6.0': optional: true - '@parcel/watcher-darwin-x64@2.5.1': + '@parcel/watcher-darwin-x64@2.6.0': optional: true - '@parcel/watcher-freebsd-x64@2.5.1': + '@parcel/watcher-freebsd-x64@2.6.0': optional: true - '@parcel/watcher-linux-arm-glibc@2.5.1': + '@parcel/watcher-linux-arm-glibc@2.6.0': optional: true - '@parcel/watcher-linux-arm-musl@2.5.1': + '@parcel/watcher-linux-arm-musl@2.6.0': optional: true - '@parcel/watcher-linux-arm64-glibc@2.5.1': + '@parcel/watcher-linux-arm64-glibc@2.6.0': optional: true - '@parcel/watcher-linux-arm64-musl@2.5.1': + '@parcel/watcher-linux-arm64-musl@2.6.0': optional: true - '@parcel/watcher-linux-x64-glibc@2.5.1': + '@parcel/watcher-linux-x64-glibc@2.6.0': optional: true - '@parcel/watcher-linux-x64-musl@2.5.1': + '@parcel/watcher-linux-x64-musl@2.6.0': optional: true - '@parcel/watcher-win32-arm64@2.5.1': + '@parcel/watcher-win32-arm64@2.6.0': optional: true - '@parcel/watcher-win32-ia32@2.5.1': + '@parcel/watcher-win32-x64@2.6.0': optional: true - '@parcel/watcher-win32-x64@2.5.1': - optional: true - - '@parcel/watcher@2.5.1': + '@parcel/watcher@2.6.0': dependencies: - detect-libc: 1.0.3 + detect-libc: 2.1.2 is-glob: 4.0.3 - micromatch: 4.0.8 node-addon-api: 7.1.1 + picomatch: 4.0.4 optionalDependencies: - '@parcel/watcher-android-arm64': 2.5.1 - '@parcel/watcher-darwin-arm64': 2.5.1 - '@parcel/watcher-darwin-x64': 2.5.1 - '@parcel/watcher-freebsd-x64': 2.5.1 - '@parcel/watcher-linux-arm-glibc': 2.5.1 - '@parcel/watcher-linux-arm-musl': 2.5.1 - '@parcel/watcher-linux-arm64-glibc': 2.5.1 - '@parcel/watcher-linux-arm64-musl': 2.5.1 - '@parcel/watcher-linux-x64-glibc': 2.5.1 - '@parcel/watcher-linux-x64-musl': 2.5.1 - '@parcel/watcher-win32-arm64': 2.5.1 - '@parcel/watcher-win32-ia32': 2.5.1 - '@parcel/watcher-win32-x64': 2.5.1 + '@parcel/watcher-android-arm64': 2.6.0 + '@parcel/watcher-darwin-arm64': 2.6.0 + '@parcel/watcher-darwin-x64': 2.6.0 + '@parcel/watcher-freebsd-x64': 2.6.0 + '@parcel/watcher-linux-arm-glibc': 2.6.0 + '@parcel/watcher-linux-arm-musl': 2.6.0 + '@parcel/watcher-linux-arm64-glibc': 2.6.0 + '@parcel/watcher-linux-arm64-musl': 2.6.0 + '@parcel/watcher-linux-x64-glibc': 2.6.0 + '@parcel/watcher-linux-x64-musl': 2.6.0 + '@parcel/watcher-win32-arm64': 2.6.0 + '@parcel/watcher-win32-x64': 2.6.0 optional: true '@phenomnomnominal/tsquery@6.2.0(typescript@5.9.3)': @@ -15729,9 +15684,12 @@ snapshots: '@rolldown/binding-openharmony-arm64@1.0.0-rc.4': optional: true - '@rolldown/binding-wasm32-wasi@1.0.0-rc.4': + '@rolldown/binding-wasm32-wasi@1.0.0-rc.4(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3)': dependencies: - '@napi-rs/wasm-runtime': 1.1.1 + '@napi-rs/wasm-runtime': 1.2.2(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3) + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' optional: true '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.4': @@ -15746,7 +15704,7 @@ snapshots: dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 - picomatch: 4.0.4 + picomatch: 4.0.3 optionalDependencies: rollup: 4.59.0 @@ -15905,18 +15863,10 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@schematics/angular@21.2.17(chokidar@5.0.0)': + '@schematics/angular@21.2.19(chokidar@5.0.0)': dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) - jsonc-parser: 3.3.1 - transitivePeerDependencies: - - chokidar - - '@schematics/angular@21.2.9(chokidar@5.0.0)': - dependencies: - '@angular-devkit/core': 21.2.9(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.9(chokidar@5.0.0) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.19(chokidar@5.0.0) jsonc-parser: 3.3.1 transitivePeerDependencies: - chokidar @@ -15956,35 +15906,35 @@ snapshots: '@sigstore/bundle@4.0.0': dependencies: - '@sigstore/protobuf-specs': 0.5.0 + '@sigstore/protobuf-specs': 0.5.1 - '@sigstore/core@3.1.0': {} + '@sigstore/core@3.2.1': {} - '@sigstore/protobuf-specs@0.5.0': {} + '@sigstore/protobuf-specs@0.5.1': {} - '@sigstore/sign@4.1.0': + '@sigstore/sign@4.1.1': dependencies: + '@gar/promise-retry': 1.0.3 '@sigstore/bundle': 4.0.0 - '@sigstore/core': 3.1.0 - '@sigstore/protobuf-specs': 0.5.0 - make-fetch-happen: 15.0.3 + '@sigstore/core': 3.2.1 + '@sigstore/protobuf-specs': 0.5.1 + make-fetch-happen: 15.0.6 proc-log: 6.1.0 - promise-retry: 2.0.1 transitivePeerDependencies: - supports-color - '@sigstore/tuf@4.0.1': + '@sigstore/tuf@4.0.2': dependencies: - '@sigstore/protobuf-specs': 0.5.0 + '@sigstore/protobuf-specs': 0.5.1 tuf-js: 4.1.0 transitivePeerDependencies: - supports-color - '@sigstore/verify@3.1.0': + '@sigstore/verify@3.1.1': dependencies: '@sigstore/bundle': 4.0.0 - '@sigstore/core': 3.1.0 - '@sigstore/protobuf-specs': 0.5.0 + '@sigstore/core': 3.2.1 + '@sigstore/protobuf-specs': 0.5.1 '@sinclair/typebox@0.34.46': {} @@ -16129,6 +16079,11 @@ snapshots: tslib: 2.8.1 optional: true + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 @@ -16587,9 +16542,9 @@ snapshots: global: 4.4.0 is-function: 1.0.2 - '@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.5(patch_hash=b3a8f88ab420b6504a61ffb0f8e402f112c7fda7f3f3e802d21272da7969882d)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0))': + '@vitejs/plugin-basic-ssl@2.1.4(vite@7.3.6(patch_hash=215b6585a9c92fa68c096d500f4676983200307b1e64c1321e20ccbd50bbc8f3)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0))': dependencies: - vite: 7.3.5(patch_hash=b3a8f88ab420b6504a61ffb0f8e402f112c7fda7f3f3e802d21272da7969882d)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0) + vite: 7.3.6(patch_hash=215b6585a9c92fa68c096d500f4676983200307b1e64c1321e20ccbd50bbc8f3)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0) '@webassemblyjs/ast@1.14.1': dependencies: @@ -16797,16 +16752,16 @@ snapshots: '@algolia/requester-fetch': 5.48.1 '@algolia/requester-node-http': 5.48.1 - angular-eslint@21.4.0(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript-eslint@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(typescript@5.9.3): + angular-eslint@21.4.0(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript-eslint@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(typescript@5.9.3): dependencies: - '@angular-devkit/core': 21.2.17(chokidar@5.0.0) - '@angular-devkit/schematics': 21.2.17(chokidar@5.0.0) - '@angular-eslint/builder': 21.4.0(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@angular-devkit/core': 21.2.19(chokidar@5.0.0) + '@angular-devkit/schematics': 21.2.19(chokidar@5.0.0) + '@angular-eslint/builder': 21.4.0(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/eslint-plugin': 21.4.0(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/eslint-plugin-template': 21.4.0(@angular-eslint/template-parser@21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@angular-eslint/schematics': 21.4.0(@angular-eslint/template-parser@21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.17(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@angular-eslint/schematics': 21.4.0(@angular-eslint/template-parser@21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(@angular/cli@21.2.19(@types/node@20.19.9)(chokidar@5.0.0))(@typescript-eslint/types@8.66.0)(@typescript-eslint/utils@8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(chokidar@5.0.0)(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@angular-eslint/template-parser': 21.4.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - '@angular/cli': 21.2.17(@types/node@20.19.9)(chokidar@5.0.0) + '@angular/cli': 21.2.19(@types/node@20.19.9)(chokidar@5.0.0) '@typescript-eslint/types': 8.66.0 '@typescript-eslint/utils': 8.65.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) eslint: 9.39.2(jiti@1.21.7) @@ -16816,10 +16771,10 @@ snapshots: - chokidar - supports-color - angularx-qrcode@21.0.5(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)): + angularx-qrcode@21.0.5(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)): dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) qrcode: 1.5.4 tslib: 2.8.1 @@ -16833,7 +16788,7 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-escapes@7.2.0: + ansi-escapes@7.3.0: dependencies: environment: 1.1.0 @@ -16893,7 +16848,7 @@ snapshots: minimatch: 10.1.1 plist: 3.1.0 resedit: 1.7.2 - semver: 7.7.3 + semver: 7.8.5 tar: 6.2.1 temp-file: 3.4.0 tiny-async-pool: 1.3.0 @@ -17197,12 +17152,12 @@ snapshots: transitivePeerDependencies: - supports-color - babel-plugin-transform-typescript-metadata@0.3.2(@babel/core@7.29.7)(@babel/traverse@7.29.7): + babel-plugin-transform-typescript-metadata@0.3.2(@babel/core@7.29.7)(@babel/traverse@7.29.8): dependencies: '@babel/core': 7.29.7 '@babel/helper-plugin-utils': 7.27.1 optionalDependencies: - '@babel/traverse': 7.29.7 + '@babel/traverse': 7.29.8 babel-preset-current-node-syntax@1.2.0(@babel/core@7.29.7): dependencies: @@ -17243,6 +17198,8 @@ snapshots: baseline-browser-mapping@2.10.29: {} + baseline-browser-mapping@2.11.12: {} + baseline-browser-mapping@2.9.11: {} basic-auth@2.0.1: @@ -17257,11 +17214,11 @@ snapshots: css-what: 7.0.0 dom-serializer: 2.0.0 domhandler: 5.0.3 - htmlparser2: 10.0.0 + htmlparser2: 10.1.0 picocolors: 1.1.1 - postcss: 8.5.6 + postcss: 8.5.26 postcss-media-query-parser: 0.2.3 - postcss-safe-parser: 7.0.1(postcss@8.5.6) + postcss-safe-parser: 7.0.1(postcss@8.5.26) better-sqlite3@12.9.0: dependencies: @@ -17376,6 +17333,14 @@ snapshots: node-releases: 2.0.38 update-browserslist-db: 1.2.3(browserslist@4.28.2) + browserslist@4.28.7: + dependencies: + baseline-browser-mapping: 2.11.12 + caniuse-lite: 1.0.30001809 + electron-to-chromium: 1.5.402 + node-releases: 2.0.53 + update-browserslist-db: 1.3.0(browserslist@4.28.7) + bs-logger@0.2.6: dependencies: fast-json-stable-stringify: 2.1.0 @@ -17460,19 +17425,18 @@ snapshots: transitivePeerDependencies: - bluebird - cacache@20.0.3: + cacache@20.0.4: dependencies: '@npmcli/fs': 5.0.0 fs-minipass: 3.0.3 glob: 13.0.6 - lru-cache: 11.2.4 + lru-cache: 11.5.2 minipass: 7.1.3 minipass-collect: 2.0.1 minipass-flush: 1.0.7 minipass-pipeline: 1.2.4 - p-map: 7.0.4 + p-map: 7.0.6 ssri: 13.0.1 - unique-filename: 5.0.0 cacheable-lookup@5.0.4: {} @@ -17516,7 +17480,7 @@ snapshots: caniuse-api@3.0.0: dependencies: browserslist: 4.28.2 - caniuse-lite: 1.0.30001792 + caniuse-lite: 1.0.30001809 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 @@ -17524,6 +17488,8 @@ snapshots: caniuse-lite@1.0.30001792: {} + caniuse-lite@1.0.30001809: {} + ccount@2.0.1: {} chalk@3.0.0: @@ -17548,7 +17514,7 @@ snapshots: character-reference-invalid@2.0.1: {} - chardet@2.1.1: {} + chardet@2.2.0: {} chokidar@3.6.0: dependencies: @@ -17568,7 +17534,7 @@ snapshots: chokidar@5.0.0: dependencies: - readdirp: 5.0.0 + readdirp: 5.1.1 chownr@1.1.4: {} @@ -17610,10 +17576,10 @@ snapshots: string-width: 4.2.3 optional: true - cli-truncate@5.1.1: + cli-truncate@5.2.0: dependencies: - slice-ansi: 7.1.2 - string-width: 8.2.0 + slice-ansi: 8.0.0 + string-width: 8.2.2 cli-width@4.1.0: {} @@ -17632,7 +17598,7 @@ snapshots: cliui@9.0.1: dependencies: string-width: 7.2.0 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi: 9.0.2 clone-deep@4.0.1: @@ -17767,12 +17733,12 @@ snapshots: normalize-path: 3.0.0 schema-utils: 4.3.3 serialize-javascript: 7.0.5 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 webpack: 5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1) core-js-compat@3.47.0: dependencies: - browserslist: 4.28.2 + browserslist: 4.28.7 core-util-is@1.0.2: optional: true @@ -18061,9 +18027,6 @@ snapshots: destroy@1.2.0: {} - detect-libc@1.0.3: - optional: true - detect-libc@2.1.2: {} detect-newline@3.1.0: {} @@ -18249,6 +18212,8 @@ snapshots: electron-to-chromium@1.5.353: {} + electron-to-chromium@1.5.402: {} + electron-updater@6.8.9: dependencies: builder-util-runtime: 9.7.0 @@ -18315,6 +18280,10 @@ snapshots: entities@6.0.1: {} + entities@7.0.1: {} + + entities@8.0.0: {} + env-paths@2.2.1: {} env-paths@3.0.0: {} @@ -18765,13 +18734,15 @@ snapshots: eventemitter3@5.0.1: {} + eventemitter3@5.0.4: {} + events@3.3.0: {} - eventsource-parser@3.0.6: {} + eventsource-parser@3.1.0: {} eventsource@3.0.7: dependencies: - eventsource-parser: 3.0.6 + eventsource-parser: 3.1.0 execa@5.1.1: dependencies: @@ -18920,6 +18891,10 @@ snapshots: dependencies: bser: 2.1.1 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: picomatch: 4.0.4 @@ -19042,7 +19017,7 @@ snapshots: minimatch: 3.1.2 node-abort-controller: 3.1.1 schema-utils: 3.3.0 - semver: 7.7.4 + semver: 7.8.5 tapable: 2.3.0 typescript: 5.9.3 webpack: 5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1) @@ -19142,7 +19117,7 @@ snapshots: get-east-asian-width@1.4.0: {} - get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} get-intrinsic@1.3.0: dependencies: @@ -19209,7 +19184,7 @@ snapshots: glob@13.0.6: dependencies: - minimatch: 10.2.4 + minimatch: 10.2.6 minipass: 7.1.3 path-scurry: 2.0.2 @@ -19484,9 +19459,9 @@ snapshots: dependencies: lru-cache: 6.0.0 - hosted-git-info@9.0.2: + hosted-git-info@9.0.3: dependencies: - lru-cache: 11.2.4 + lru-cache: 11.5.2 hpack.js@2.1.6: dependencies: @@ -19511,12 +19486,12 @@ snapshots: html-void-elements@3.0.0: {} - htmlparser2@10.0.0: + htmlparser2@10.1.0: dependencies: domelementtype: 2.3.0 domhandler: 5.0.3 domutils: 3.2.2 - entities: 6.0.1 + entities: 7.0.1 http-assert@1.5.0: dependencies: @@ -19677,7 +19652,6 @@ snapshots: iconv-lite@0.7.3: dependencies: safer-buffer: 2.1.2 - optional: true icss-utils@5.1.0(postcss@8.5.6): dependencies: @@ -19691,7 +19665,7 @@ snapshots: ignore-walk@8.0.0: dependencies: - minimatch: 10.2.4 + minimatch: 10.2.6 ignore@5.3.2: {} @@ -19830,7 +19804,7 @@ snapshots: is-fullwidth-code-point@5.1.0: dependencies: - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 is-function@1.0.2: {} @@ -19967,8 +19941,8 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.29.7 - '@babel/parser': 7.29.0 - '@istanbuljs/schema': 0.1.3 + '@babel/parser': 7.29.8 + '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 7.7.4 transitivePeerDependencies: @@ -20048,7 +20022,7 @@ snapshots: jest-config: 30.4.2(@types/node@20.19.9)(babel-plugin-macros@3.1.0)(esbuild-register@3.6.0(esbuild@0.28.1))(ts-node@10.9.2(@swc/core@1.15.46(@swc/helpers@0.5.23))(@types/node@20.19.9)(typescript@5.9.3)) jest-util: 30.4.1 jest-validate: 30.4.1 - yargs: 17.7.2 + yargs: 17.7.3 transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -20145,7 +20119,7 @@ snapshots: jest-regex-util: 30.4.0 jest-util: 30.4.1 jest-worker: 30.4.1 - picomatch: 4.0.4 + picomatch: 4.0.5 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -20189,7 +20163,7 @@ snapshots: chalk: 4.1.2 graceful-fs: 4.2.11 jest-util: 30.4.1 - picomatch: 4.0.4 + picomatch: 4.0.5 pretty-format: 30.4.1 slash: 3.0.0 stack-utils: 2.0.6 @@ -20210,12 +20184,12 @@ snapshots: optionalDependencies: jest-resolve: 30.4.1 - jest-preset-angular@15.0.3(c4e4d73a3616691068af99860e93e092): + jest-preset-angular@15.0.3(98452fae979b413e96b064b581c4172d): dependencies: - '@angular/compiler-cli': 21.2.17(@angular/compiler@21.2.17)(typescript@5.9.3) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) - '@angular/platform-browser-dynamic': 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@21.2.17)(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))) + '@angular/compiler-cli': 21.2.19(@angular/compiler@21.2.19)(typescript@5.9.3) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/platform-browser-dynamic': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/compiler@21.2.19)(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))) '@jest/environment-jsdom-abstract': 30.2.0(jsdom@26.1.0) bs-logger: 0.2.6 esbuild-wasm: 0.27.2 @@ -20343,7 +20317,7 @@ snapshots: chalk: 4.1.2 ci-info: 4.3.1 graceful-fs: 4.2.11 - picomatch: 4.0.4 + picomatch: 4.0.5 jest-util@30.4.1: dependencies: @@ -20407,7 +20381,7 @@ snapshots: jiti@2.6.1: {} - jose@6.1.3: {} + jose@6.2.8: {} js-tokens@4.0.0: {} @@ -20585,9 +20559,9 @@ snapshots: listr2@9.0.5: dependencies: - cli-truncate: 5.1.1 + cli-truncate: 5.2.0 colorette: 2.0.20 - eventemitter3: 5.0.1 + eventemitter3: 5.0.4 log-update: 6.1.0 rfdc: 1.4.1 wrap-ansi: 9.0.2 @@ -20595,7 +20569,7 @@ snapshots: lmdb@3.5.1: dependencies: '@harperfast/extended-iterable': 1.0.3 - msgpackr: 1.11.8 + msgpackr: 1.12.1 node-addon-api: 6.1.0 node-gyp-build-optional-packages: 5.2.2 ordered-binary: 1.6.1 @@ -20654,14 +20628,14 @@ snapshots: log-symbols@7.0.1: dependencies: is-unicode-supported: 2.1.0 - yoctocolors: 2.1.2 + yoctocolors: 2.2.0 log-update@6.1.0: dependencies: - ansi-escapes: 7.2.0 + ansi-escapes: 7.3.0 cli-cursor: 5.0.0 slice-ansi: 7.1.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrap-ansi: 9.0.2 log4js@6.9.1: @@ -20684,6 +20658,8 @@ snapshots: lru-cache@11.2.4: {} + lru-cache@11.5.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -20726,7 +20702,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.7.3 + semver: 7.8.5 make-error@1.3.6: {} @@ -20752,28 +20728,12 @@ snapshots: - bluebird - supports-color - make-fetch-happen@15.0.3: - dependencies: - '@npmcli/agent': 4.0.0 - cacache: 20.0.3 - http-cache-semantics: 4.2.0 - minipass: 7.1.3 - minipass-fetch: 5.0.1 - minipass-flush: 1.0.7 - minipass-pipeline: 1.2.4 - negotiator: 1.0.0 - proc-log: 6.1.0 - promise-retry: 2.0.1 - ssri: 13.0.1 - transitivePeerDependencies: - - supports-color - make-fetch-happen@15.0.6: dependencies: '@gar/promise-retry': 1.0.3 - '@npmcli/agent': 4.0.0 + '@npmcli/agent': 4.0.2 '@npmcli/redact': 4.0.0 - cacache: 20.0.3 + cacache: 20.0.4 http-cache-semantics: 4.2.0 minipass: 7.1.3 minipass-fetch: 5.0.2 @@ -21353,14 +21313,6 @@ snapshots: optionalDependencies: encoding: 0.1.13 - minipass-fetch@5.0.1: - dependencies: - minipass: 7.1.3 - minipass-sized: 2.0.0 - minizlib: 3.1.0 - optionalDependencies: - encoding: 0.1.13 - minipass-fetch@5.0.2: dependencies: minipass: 7.1.3 @@ -21435,21 +21387,21 @@ snapshots: ms@2.1.3: {} - msgpackr-extract@3.0.3: + msgpackr-extract@3.0.4: dependencies: node-gyp-build-optional-packages: 5.2.2 optionalDependencies: - '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.3 - '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.3 + '@msgpackr-extract/msgpackr-extract-darwin-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-darwin-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-arm64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-linux-x64': 3.0.4 + '@msgpackr-extract/msgpackr-extract-win32-x64': 3.0.4 optional: true - msgpackr@1.11.8: + msgpackr@1.12.1: optionalDependencies: - msgpackr-extract: 3.0.3 + msgpackr-extract: 3.0.4 optional: true multicast-dns@7.2.5: @@ -21477,6 +21429,8 @@ snapshots: nanoid@3.3.11: {} + nanoid@3.3.18: {} + napi-build-utils@2.0.0: {} napi-postinstall@0.3.4: {} @@ -21499,23 +21453,23 @@ snapshots: neotraverse@0.6.18: {} - ng-mocks@14.15.3(1918f1ef5f9f83bc2aab38921c00c721): + ng-mocks@14.15.3(b285834fe0000b6ade3305b52068a4d2): dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) - '@angular/forms': 21.2.17(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) - '@angular/platform-browser': 21.2.17(@angular/animations@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/forms': 21.2.19(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(@angular/platform-browser@21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(rxjs@7.8.2) + '@angular/platform-browser': 21.2.19(@angular/animations@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)))(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)) - ngx-indexed-db@21.0.0(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)): + ngx-indexed-db@21.0.0(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)): dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 - ngx-skeleton-loader@11.3.0(@angular/common@21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2)): + ngx-skeleton-loader@11.3.0(@angular/common@21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2))(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2)): dependencies: - '@angular/common': 21.2.17(@angular/core@21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) - '@angular/core': 21.2.17(@angular/compiler@21.2.17)(rxjs@7.8.2)(zone.js@0.16.2) + '@angular/common': 21.2.19(@angular/core@21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2))(rxjs@7.8.2) + '@angular/core': 21.2.19(@angular/compiler@21.2.19)(rxjs@7.8.2)(zone.js@0.16.2) tslib: 2.8.1 nlcst-to-string@4.0.0: @@ -21556,20 +21510,18 @@ snapshots: detect-libc: 2.1.2 optional: true - node-gyp@12.2.0: + node-gyp@12.4.0: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.3 graceful-fs: 4.2.11 - make-fetch-happen: 15.0.3 nopt: 9.0.0 proc-log: 6.1.0 - semver: 7.8.5 - tar: 7.5.9 - tinyglobby: 0.2.15 + semver: 7.7.4 + tar: 7.5.22 + tinyglobby: 0.2.17 + undici: 6.28.0 which: 6.0.1 - transitivePeerDependencies: - - supports-color node-int64@0.4.0: {} @@ -21579,6 +21531,8 @@ snapshots: node-releases@2.0.38: {} + node-releases@2.0.53: {} + node-schedule@2.1.1: dependencies: cron-parser: 4.9.0 @@ -21603,18 +21557,18 @@ snapshots: npm-install-checks@8.0.0: dependencies: - semver: 7.8.5 + semver: 7.7.4 npm-normalize-package-bin@5.0.0: {} npm-package-arg@13.0.2: dependencies: - hosted-git-info: 9.0.2 + hosted-git-info: 9.0.3 proc-log: 6.1.0 semver: 7.7.4 validate-npm-package-name: 7.0.2 - npm-packlist@10.0.3: + npm-packlist@10.0.4: dependencies: ignore-walk: 8.0.0 proc-log: 6.1.0 @@ -21624,15 +21578,15 @@ snapshots: npm-install-checks: 8.0.0 npm-normalize-package-bin: 5.0.0 npm-package-arg: 13.0.2 - semver: 7.8.5 + semver: 7.7.4 npm-registry-fetch@19.1.1: dependencies: '@npmcli/redact': 4.0.0 jsonparse: 1.3.1 - make-fetch-happen: 15.0.3 + make-fetch-happen: 15.0.6 minipass: 7.1.3 - minipass-fetch: 5.0.1 + minipass-fetch: 5.0.2 minizlib: 3.1.0 npm-package-arg: 13.0.2 proc-log: 6.1.0 @@ -21938,7 +21892,7 @@ snapshots: is-unicode-supported: 2.1.0 log-symbols: 7.0.1 stdin-discarder: 0.3.2 - string-width: 8.2.0 + string-width: 8.2.2 ordered-binary@1.6.1: optional: true @@ -22006,7 +21960,7 @@ snapshots: dependencies: aggregate-error: 3.1.0 - p-map@7.0.4: {} + p-map@7.0.6: {} p-queue@8.1.1: dependencies: @@ -22030,22 +21984,22 @@ snapshots: pacote@21.5.1: dependencies: '@gar/promise-retry': 1.0.3 - '@npmcli/git': 7.0.1 + '@npmcli/git': 7.0.2 '@npmcli/installed-package-contents': 4.0.0 '@npmcli/package-json': 7.0.5 '@npmcli/promise-spawn': 9.0.1 - '@npmcli/run-script': 10.0.3 - cacache: 20.0.3 + '@npmcli/run-script': 10.0.4 + cacache: 20.0.4 fs-minipass: 3.0.3 minipass: 7.1.3 npm-package-arg: 13.0.2 - npm-packlist: 10.0.3 + npm-packlist: 10.0.4 npm-pick-manifest: 11.0.3 npm-registry-fetch: 19.1.1 proc-log: 6.1.0 - sigstore: 4.1.0 + sigstore: 4.1.1 ssri: 13.0.1 - tar: 7.5.9 + tar: 7.5.22 transitivePeerDependencies: - supports-color @@ -22086,12 +22040,12 @@ snapshots: parse5-html-rewriting-stream@8.0.0: dependencies: entities: 6.0.1 - parse5: 8.0.0 + parse5: 8.0.1 parse5-sax-parser: 8.0.0 parse5-sax-parser@8.0.0: dependencies: - parse5: 8.0.0 + parse5: 8.0.1 parse5@4.0.0: {} @@ -22103,6 +22057,10 @@ snapshots: dependencies: entities: 6.0.1 + parse5@8.0.1: + dependencies: + entities: 8.0.0 + parseurl@1.3.3: {} path-exists@4.0.0: {} @@ -22122,7 +22080,7 @@ snapshots: path-scurry@2.0.2: dependencies: - lru-cache: 11.2.4 + lru-cache: 11.5.2 minipass: 7.1.3 path-to-regexp@0.1.13: {} @@ -22145,6 +22103,8 @@ snapshots: picomatch@4.0.4: {} + picomatch@4.0.5: {} + pify@2.3.0: {} pify@4.0.1: @@ -22411,9 +22371,9 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-safe-parser@7.0.1(postcss@8.5.6): + postcss-safe-parser@7.0.1(postcss@8.5.26): dependencies: - postcss: 8.5.6 + postcss: 8.5.26 postcss-selector-parser@6.0.10: dependencies: @@ -22443,6 +22403,12 @@ snapshots: postcss-value-parser@4.2.0: {} + postcss@8.5.26: + dependencies: + nanoid: 3.3.18 + picocolors: 1.1.1 + source-map-js: 1.2.1 + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -22621,7 +22587,7 @@ snapshots: readdirp@4.1.2: {} - readdirp@5.0.0: {} + readdirp@5.1.1: {} recma-build-jsx@1.0.0: dependencies: @@ -22884,7 +22850,7 @@ snapshots: dependencies: glob: 7.2.3 - rolldown@1.0.0-rc.4: + rolldown@1.0.0-rc.4(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3): dependencies: '@oxc-project/types': 0.113.0 '@rolldown/pluginutils': 1.0.0-rc.4 @@ -22899,9 +22865,12 @@ snapshots: '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.4 '@rolldown/binding-linux-x64-musl': 1.0.0-rc.4 '@rolldown/binding-openharmony-arm64': 1.0.0-rc.4 - '@rolldown/binding-wasm32-wasi': 1.0.0-rc.4 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.4(@emnapi/core@1.8.1)(@emnapi/runtime@1.11.3) '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.4 '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.4 + transitivePeerDependencies: + - '@emnapi/core' + - '@emnapi/runtime' rollup@4.59.0: dependencies: @@ -23100,7 +23069,7 @@ snapshots: immutable: 5.1.5 source-map-js: 1.2.1 optionalDependencies: - '@parcel/watcher': 2.5.1 + '@parcel/watcher': 2.6.0 optional: true sass@1.97.3: @@ -23109,7 +23078,7 @@ snapshots: immutable: 5.1.5 source-map-js: 1.2.1 optionalDependencies: - '@parcel/watcher': 2.5.1 + '@parcel/watcher': 2.6.0 sax@1.4.3: {} @@ -23270,7 +23239,7 @@ snapshots: dependencies: '@img/colour': 1.0.0 detect-libc: 2.1.2 - semver: 7.8.5 + semver: 7.7.3 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.5 '@img/sharp-darwin-x64': 0.34.5 @@ -23392,14 +23361,14 @@ snapshots: signal-exit@4.1.0: {} - sigstore@4.1.0: + sigstore@4.1.1: dependencies: '@sigstore/bundle': 4.0.0 - '@sigstore/core': 3.1.0 - '@sigstore/protobuf-specs': 0.5.0 - '@sigstore/sign': 4.1.0 - '@sigstore/tuf': 4.0.1 - '@sigstore/verify': 3.1.0 + '@sigstore/core': 3.2.1 + '@sigstore/protobuf-specs': 0.5.1 + '@sigstore/sign': 4.1.1 + '@sigstore/tuf': 4.0.2 + '@sigstore/verify': 3.1.1 transitivePeerDependencies: - supports-color @@ -23413,7 +23382,7 @@ snapshots: simple-update-notifier@2.0.0: dependencies: - semver: 7.7.3 + semver: 7.8.5 sisteransi@1.0.5: {} @@ -23440,6 +23409,11 @@ snapshots: ansi-styles: 6.2.3 is-fullwidth-code-point: 5.1.0 + slice-ansi@8.0.0: + dependencies: + ansi-styles: 6.2.3 + is-fullwidth-code-point: 5.1.0 + smart-buffer@4.2.0: {} smol-toml@1.6.1: {} @@ -23507,9 +23481,9 @@ snapshots: spdx-expression-parse@4.0.0: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.23 - spdx-license-ids@3.0.22: {} + spdx-license-ids@3.0.23: {} spdy-transport@3.0.0: dependencies: @@ -23594,10 +23568,10 @@ snapshots: get-east-asian-width: 1.4.0 strip-ansi: 7.1.2 - string-width@8.2.0: + string-width@8.2.2: dependencies: - get-east-asian-width: 1.5.0 - strip-ansi: 7.1.2 + get-east-asian-width: 1.6.0 + strip-ansi: 7.2.0 string.prototype.trim@1.2.10: dependencies: @@ -23787,7 +23761,7 @@ snapshots: mkdirp: 1.0.4 yallist: 4.0.0 - tar@7.5.9: + tar@7.5.22: dependencies: '@isaacs/fs-minipass': 4.0.1 chownr: 3.0.0 @@ -23859,6 +23833,11 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + tldts-core@6.1.86: {} tldts@6.1.86: @@ -23954,7 +23933,7 @@ snapshots: chalk: 4.1.2 enhanced-resolve: 5.18.4 micromatch: 4.0.8 - semver: 7.7.4 + semver: 7.8.5 source-map: 0.7.6 typescript: 5.9.3 webpack: 5.104.1(@swc/core@1.15.46(@swc/helpers@0.5.23))(esbuild@0.28.1) @@ -24116,10 +24095,12 @@ snapshots: undici-types@7.18.2: {} - undici@7.24.4: {} + undici@6.28.0: {} undici@7.24.7: {} + undici@7.28.0: {} + undici@7.29.0: optional: true @@ -24160,18 +24141,10 @@ snapshots: dependencies: unique-slug: 3.0.0 - unique-filename@5.0.0: - dependencies: - unique-slug: 6.0.0 - unique-slug@3.0.0: dependencies: imurmurhash: 0.1.4 - unique-slug@6.0.0: - dependencies: - imurmurhash: 0.1.4 - unist-util-find-after@5.0.0: dependencies: '@types/unist': 3.0.3 @@ -24273,6 +24246,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.3.0(browserslist@4.28.7): + dependencies: + browserslist: 4.28.7 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -24378,8 +24357,8 @@ snapshots: vite@6.4.1(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0): dependencies: esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 postcss: 8.5.6 rollup: 4.59.0 tinyglobby: 0.2.15 @@ -24394,12 +24373,12 @@ snapshots: tsx: 4.23.1 yaml: 2.9.0 - vite@7.3.5(patch_hash=b3a8f88ab420b6504a61ffb0f8e402f112c7fda7f3f3e802d21272da7969882d)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0): + vite@7.3.6(patch_hash=215b6585a9c92fa68c096d500f4676983200307b1e64c1321e20ccbd50bbc8f3)(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(sass-embedded@1.97.1)(sass@1.97.3)(terser@5.44.1)(tsx@4.23.1)(yaml@2.9.0): dependencies: - esbuild: 0.27.7 + esbuild: 0.28.1 fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - postcss: 8.5.6 + postcss: 8.5.26 rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: @@ -24745,6 +24724,16 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yargs@17.7.3: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yargs@18.0.0: dependencies: cliui: 9.0.1 @@ -24754,6 +24743,15 @@ snapshots: y18n: 5.0.8 yargs-parser: 22.0.0 + yargs@18.1.0: + dependencies: + cliui: 9.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + string-width: 8.2.2 + y18n: 5.0.8 + yargs-parser: 22.0.0 + yn@3.1.1: {} yocto-queue@0.1.0: {} @@ -24768,11 +24766,13 @@ snapshots: yoctocolors@2.1.2: {} + yoctocolors@2.2.0: {} + zod-to-json-schema@3.25.1(zod@3.25.76): dependencies: zod: 3.25.76 - zod-to-json-schema@3.25.1(zod@4.3.6): + zod-to-json-schema@3.25.2(zod@4.3.6): dependencies: zod: 4.3.6 diff --git a/tools/dependencies/vite-transform-filter.test.mjs b/tools/dependencies/vite-transform-filter.test.mjs index 2737b7893..fc627e6af 100644 --- a/tools/dependencies/vite-transform-filter.test.mjs +++ b/tools/dependencies/vite-transform-filter.test.mjs @@ -27,7 +27,7 @@ function extractRegExp(name) { } test('pins the Vite version carrying the local transform-filter backport', () => { - assert.equal(vitePackage.version, '7.3.5'); + assert.equal(vitePackage.version, '7.3.6'); }); test('uses bounded Vite prefilters with precise handler matchers', () => {