diff --git a/.github/workflows/auto-close.yml b/.github/workflows/auto-close.yml new file mode 100644 index 0000000000..559cb20e66 --- /dev/null +++ b/.github/workflows/auto-close.yml @@ -0,0 +1,143 @@ +name: Auto-close PRs + +on: + pull_request_target: # zizmor: ignore[dangerous-triggers] + types: [opened, edited, labeled] + +permissions: {} + +jobs: + parse_template: + runs-on: ubuntu-latest + if: ${{ github.event.action != 'labeled' && github.event.pull_request.head.repo.fork == true }} + permissions: + contents: read + outputs: + uses_template: ${{ steps.check.outputs.uses_template }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + sparse-checkout: .github/pull_request_template.md + sparse-checkout-cone-mode: false + persist-credentials: false + + - name: Check required sections + id: check + env: + BODY: ${{ github.event.pull_request.body }} + run: | + OK=true + while IFS= read -r header; do + printf '%s\n' "$BODY" | grep -qF "$header" || OK=false + done < <(sed '//d' .github/pull_request_template.md | grep "^## ") + echo "uses_template=$OK" >> "$GITHUB_OUTPUT" + + close_template: + runs-on: ubuntu-latest + needs: parse_template + if: ${{ needs.parse_template.outputs.uses_template == 'false' && github.event.pull_request.state != 'closed' }} + permissions: + pull-requests: write + steps: + - name: Comment and close + env: + GH_TOKEN: ${{ github.token }} + NODE_ID: ${{ github.event.pull_request.node_id }} + run: | + gh api graphql \ + -f prId="$NODE_ID" \ + -f body="This PR has been automatically closed as the description doesn't follow our template. After you edit it to match the template, the PR will automatically be reopened." \ + -f query=' + mutation CommentAndClosePR($prId: ID!, $body: String!) { + addComment(input: { + subjectId: $prId, + body: $body + }) { + __typename + } + closePullRequest(input: { + pullRequestId: $prId + }) { + __typename + } + }' + + - name: Add label + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: gh pr edit "$PR_NUMBER" --add-label "auto-closed:template" + + close_llm: + runs-on: ubuntu-latest + if: ${{ github.event.action == 'labeled' && github.event.label.name == 'auto-closed:llm' }} + permissions: + pull-requests: write + steps: + - name: Comment and close + env: + GH_TOKEN: ${{ github.token }} + NODE_ID: ${{ github.event.pull_request.node_id }} + run: | + gh api graphql \ + -f prId="$NODE_ID" \ + -f body="Thank you for your interest in contributing to Immich! Unfortunately this PR looks like it was generated using an LLM. As noted in our [CONTRIBUTING.md](https://github.com/immich-app/immich/blob/main/CONTRIBUTING.md#use-of-generative-ai), we request that you don't use LLMs to generate PRs as those are not a good use of maintainer time." \ + -f query=' + mutation CommentAndClosePR($prId: ID!, $body: String!) { + addComment(input: { + subjectId: $prId, + body: $body + }) { + __typename + } + closePullRequest(input: { + pullRequestId: $prId + }) { + __typename + } + }' + + reopen: + runs-on: ubuntu-latest + needs: parse_template + if: >- + ${{ + needs.parse_template.outputs.uses_template == 'true' + && github.event.pull_request.state == 'closed' + && contains(github.event.pull_request.labels.*.name, 'auto-closed:template') + }} + permissions: + pull-requests: write + steps: + - name: Remove template label + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: gh pr edit "$PR_NUMBER" --remove-label "auto-closed:template" || true + + - name: Check for remaining auto-closed labels + id: check_labels + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ github.event.pull_request.number }} + run: | + REMAINING=$(gh pr view "$PR_NUMBER" --json labels \ + --jq '[.labels[].name | select(startswith("auto-closed:"))] | length') + echo "remaining=$REMAINING" >> "$GITHUB_OUTPUT" + + - name: Reopen PR + if: ${{ steps.check_labels.outputs.remaining == '0' }} + env: + GH_TOKEN: ${{ github.token }} + NODE_ID: ${{ github.event.pull_request.node_id }} + run: | + gh api graphql \ + -f prId="$NODE_ID" \ + -f query=' + mutation ReopenPR($prId: ID!) { + reopenPullRequest(input: { + pullRequestId: $prId + }) { + __typename + } + }' diff --git a/.github/workflows/check-pr-template.yml b/.github/workflows/check-pr-template.yml deleted file mode 100644 index 5419fb27f7..0000000000 --- a/.github/workflows/check-pr-template.yml +++ /dev/null @@ -1,97 +0,0 @@ -name: Check PR Template - -on: - pull_request_target: # zizmor: ignore[dangerous-triggers] - types: [opened, edited] - -permissions: {} - -env: - LABEL_ID: 'LA_kwDOGyI-8M8AAAACcAeOfg' # auto-closed:template - -jobs: - parse: - runs-on: ubuntu-latest - if: ${{ github.event.pull_request.head.repo.fork == true }} - permissions: - contents: read - outputs: - uses_template: ${{ steps.check.outputs.uses_template }} - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - sparse-checkout: .github/pull_request_template.md - sparse-checkout-cone-mode: false - persist-credentials: false - - - name: Check required sections - id: check - env: - BODY: ${{ github.event.pull_request.body }} - run: | - OK=true - while IFS= read -r header; do - printf '%s\n' "$BODY" | grep -qF "$header" || OK=false - done < <(sed '//d' .github/pull_request_template.md | grep "^## ") - echo "uses_template=$OK" >> "$GITHUB_OUTPUT" - - act: - runs-on: ubuntu-latest - needs: parse - permissions: - pull-requests: write - steps: - - name: Close PR - if: ${{ needs.parse.outputs.uses_template == 'false' && github.event.pull_request.state != 'closed' }} - env: - GH_TOKEN: ${{ github.token }} - NODE_ID: ${{ github.event.pull_request.node_id }} - run: | - gh api graphql \ - -f prId="$NODE_ID" \ - -f labelId="$LABEL_ID" \ - -f body="This PR has been automatically closed as the description doesn't follow our template. After you edit it to match the template, the PR will automatically be reopened." \ - -f query=' - mutation CommentAndClosePR($prId: ID!, $body: String!, $labelId: ID!) { - addComment(input: { - subjectId: $prId, - body: $body - }) { - __typename - } - closePullRequest(input: { - pullRequestId: $prId - }) { - __typename - } - addLabelsToLabelable(input: { - labelableId: $prId, - labelIds: [$labelId] - }) { - __typename - } - }' - - - name: Reopen PR (sections now present, PR was auto-closed) - if: ${{ needs.parse.outputs.uses_template == 'true' && github.event.pull_request.state == 'closed' && contains(github.event.pull_request.labels.*.node_id, env.LABEL_ID) }} - env: - GH_TOKEN: ${{ github.token }} - NODE_ID: ${{ github.event.pull_request.node_id }} - run: | - gh api graphql \ - -f prId="$NODE_ID" \ - -f labelId="$LABEL_ID" \ - -f query=' - mutation ReopenPR($prId: ID!, $labelId: ID!) { - reopenPullRequest(input: { - pullRequestId: $prId - }) { - __typename - } - removeLabelsFromLabelable(input: { - labelableId: $prId, - labelIds: [$labelId] - }) { - __typename - } - }' diff --git a/.github/workflows/close-llm-pr.yml b/.github/workflows/close-llm-pr.yml deleted file mode 100644 index 511d5c7f55..0000000000 --- a/.github/workflows/close-llm-pr.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Close LLM-generated PRs - -on: - pull_request_target: - types: [labeled] - -permissions: {} - -jobs: - comment_and_close: - runs-on: ubuntu-latest - if: ${{ github.event.label.name == 'llm-generated' }} - permissions: - pull-requests: write - steps: - - name: Comment and close - env: - GH_TOKEN: ${{ github.token }} - NODE_ID: ${{ github.event.pull_request.node_id }} - run: | - gh api graphql \ - -f prId="$NODE_ID" \ - -f body="Thank you for your interest in contributing to Immich! Unfortunately this PR looks like it was generated using an LLM. As noted in our [CONTRIBUTING.md](https://github.com/immich-app/immich/blob/main/CONTRIBUTING.md#use-of-generative-ai), we request that you don't use LLMs to generate PRs as those are not a good use of maintainer time." \ - -f query=' - mutation CommentAndClosePR($prId: ID!, $body: String!) { - addComment(input: { - subjectId: $prId, - body: $body - }) { - __typename - } - - closePullRequest(input: { - pullRequestId: $prId - }) { - __typename - } - }' diff --git a/cli/package.json b/cli/package.json index 9faf2e4981..c22b2c17b7 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@immich/cli", - "version": "2.6.1", + "version": "2.6.2", "description": "Command Line Interface (CLI) for Immich", "type": "module", "exports": "./dist/index.js", @@ -35,8 +35,7 @@ "prettier-plugin-organize-imports": "^4.0.0", "typescript": "^5.3.3", "typescript-eslint": "^8.28.0", - "vite": "^7.0.0", - "vite-tsconfig-paths": "^6.0.0", + "vite": "^8.0.0", "vitest": "^4.0.0", "vitest-fetch-mock": "^0.4.0", "yaml": "^2.3.1" diff --git a/cli/vite.config.ts b/cli/vite.config.ts index c69b467011..fc57b9c796 100644 --- a/cli/vite.config.ts +++ b/cli/vite.config.ts @@ -1,10 +1,12 @@ import { defineConfig, UserConfig } from 'vite'; -import tsconfigPaths from 'vite-tsconfig-paths'; export default defineConfig({ - resolve: { alias: { src: '/src' } }, + resolve: { + alias: { src: '/src' }, + tsconfigPaths: true, + }, build: { - rollupOptions: { + rolldownOptions: { input: 'src/index.ts', output: { dir: 'dist', @@ -16,7 +18,6 @@ export default defineConfig({ // bundle everything except for Node built-ins noExternal: /^(?!node:).*$/, }, - plugins: [tsconfigPaths()], test: { name: 'cli:unit', globals: true, diff --git a/docs/docs/install/requirements.md b/docs/docs/install/requirements.md index ee5db45c9a..178cf45388 100644 --- a/docs/docs/install/requirements.md +++ b/docs/docs/install/requirements.md @@ -8,7 +8,7 @@ Hardware and software requirements for Immich: ## Hardware -- **OS**: Recommended Linux or \*nix operating system (Ubuntu, Debian, etc). +- **OS**: Recommended Linux or \*nix 64-bit operating system (Ubuntu, Debian, etc). - Non-Linux OSes tend to provide a poor Docker experience and are strongly discouraged. Our ability to assist with setup or troubleshooting on non-Linux OSes will be severely reduced. If you still want to try to use a non-Linux OS, you can set it up as follows: @@ -19,6 +19,10 @@ Hardware and software requirements for Immich: If you have issues, we recommend that you switch to a supported VM deployment. - **RAM**: Minimum 6GB, recommended 8GB. - **CPU**: Minimum 2 cores, recommended 4 cores. + - Immich runs on the `amd64` and `arm64` platforms. + Since `v2.6`, the machine learning container on `amd64` requires the `>= x86-64-v2` [microarchitecture level](https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels). + Most CPUs released since ~2012 support this microarchitecture. + If you are using a virtual machine, ensure you have selected a [supported microarchitecture](https://pve.proxmox.com/pve-docs/chapter-qm.html#_qemu_cpu_types). - **Storage**: Recommended Unix-compatible filesystem (EXT4, ZFS, APFS, etc.) with support for user/group ownership and permissions. - The generation of thumbnails and transcoded video can increase the size of the photo library by 10-20% on average. diff --git a/docs/static/archived-versions.json b/docs/static/archived-versions.json index b253234b39..09cd1b1548 100644 --- a/docs/static/archived-versions.json +++ b/docs/static/archived-versions.json @@ -1,7 +1,7 @@ [ { - "label": "v2.6.1", - "url": "https://docs.v2.6.1.archive.immich.app" + "label": "v2.6.2", + "url": "https://docs.v2.6.2.archive.immich.app" }, { "label": "v2.5.6", diff --git a/e2e/package.json b/e2e/package.json index 48bc8de65e..58304f3433 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "immich-e2e", - "version": "2.6.1", + "version": "2.6.2", "description": "", "main": "index.js", "type": "module", diff --git a/e2e/src/specs/server/api/album.e2e-spec.ts b/e2e/src/specs/server/api/album.e2e-spec.ts index c4f06edd93..a9e90940ab 100644 --- a/e2e/src/specs/server/api/album.e2e-spec.ts +++ b/e2e/src/specs/server/api/album.e2e-spec.ts @@ -524,14 +524,19 @@ describe('/albums', () => { expect(body).toEqual(errorDto.badRequest('Not found or no album.update access')); }); - it('should not be able to update as an editor', async () => { + it('should be able to update as an editor', async () => { const { status, body } = await request(app) .patch(`/albums/${user1Albums[0].id}`) .set('Authorization', `Bearer ${user2.accessToken}`) .send({ albumName: 'New album name' }); - expect(status).toBe(400); - expect(body).toEqual(errorDto.badRequest('Not found or no album.update access')); + expect(status).toBe(200); + expect(body).toEqual( + expect.objectContaining({ + id: user1Albums[0].id, + albumName: 'New album name', + }), + ); }); }); diff --git a/e2e/src/specs/web/duplicates.e2e-spec.ts b/e2e/src/specs/web/duplicates.e2e-spec.ts new file mode 100644 index 0000000000..34f11cdf78 --- /dev/null +++ b/e2e/src/specs/web/duplicates.e2e-spec.ts @@ -0,0 +1,51 @@ +import { AssetMediaResponseDto, LoginResponseDto, updateAssets } from '@immich/sdk'; +import { expect, test } from '@playwright/test'; +import crypto from 'node:crypto'; +import { asBearerAuth, utils } from 'src/utils'; + +test.describe('Duplicates Utility', () => { + let admin: LoginResponseDto; + let firstAsset: AssetMediaResponseDto; + let secondAsset: AssetMediaResponseDto; + + test.beforeAll(async () => { + utils.initSdk(); + await utils.resetDatabase(); + admin = await utils.adminSetup(); + }); + + test.beforeEach(async ({ context }) => { + [firstAsset, secondAsset] = await Promise.all([ + utils.createAsset(admin.accessToken, { deviceAssetId: 'duplicate-a' }), + utils.createAsset(admin.accessToken, { deviceAssetId: 'duplicate-b' }), + ]); + + await updateAssets( + { + assetBulkUpdateDto: { + ids: [firstAsset.id, secondAsset.id], + duplicateId: crypto.randomUUID(), + }, + }, + { headers: asBearerAuth(admin.accessToken) }, + ); + + await utils.setAuthCookies(context, admin.accessToken); + }); + + test('navigates with arrow keys between duplicate preview assets', async ({ page }) => { + await page.goto('/utilities/duplicates'); + await page.getByRole('button', { name: 'View' }).first().click(); + await page.waitForSelector('#immich-asset-viewer'); + + const getViewedAssetId = () => new URL(page.url()).pathname.split('/').at(-1) ?? ''; + const initialAssetId = getViewedAssetId(); + expect([firstAsset.id, secondAsset.id]).toContain(initialAssetId); + + await page.keyboard.press('ArrowRight'); + await expect.poll(getViewedAssetId).not.toBe(initialAssetId); + + await page.keyboard.press('ArrowLeft'); + await expect.poll(getViewedAssetId).toBe(initialAssetId); + }); +}); diff --git a/i18n/package.json b/i18n/package.json index 1e4d885de1..a654f8715f 100644 --- a/i18n/package.json +++ b/i18n/package.json @@ -1,6 +1,6 @@ { "name": "immich-i18n", - "version": "2.6.1", + "version": "2.6.2", "private": true, "scripts": { "format": "prettier --cache --check .", diff --git a/machine-learning/pyproject.toml b/machine-learning/pyproject.toml index 44911976a1..9afaf2ecc8 100644 --- a/machine-learning/pyproject.toml +++ b/machine-learning/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "immich-ml" -version = "2.6.1" +version = "2.6.2" description = "" authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }] requires-python = ">=3.11,<4.0" diff --git a/machine-learning/uv.lock b/machine-learning/uv.lock index b24516cb79..0c1ecf1846 100644 --- a/machine-learning/uv.lock +++ b/machine-learning/uv.lock @@ -898,7 +898,7 @@ wheels = [ [[package]] name = "immich-ml" -version = "2.6.1" +version = "2.6.2" source = { editable = "." } dependencies = [ { name = "aiocache" }, diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt index e7268396e8..cefdf4fbd2 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/core/HttpClientManager.kt @@ -23,10 +23,18 @@ import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.OkHttpClient import org.chromium.net.CronetEngine +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import java.io.ByteArrayInputStream import java.io.File +import java.io.IOException +import java.nio.file.FileVisitResult +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.SimpleFileVisitor +import java.nio.file.attribute.BasicFileAttributes import java.net.Authenticator import java.net.CookieHandler import java.net.PasswordAuthentication @@ -277,10 +285,13 @@ object HttpClientManager { return result } - fun rebuildCronetEngine(): CronetEngine { - val old = cronetEngine!! - cronetEngine = buildCronetEngine() - return old + suspend fun rebuildCronetEngine(): Result { + return runCatching { + cronetEngine?.shutdown() + val deletionResult = deleteFolderAndGetSize(cronetStoragePath.toPath()) + cronetEngine = buildCronetEngine() + deletionResult + } } val cronetStoragePath: File get() = cronetStorageDir @@ -301,7 +312,7 @@ object HttpClientManager { } } - private fun buildCronetEngine(): CronetEngine { + fun buildCronetEngine(): CronetEngine { return CronetEngine.Builder(appContext) .enableHttp2(true) .enableQuic(true) @@ -312,6 +323,27 @@ object HttpClientManager { .build() } + private suspend fun deleteFolderAndGetSize(root: Path): Long = withContext(Dispatchers.IO) { + var totalSize = 0L + + Files.walkFileTree(root, object : SimpleFileVisitor() { + override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult { + totalSize += attrs.size() + Files.delete(file) + return FileVisitResult.CONTINUE + } + + override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult { + if (dir != root) { + Files.delete(dir) + } + return FileVisitResult.CONTINUE + } + }) + + totalSize + } + private fun build(cacheDir: File): OkHttpClient { val connectionPool = ConnectionPool( maxIdleConnections = KEEP_ALIVE_CONNECTIONS, diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/images/RemoteImagesImpl.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/images/RemoteImagesImpl.kt index 8e9fc3f6d5..9255eff44b 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/images/RemoteImagesImpl.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/images/RemoteImagesImpl.kt @@ -21,11 +21,6 @@ import java.io.EOFException import java.io.File import java.io.IOException import java.nio.ByteBuffer -import java.nio.file.FileVisitResult -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.SimpleFileVisitor -import java.nio.file.attribute.BasicFileAttributes import java.util.concurrent.ConcurrentHashMap private class RemoteRequest(val cancellationSignal: CancellationSignal) @@ -205,18 +200,15 @@ private class CronetImageFetcher : ImageFetcher { private fun onDrained() { val onCacheCleared = synchronized(stateLock) { - val onCacheCleared = onCacheCleared + val onCacheCleared = this.onCacheCleared this.onCacheCleared = null onCacheCleared - } - if (onCacheCleared != null) { - val oldEngine = HttpClientManager.rebuildCronetEngine() - oldEngine.shutdown() - CoroutineScope(Dispatchers.IO).launch { - val result = runCatching { deleteFolderAndGetSize(HttpClientManager.cronetStoragePath.toPath()) } - synchronized(stateLock) { draining = false } - onCacheCleared(result) - } + } ?: return + + CoroutineScope(Dispatchers.IO).launch { + val result = HttpClientManager.rebuildCronetEngine() + synchronized(stateLock) { draining = false } + onCacheCleared(result) } } @@ -306,26 +298,6 @@ private class CronetImageFetcher : ImageFetcher { } } - suspend fun deleteFolderAndGetSize(root: Path): Long = withContext(Dispatchers.IO) { - var totalSize = 0L - - Files.walkFileTree(root, object : SimpleFileVisitor() { - override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult { - totalSize += attrs.size() - Files.delete(file) - return FileVisitResult.CONTINUE - } - - override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult { - if (dir != root) { - Files.delete(dir) - } - return FileVisitResult.CONTINUE - } - }) - - totalSize - } } private class OkHttpImageFetcher private constructor( diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile index 3cabc0df0f..b40f394d01 100644 --- a/mobile/android/fastlane/Fastfile +++ b/mobile/android/fastlane/Fastfile @@ -35,8 +35,8 @@ platform :android do task: 'bundle', build_type: 'Release', properties: { - "android.injected.version.code" => 3039, - "android.injected.version.name" => "2.6.1", + "android.injected.version.code" => 3040, + "android.injected.version.name" => "2.6.2", } ) upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index 366d68c313..71be571216 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -80,7 +80,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.6.1 + 2.6.2 CFBundleSignature ???? CFBundleURLTypes diff --git a/mobile/lib/constants/locales.dart b/mobile/lib/constants/locales.dart index e20f037beb..f44aa5cc3e 100644 --- a/mobile/lib/constants/locales.dart +++ b/mobile/lib/constants/locales.dart @@ -7,7 +7,7 @@ const Map locales = { 'Arabic (ar)': Locale('ar'), 'Bulgarian (bg)': Locale('bg'), 'Catalan (ca)': Locale('ca'), - 'Chinese Simplified (zh_CN)': Locale.fromSubtags(languageCode: 'zh', scriptCode: 'SIMPLIFIED'), + 'Chinese Simplified (zh_CN)': Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'), 'Chinese Traditional (zh_TW)': Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'), 'Croatian (hr)': Locale('hr'), 'Czech (cs)': Locale('cs'), diff --git a/mobile/lib/presentation/pages/drift_people_collection.page.dart b/mobile/lib/presentation/pages/drift_people_collection.page.dart index f73dac3af2..d34ce3e776 100644 --- a/mobile/lib/presentation/pages/drift_people_collection.page.dart +++ b/mobile/lib/presentation/pages/drift_people_collection.page.dart @@ -79,6 +79,7 @@ class _DriftPeopleCollectionPageState extends ConsumerState(null); + final hasRequestedSearch = useState(false); final dateInputFilter = useState(null); final peopleCurrentFilterWidget = useState(null); @@ -91,9 +92,11 @@ class DriftSearchPage extends HookConsumerWidget { if (filter.isEmpty) { previousFilter.value = null; + hasRequestedSearch.value = false; return; } + hasRequestedSearch.value = true; unawaited(ref.read(paginatedSearchProvider.notifier).search(filter)); previousFilter.value = filter; } @@ -107,6 +110,8 @@ class DriftSearchPage extends HookConsumerWidget { searchPreFilter() { if (preFilter != null) { Future.delayed(Duration.zero, () { + filter.value = preFilter; + textSearchController.clear(); searchFilter(preFilter); if (preFilter.location.city != null) { @@ -719,7 +724,7 @@ class DriftSearchPage extends HookConsumerWidget { ), ), ), - if (filter.value.isEmpty) + if (!hasRequestedSearch.value) const _SearchSuggestions() else _SearchResultGrid(onScrollEnd: loadMoreSearchResults), diff --git a/mobile/lib/presentation/widgets/action_buttons/similar_photos_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/similar_photos_action_button.widget.dart index 530c3fd8d4..bb42140d0a 100644 --- a/mobile/lib/presentation/widgets/action_buttons/similar_photos_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/similar_photos_action_button.widget.dart @@ -24,20 +24,22 @@ class SimilarPhotosActionButton extends ConsumerWidget { } ref.invalidate(assetViewerProvider); - ref - .read(searchPreFilterProvider.notifier) - .setFilter( - SearchFilter( - assetId: assetId, - people: {}, - location: SearchLocationFilter(), - camera: SearchCameraFilter(), - date: SearchDateFilter(), - display: SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), - rating: SearchRatingFilter(), - mediaType: AssetType.image, - ), - ); + ref.invalidate(paginatedSearchProvider); + + ref.read(searchPreFilterProvider.notifier) + ..clear() + ..setFilter( + SearchFilter( + assetId: assetId, + people: {}, + location: SearchLocationFilter(), + camera: SearchCameraFilter(), + date: SearchDateFilter(), + display: SearchDisplayFilters(isNotInAlbum: false, isArchive: false, isFavorite: false), + rating: SearchRatingFilter(), + mediaType: AssetType.image, + ), + ); unawaited(context.navigateTo(const DriftSearchRoute())); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/rating_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/rating_bar.widget.dart index 64090dc5c2..62a439fe39 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/rating_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/rating_bar.widget.dart @@ -39,6 +39,16 @@ class _RatingBarState extends State { _currentRating = widget.initialRating; } + @override + void didUpdateWidget(covariant RatingBar oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.initialRating != widget.initialRating && _currentRating != widget.initialRating) { + setState(() { + _currentRating = widget.initialRating; + }); + } + } + void _updateRating(Offset localPosition, bool isRTL, {bool isTap = false}) { final totalWidth = widget.itemCount * widget.itemSize + (widget.itemCount - 1) * widget.starPadding; double dx = localPosition.dx; diff --git a/mobile/lib/services/auth.service.dart b/mobile/lib/services/auth.service.dart index c5f3fa6a4a..667681e579 100644 --- a/mobile/lib/services/auth.service.dart +++ b/mobile/lib/services/auth.service.dart @@ -67,6 +67,9 @@ class AuthService { bool isValid = false; try { + final urls = ApiService.getServerUrls(); + urls.add(url); + await NetworkRepository.setHeaders(ApiService.getRequestHeaders(), urls); final uri = Uri.parse('$url/users/me'); final response = await NetworkRepository.client.get(uri); if (response.statusCode == 200) { diff --git a/mobile/lib/utils/action_button.utils.dart b/mobile/lib/utils/action_button.utils.dart index 071956392c..2aad2f264a 100644 --- a/mobile/lib/utils/action_button.utils.dart +++ b/mobile/lib/utils/action_button.utils.dart @@ -143,8 +143,7 @@ enum ActionButtonType { !context.isInLockedView && // context.currentAlbum != null, ActionButtonType.setAlbumCover => - context.isOwner && // - !context.isInLockedView && // + !context.isInLockedView && // context.currentAlbum != null && // context.selectedCount == 1, ActionButtonType.unstack => diff --git a/mobile/lib/utils/cache/custom_image_cache.dart b/mobile/lib/utils/cache/custom_image_cache.dart index 99ce0db57c..2c09030ffa 100644 --- a/mobile/lib/utils/cache/custom_image_cache.dart +++ b/mobile/lib/utils/cache/custom_image_cache.dart @@ -20,7 +20,7 @@ final class CustomImageCache implements ImageCache { set maximumSize(int value) => _small.maximumSize = value; @override - set maximumSizeBytes(int value) => _small.maximumSize = value; + set maximumSizeBytes(int value) => _small.maximumSizeBytes = value; @override void clear() { diff --git a/mobile/lib/widgets/search/search_filter/common/dropdown.dart b/mobile/lib/widgets/search/search_filter/common/dropdown.dart index 70cbfd2c15..9d02f4f3e8 100644 --- a/mobile/lib/widgets/search/search_filter/common/dropdown.dart +++ b/mobile/lib/widgets/search/search_filter/common/dropdown.dart @@ -16,9 +16,15 @@ class SearchDropdown extends StatelessWidget { final Widget? label; final Widget? leadingIcon; + static const WidgetStatePropertyAll _optionPadding = WidgetStatePropertyAll( + EdgeInsetsDirectional.fromSTEB(16, 0, 16, 0), + ); + @override Widget build(BuildContext context) { - final menuStyle = const MenuStyle( + final mediaQuery = MediaQuery.of(context); + final maxMenuHeight = mediaQuery.size.height * 0.5 - mediaQuery.viewPadding.bottom; + const menuStyle = MenuStyle( shape: WidgetStatePropertyAll( RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(15))), ), @@ -26,11 +32,26 @@ class SearchDropdown extends StatelessWidget { return LayoutBuilder( builder: (context, constraints) { + final styledEntries = dropdownMenuEntries + .map( + (entry) => DropdownMenuEntry( + value: entry.value, + label: entry.label, + labelWidget: entry.labelWidget, + enabled: entry.enabled, + leadingIcon: entry.leadingIcon, + trailingIcon: entry.trailingIcon, + style: (entry.style ?? const ButtonStyle()).copyWith(padding: _optionPadding), + ), + ) + .toList(growable: false); + return DropdownMenu( controller: controller, leadingIcon: leadingIcon, width: constraints.maxWidth, - dropdownMenuEntries: dropdownMenuEntries, + menuHeight: maxMenuHeight, + dropdownMenuEntries: styledEntries, label: label, menuStyle: menuStyle, trailingIcon: const Icon(Icons.arrow_drop_down_rounded), diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index ceb41ac7bb..3dc0a0c1fa 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -3,7 +3,7 @@ Immich API This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: -- API version: 2.6.1 +- API version: 2.6.2 - Generator version: 7.8.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 201f4395a3..b0046ec449 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -2,7 +2,7 @@ name: immich_mobile description: Immich - selfhosted backup media file on mobile phone publish_to: 'none' -version: 2.6.1+3039 +version: 2.6.2+3040 environment: sdk: '>=3.8.0 <4.0.0' diff --git a/mobile/test/utils/action_button_utils_test.dart b/mobile/test/utils/action_button_utils_test.dart index b5540f9dc7..9956dfa2d0 100644 --- a/mobile/test/utils/action_button_utils_test.dart +++ b/mobile/test/utils/action_button_utils_test.dart @@ -727,7 +727,7 @@ void main() { expect(ActionButtonType.setAlbumCover.shouldShow(context), isTrue); }); - test('should not show when not owner', () { + test('should show when not owner', () { final album = createRemoteAlbum(); final context = ActionButtonContext( asset: mergedAsset, @@ -742,7 +742,7 @@ void main() { selectedCount: 1, ); - expect(ActionButtonType.setAlbumCover.shouldShow(context), isFalse); + expect(ActionButtonType.setAlbumCover.shouldShow(context), isTrue); }); test('should not show when in locked view', () { diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index dfca8737f8..a504214681 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -15166,7 +15166,7 @@ "info": { "title": "Immich", "description": "Immich API", - "version": "2.6.1", + "version": "2.6.2", "contact": {} }, "tags": [ diff --git a/open-api/typescript-sdk/package.json b/open-api/typescript-sdk/package.json index 42184f3841..9f6846d072 100644 --- a/open-api/typescript-sdk/package.json +++ b/open-api/typescript-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@immich/sdk", - "version": "2.6.1", + "version": "2.6.2", "description": "Auto-generated TypeScript SDK for the Immich API", "type": "module", "main": "./build/index.js", diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 3f87aa82ef..aa71f9f896 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -1,6 +1,6 @@ /** * Immich - * 2.6.1 + * 2.6.2 * DO NOT MODIFY - This file has been generated using oazapfts. * See https://www.npmjs.com/package/oazapfts */ diff --git a/package.json b/package.json index 7e323425ea..a02b7efc8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "immich-monorepo", - "version": "2.6.1", + "version": "2.6.2", "description": "Monorepo for Immich", "private": true, "packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4826666b24..320815b631 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -67,7 +67,7 @@ importers: version: 24.12.0 '@vitest/coverage-v8': specifier: ^4.0.0 - version: 4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) byte-size: specifier: ^9.0.0 version: 9.0.1 @@ -108,17 +108,14 @@ importers: specifier: ^8.28.0 version: 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) vite: - specifier: ^7.0.0 - version: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vite-tsconfig-paths: - specifier: ^6.0.0 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^8.0.0 + version: 8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitest: specifier: ^4.0.0 - version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitest-fetch-mock: specifier: ^0.4.0 - version: 0.4.5(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 0.4.5(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) yaml: specifier: ^2.3.1 version: 2.8.2 @@ -287,10 +284,10 @@ importers: version: 5.2.1(encoding@0.1.13) vite-tsconfig-paths: specifier: ^6.1.1 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 6.1.1(typescript@5.9.3)(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) vitest: specifier: ^4.0.0 - version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) e2e-auth-server: devDependencies: @@ -592,7 +589,7 @@ importers: version: 10.0.1(eslint@10.0.2(jiti@2.6.1)) '@nestjs/cli': specifier: ^11.0.2 - version: 11.0.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(@types/node@24.12.0) + version: 11.0.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(@types/node@24.12.0)(esbuild@0.27.3) '@nestjs/schematics': specifier: ^11.0.0 version: 11.0.9(chokidar@4.0.3)(typescript@5.9.3) @@ -676,7 +673,7 @@ importers: version: 13.15.10 '@vitest/coverage-v8': specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) eslint: specifier: ^10.0.0 version: 10.0.2(jiti@2.6.1) @@ -730,10 +727,10 @@ importers: version: 1.5.9(@swc/core@1.15.18(@swc/helpers@0.5.17))(rollup@4.55.1) vite-tsconfig-paths: specifier: ^6.0.0 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 6.1.1(typescript@5.9.3)(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) web: dependencies: @@ -748,7 +745,7 @@ importers: version: link:../open-api/typescript-sdk '@immich/ui': specifier: ^0.65.3 - version: 0.65.3(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7) + version: 0.65.3(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13) '@mapbox/mapbox-gl-rtl-text': specifier: 0.3.0 version: 0.3.0 @@ -781,7 +778,7 @@ importers: version: 0.42.0 '@zoom-image/svelte': specifier: ^0.3.0 - version: 0.3.9(svelte@5.53.7) + version: 0.3.9(svelte@5.53.13) dom-to-image: specifier: ^2.6.0 version: 2.6.0 @@ -832,16 +829,16 @@ importers: version: 5.2.2 svelte-i18n: specifier: ^4.0.1 - version: 4.0.1(svelte@5.53.7) + version: 4.0.1(svelte@5.53.13) svelte-jsoneditor: specifier: ^3.10.0 - version: 3.11.0(svelte@5.53.7) + version: 3.11.0(svelte@5.53.13) svelte-maplibre: specifier: ^1.2.5 - version: 1.2.6(svelte@5.53.7) + version: 1.2.6(svelte@5.53.13) svelte-persisted-store: specifier: ^0.12.0 - version: 0.12.0(svelte@5.53.7) + version: 0.12.0(svelte@5.53.13) tabbable: specifier: ^6.2.0 version: 6.4.0 @@ -850,7 +847,7 @@ importers: version: 3.5.0 tailwind-variants: specifier: ^3.2.2 - version: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.1) + version: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2) thumbhash: specifier: ^0.1.1 version: 0.1.1 @@ -875,25 +872,25 @@ importers: version: 3.1.2 '@sveltejs/adapter-static': specifier: ^3.0.8 - version: 3.0.10(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))) + version: 3.0.10(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))) '@sveltejs/enhanced-img': - specifier: ^0.10.0 - version: 0.10.3(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rollup@4.55.1)(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^0.10.4 + version: 0.10.4(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rollup@4.55.1)(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@sveltejs/kit': specifier: ^2.27.1 - version: 2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@sveltejs/vite-plugin-svelte': - specifier: 6.2.4 - version: 6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + specifier: 7.0.0 + version: 7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@tailwindcss/vite': - specifier: ^4.1.7 - version: 4.2.1(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^4.2.2 + version: 4.2.2(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@testing-library/jest-dom': specifier: ^6.4.2 version: 6.9.1 '@testing-library/svelte': specifier: ^5.2.8 - version: 5.3.1(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 5.3.1(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@testing-library/user-event': specifier: ^14.5.2 version: 14.6.1(@testing-library/dom@10.4.1) @@ -917,7 +914,7 @@ importers: version: 1.5.6 '@vitest/coverage-v8': specifier: ^4.0.0 - version: 4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + version: 4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) dotenv: specifier: ^17.0.0 version: 17.3.1 @@ -932,7 +929,7 @@ importers: version: 6.2.1(eslint@10.0.2(jiti@2.6.1)) eslint-plugin-svelte: specifier: ^3.12.4 - version: 3.15.0(eslint@10.0.2(jiti@2.6.1))(svelte@5.53.7) + version: 3.15.0(eslint@10.0.2(jiti@2.6.1))(svelte@5.53.13) eslint-plugin-unicorn: specifier: ^63.0.0 version: 63.0.0(eslint@10.0.2(jiti@2.6.1)) @@ -953,22 +950,22 @@ importers: version: 4.2.0(prettier@3.8.1) prettier-plugin-svelte: specifier: ^3.3.3 - version: 3.5.1(prettier@3.8.1)(svelte@5.53.7) + version: 3.5.1(prettier@3.8.1)(svelte@5.53.13) rollup-plugin-visualizer: specifier: ^6.0.0 - version: 6.0.11(rollup@4.55.1) + version: 6.0.11(rolldown@1.0.0-rc.9)(rollup@4.55.1) svelte: - specifier: 5.53.7 - version: 5.53.7 + specifier: 5.53.13 + version: 5.53.13 svelte-check: specifier: ^4.1.5 - version: 4.4.4(picomatch@4.0.3)(svelte@5.53.7)(typescript@5.9.3) + version: 4.4.4(picomatch@4.0.3)(svelte@5.53.13)(typescript@5.9.3) svelte-eslint-parser: specifier: ^1.3.3 - version: 1.6.0(svelte@5.53.7) + version: 1.6.0(svelte@5.53.13) tailwindcss: - specifier: ^4.1.7 - version: 4.2.1 + specifier: ^4.2.2 + version: 4.2.2 typescript: specifier: ^5.8.3 version: 5.9.3 @@ -976,11 +973,11 @@ importers: specifier: ^8.45.0 version: 8.56.1(eslint@10.0.2(jiti@2.6.1))(typescript@5.9.3) vite: - specifier: ^7.1.2 - version: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + specifier: ^8.0.0 + version: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vitest: specifier: ^4.0.0 - version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + version: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) packages: @@ -2264,9 +2261,15 @@ packages: resolution: {integrity: sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==} engines: {node: '>=20.0'} + '@emnapi/core@1.9.0': + resolution: {integrity: sha512-0DQ98G9ZQZOxfUcQn1waV2yS8aWdZ6kJMbYCJB3oUBecjWYO1fqJ+a1DRfPF3O5JEkwqwP1A9QEN/9mYm2Yd0w==} + '@emnapi/runtime@1.7.1': resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + '@emnapi/wasi-threads@1.2.0': + resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} + '@esbuild/aix-ppc64@0.19.12': resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} engines: {node: '>=12'} @@ -3428,6 +3431,9 @@ packages: '@namnode/store@0.1.0': resolution: {integrity: sha512-4NGTldxKcmY0UuZ7OEkvCjs8ZEoeYB6M2UwMu74pdLiFMKxXbj9HdNk1Qn213bxX1O7bY5h+PLh5DZsTURZkYA==} + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + '@nestjs/bull-shared@11.0.4': resolution: {integrity: sha512-VBJcDHSAzxQnpcDfA0kt9MTGUD1XZzfByV70su0W0eDCQ9aqIEBlzWRW21tv9FG9dIut22ysgDidshdjlnczLw==} peerDependencies: @@ -3804,6 +3810,13 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 + '@oxc-project/runtime@0.115.0': + resolution: {integrity: sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@oxc-project/types@0.115.0': + resolution: {integrity: sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==} + '@paralleldrive/cuid2@2.3.1': resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} @@ -4118,6 +4131,104 @@ packages: '@codemirror/state': ^6.0.0 '@codemirror/view': ^6.0.0 + '@rolldown/binding-android-arm64@1.0.0-rc.9': + resolution: {integrity: sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.9': + resolution: {integrity: sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.9': + resolution: {integrity: sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.9': + resolution: {integrity: sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9': + resolution: {integrity: sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.9': + resolution: {integrity: sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.9': + resolution: {integrity: sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.9': + resolution: {integrity: sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.9': + resolution: {integrity: sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9': + resolution: {integrity: sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.9': + resolution: {integrity: sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-rc.9': + resolution: {integrity: sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==} + '@rollup/pluginutils@5.3.0': resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} @@ -4325,10 +4436,10 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/enhanced-img@0.10.3': - resolution: {integrity: sha512-/6tYiqVmVgWcntSD/TChENE74yN8Gde9JEN8gyGKtm2ytlsUzGiS8loPPiO7Lh4V/rSsOFbvLdXPdiNVztMArA==} + '@sveltejs/enhanced-img@0.10.4': + resolution: {integrity: sha512-Am5nmAKUo7Nboqq7Dhtfn7dcXA087d7gIz6Vecn1opB41aJ680+0q9U9KvEcMgduOyeiwckTIOQOx4Mmq9GcvA==} peerDependencies: - '@sveltejs/vite-plugin-svelte': ^6.0.0 + '@sveltejs/vite-plugin-svelte': ^6.0.0 || ^7.0.0 svelte: ^5.0.0 vite: ^6.3.0 || >=7.0.0 @@ -4348,20 +4459,12 @@ packages: typescript: optional: true - '@sveltejs/vite-plugin-svelte-inspector@5.0.1': - resolution: {integrity: sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==} + '@sveltejs/vite-plugin-svelte@7.0.0': + resolution: {integrity: sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g==} engines: {node: ^20.19 || ^22.12 || >=24} peerDependencies: - '@sveltejs/vite-plugin-svelte': ^6.0.0-next.0 - svelte: ^5.0.0 - vite: ^6.3.0 || ^7.0.0 - - '@sveltejs/vite-plugin-svelte@6.2.4': - resolution: {integrity: sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==} - engines: {node: ^20.19 || ^22.12 || >=24} - peerDependencies: - svelte: ^5.0.0 - vite: ^6.3.0 || ^7.0.0 + svelte: ^5.46.4 + vite: ^8.0.0-beta.7 || ^8.0.0 '@svgr/babel-plugin-add-jsx-attribute@8.0.0': resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} @@ -4527,69 +4630,69 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} - '@tailwindcss/node@4.2.1': - resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} + '@tailwindcss/node@4.2.2': + resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} - '@tailwindcss/oxide-android-arm64@4.2.1': - resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} + '@tailwindcss/oxide-android-arm64@4.2.2': + resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} engines: {node: '>= 20'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.2.1': - resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} + '@tailwindcss/oxide-darwin-arm64@4.2.2': + resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} engines: {node: '>= 20'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.2.1': - resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} + '@tailwindcss/oxide-darwin-x64@4.2.2': + resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} engines: {node: '>= 20'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.2.1': - resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} + '@tailwindcss/oxide-freebsd-x64@4.2.2': + resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} engines: {node: '>= 20'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': - resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': + resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} engines: {node: '>= 20'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': - resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': + resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-arm64-musl@4.2.1': - resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': + resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] libc: [musl] - '@tailwindcss/oxide-linux-x64-gnu@4.2.1': - resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': + resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [glibc] - '@tailwindcss/oxide-linux-x64-musl@4.2.1': - resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} + '@tailwindcss/oxide-linux-x64-musl@4.2.2': + resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} engines: {node: '>= 20'} cpu: [x64] os: [linux] libc: [musl] - '@tailwindcss/oxide-wasm32-wasi@4.2.1': - resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} + '@tailwindcss/oxide-wasm32-wasi@4.2.2': + resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -4600,26 +4703,26 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': - resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': + resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} engines: {node: '>= 20'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.2.1': - resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': + resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} engines: {node: '>= 20'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.2.1': - resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} + '@tailwindcss/oxide@4.2.2': + resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} engines: {node: '>= 20'} - '@tailwindcss/vite@4.2.1': - resolution: {integrity: sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==} + '@tailwindcss/vite@4.2.2': + resolution: {integrity: sha512-mEiF5HO1QqCLXoNEfXVA1Tzo+cYsrqV7w9Juj2wdUFyW07JRenqMG225MvPwr3ZD9N1bFQj46X7r33iHxLUW0w==} peerDependencies: - vite: ^5.2.0 || ^6 || ^7 + vite: ^5.2.0 || ^6 || ^7 || ^8 '@testing-library/dom@10.4.1': resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} @@ -4674,6 +4777,9 @@ packages: '@turf/invariant@7.3.2': resolution: {integrity: sha512-brGmL1EFhZH/YNXhq6S+8sPWBEnmvEyxMWJO8bUNOFZyWHYiRTwxQHZM+An1blkbQ77PiEzsdNAspZqE1j7YKA==} + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/accepts@1.3.7': resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} @@ -6752,6 +6858,9 @@ packages: devalue@5.6.3: resolution: {integrity: sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==} + devalue@5.6.4: + resolution: {integrity: sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -8434,78 +8543,78 @@ packages: libphonenumber-js@1.12.38: resolution: {integrity: sha512-vwzxmasAy9hZigxtqTbFEwp8ZdZ975TiqVDwj5bKx5sR+zi5ucUQy9mbVTkKM9GzqdLdxux/hTw2nmN5J7POMA==} - lightningcss-android-arm64@1.31.1: - resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] - lightningcss-darwin-arm64@1.31.1: - resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] - lightningcss-darwin-x64@1.31.1: - resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] - lightningcss-freebsd-x64@1.31.1: - resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] - lightningcss-linux-arm-gnueabihf@1.31.1: - resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] - lightningcss-linux-arm64-gnu@1.31.1: - resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [glibc] - lightningcss-linux-arm64-musl@1.31.1: - resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] libc: [musl] - lightningcss-linux-x64-gnu@1.31.1: - resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [glibc] - lightningcss-linux-x64-musl@1.31.1: - resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] libc: [musl] - lightningcss-win32-arm64-msvc@1.31.1: - resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] - lightningcss-win32-x64-msvc@1.31.1: - resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] - lightningcss@1.31.1: - resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} engines: {node: '>= 12.0.0'} lilconfig@2.1.0: @@ -10617,6 +10726,11 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + rolldown@1.0.0-rc.9: + resolution: {integrity: sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup-plugin-visualizer@6.0.11: resolution: {integrity: sha512-TBwVHVY7buHjIKVLqr9scTVFwqZqMXINcCphPwIWKPDCOBIa+jCQfafvbjRJDZgXdq/A996Dy6yGJ/+/NtAXDQ==} engines: {node: '>=18'} @@ -11218,8 +11332,8 @@ packages: peerDependencies: svelte: ^5.30.2 - svelte@5.53.7: - resolution: {integrity: sha512-uxck1KI7JWtlfP3H6HOWi/94soAl23jsGJkBzN2BAWcQng0+lTrRNhxActFqORgnO9BHVd1hKJhG+ljRuIUWfQ==} + svelte@5.53.13: + resolution: {integrity: sha512-9P6I/jGcQMzAMb76Uyd6L6RELAC7qt53GOSBLCke9lubh9iJjmjCo+EffRH4gOPnTB/x4RR2Tmt6s3o9ywQO3g==} engines: {node: '>=18'} svg-parser@2.0.4: @@ -11293,8 +11407,8 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tailwindcss@4.2.1: - resolution: {integrity: sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==} + tailwindcss@4.2.2: + resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} tapable@2.3.0: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} @@ -11877,10 +11991,53 @@ packages: yaml: optional: true - vitefu@1.1.1: - resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} + vite@8.0.0: + resolution: {integrity: sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.0.0-alpha.31 + esbuild: ^0.27.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.1.2: + resolution: {integrity: sha512-zpKATdUbzbsycPFBN71nS2uzBUQiVnFoOrr2rvqv34S1lcAgMKKkjWleLGeiJlZ8lwCXvtWaRn7R3ZC16SYRuw==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-beta.0 peerDependenciesMeta: vite: optional: true @@ -14441,11 +14598,22 @@ snapshots: - uglify-js - webpack-cli + '@emnapi/core@1.9.0': + dependencies: + '@emnapi/wasi-threads': 1.2.0 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.7.1': dependencies: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.0': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.19.12': optional: true @@ -14948,26 +15116,26 @@ snapshots: pg-connection-string: 2.12.0 postgres: 3.4.8 - '@immich/svelte-markdown-preprocess@0.2.1(svelte@5.53.7)': + '@immich/svelte-markdown-preprocess@0.2.1(svelte@5.53.13)': dependencies: front-matter: 4.0.2 marked: 17.0.3 node-emoji: 2.2.0 - svelte: 5.53.7 + svelte: 5.53.13 - '@immich/ui@0.65.3(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)': + '@immich/ui@0.65.3(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)': dependencies: - '@immich/svelte-markdown-preprocess': 0.2.1(svelte@5.53.7) + '@immich/svelte-markdown-preprocess': 0.2.1(svelte@5.53.13) '@internationalized/date': 3.10.0 '@mdi/js': 7.4.47 - bits-ui: 2.16.0(@internationalized/date@3.10.0)(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7) + bits-ui: 2.16.0(@internationalized/date@3.10.0)(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13) luxon: 3.7.2 simple-icons: 16.9.0 - svelte: 5.53.7 + svelte: 5.53.13 svelte-highlight: 7.9.0 tailwind-merge: 3.5.0 - tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.1) - tailwindcss: 4.2.1 + tailwind-variants: 3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2) + tailwindcss: 4.2.2 transitivePeerDependencies: - '@sveltejs/kit' @@ -15424,6 +15592,13 @@ snapshots: '@namnode/store@0.1.0': {} + '@napi-rs/wasm-runtime@1.1.1': + dependencies: + '@emnapi/core': 1.9.0 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + '@nestjs/bull-shared@11.0.4(@nestjs/common@11.1.16(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.16)': dependencies: '@nestjs/common': 11.1.16(class-transformer@0.5.1)(class-validator@0.15.1)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -15438,7 +15613,7 @@ snapshots: bullmq: 5.70.4 tslib: 2.8.1 - '@nestjs/cli@11.0.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(@types/node@24.12.0)': + '@nestjs/cli@11.0.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(@types/node@24.12.0)(esbuild@0.27.3)': dependencies: '@angular-devkit/core': 19.2.19(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.19(chokidar@4.0.3) @@ -15449,14 +15624,14 @@ snapshots: chokidar: 4.0.3 cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))) + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3)) glob: 13.0.0 node-emoji: 1.11.0 ora: 5.4.1 tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.2.0 typescript: 5.9.3 - webpack: 5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17)) + webpack: 5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3) webpack-node-externals: 3.0.0 optionalDependencies: '@swc/core': 1.15.18(@swc/helpers@0.5.17) @@ -15902,6 +16077,10 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.6.0(@opentelemetry/api@1.9.0) + '@oxc-project/runtime@0.115.0': {} + + '@oxc-project/types@0.115.0': {} + '@paralleldrive/cuid2@2.3.1': dependencies: '@noble/hashes': 1.8.0 @@ -16161,6 +16340,55 @@ snapshots: '@codemirror/state': 6.5.3 '@codemirror/view': 6.39.8 + '@rolldown/binding-android-arm64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.9': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.9': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.9': + optional: true + + '@rolldown/pluginutils@1.0.0-rc.9': {} + '@rollup/pluginutils@5.3.0(rollup@4.55.1)': dependencies: '@types/estree': 1.0.8 @@ -16300,29 +16528,29 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))': + '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))': dependencies: - '@sveltejs/kit': 2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@sveltejs/kit': 2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - '@sveltejs/enhanced-img@0.10.3(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rollup@4.55.1)(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@sveltejs/enhanced-img@0.10.4(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(rollup@4.55.1)(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@sveltejs/vite-plugin-svelte': 7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) magic-string: 0.30.21 sharp: 0.34.5 - svelte: 5.53.7 - svelte-parse-markup: 0.1.5(svelte@5.53.7) - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + svelte: 5.53.13 + svelte-parse-markup: 0.1.5(svelte@5.53.13) + vite: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) vite-imagetools: 9.0.3(rollup@4.55.1) zimmerframe: 1.1.4 transitivePeerDependencies: - rollup - supports-color - '@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.9(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@sveltejs/vite-plugin-svelte': 7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -16333,32 +16561,20 @@ snapshots: mrmime: 2.0.1 set-cookie-parser: 3.0.1 sirv: 3.0.2 - svelte: 5.53.7 - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + svelte: 5.53.13 + vite: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) optionalDependencies: '@opentelemetry/api': 1.9.0 typescript: 5.9.3 - '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - debug: 4.4.3 - svelte: 5.53.7 - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - transitivePeerDependencies: - - supports-color - - '@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': - dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) deepmerge: 4.3.1 magic-string: 0.30.21 obug: 2.1.1 - svelte: 5.53.7 - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vitefu: 1.1.1(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) - transitivePeerDependencies: - - supports-color + svelte: 5.53.13 + vite: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitefu: 1.1.2(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.28.5)': dependencies: @@ -16514,73 +16730,73 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tailwindcss/node@4.2.1': + '@tailwindcss/node@4.2.2': dependencies: '@jridgewell/remapping': 2.3.5 enhanced-resolve: 5.20.0 jiti: 2.6.1 - lightningcss: 1.31.1 + lightningcss: 1.32.0 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.2.1 + tailwindcss: 4.2.2 - '@tailwindcss/oxide-android-arm64@4.2.1': + '@tailwindcss/oxide-android-arm64@4.2.2': optional: true - '@tailwindcss/oxide-darwin-arm64@4.2.1': + '@tailwindcss/oxide-darwin-arm64@4.2.2': optional: true - '@tailwindcss/oxide-darwin-x64@4.2.1': + '@tailwindcss/oxide-darwin-x64@4.2.2': optional: true - '@tailwindcss/oxide-freebsd-x64@4.2.1': + '@tailwindcss/oxide-freebsd-x64@4.2.2': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + '@tailwindcss/oxide-linux-arm64-musl@4.2.2': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.2.1': + '@tailwindcss/oxide-linux-x64-gnu@4.2.2': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.2.1': + '@tailwindcss/oxide-linux-x64-musl@4.2.2': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.2.1': + '@tailwindcss/oxide-wasm32-wasi@4.2.2': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + '@tailwindcss/oxide-win32-x64-msvc@4.2.2': optional: true - '@tailwindcss/oxide@4.2.1': + '@tailwindcss/oxide@4.2.2': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.1 - '@tailwindcss/oxide-darwin-arm64': 4.2.1 - '@tailwindcss/oxide-darwin-x64': 4.2.1 - '@tailwindcss/oxide-freebsd-x64': 4.2.1 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.1 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.1 - '@tailwindcss/oxide-linux-x64-musl': 4.2.1 - '@tailwindcss/oxide-wasm32-wasi': 4.2.1 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 + '@tailwindcss/oxide-android-arm64': 4.2.2 + '@tailwindcss/oxide-darwin-arm64': 4.2.2 + '@tailwindcss/oxide-darwin-x64': 4.2.2 + '@tailwindcss/oxide-freebsd-x64': 4.2.2 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 + '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 + '@tailwindcss/oxide-linux-x64-musl': 4.2.2 + '@tailwindcss/oxide-wasm32-wasi': 4.2.2 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - '@tailwindcss/vite@4.2.1(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@tailwindcss/vite@4.2.2(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: - '@tailwindcss/node': 4.2.1 - '@tailwindcss/oxide': 4.2.1 - tailwindcss: 4.2.1 - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + '@tailwindcss/node': 4.2.2 + '@tailwindcss/oxide': 4.2.2 + tailwindcss: 4.2.2 + vite: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@testing-library/dom@10.4.1': dependencies: @@ -16602,18 +16818,18 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/svelte-core@1.0.0(svelte@5.53.7)': + '@testing-library/svelte-core@1.0.0(svelte@5.53.13)': dependencies: - svelte: 5.53.7 + svelte: 5.53.13 - '@testing-library/svelte@5.3.1(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@testing-library/svelte@5.3.1(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@testing-library/dom': 10.4.1 - '@testing-library/svelte-core': 1.0.0(svelte@5.53.7) - svelte: 5.53.7 + '@testing-library/svelte-core': 1.0.0(svelte@5.53.13) + svelte: 5.53.13 optionalDependencies: - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': dependencies: @@ -16649,6 +16865,11 @@ snapshots: '@types/geojson': 7946.0.16 tslib: 2.8.1 + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + '@types/accepts@1.3.7': dependencies: '@types/node': 24.12.0 @@ -17307,7 +17528,7 @@ snapshots: '@vercel/oidc@3.0.5': {} - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -17322,11 +17543,11 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.2 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color - '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.18 @@ -17338,9 +17559,9 @@ snapshots: obug: 2.1.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/coverage-v8@4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.0.18 @@ -17352,7 +17573,7 @@ snapshots: obug: 2.1.1 std-env: 3.10.0 tinyrainbow: 3.0.3 - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/expect@3.2.4': dependencies: @@ -17371,29 +17592,29 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.0.3 - '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.18 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -17527,10 +17748,10 @@ snapshots: dependencies: '@namnode/store': 0.1.0 - '@zoom-image/svelte@0.3.9(svelte@5.53.7)': + '@zoom-image/svelte@0.3.9(svelte@5.53.13)': dependencies: '@zoom-image/core': 0.42.0 - svelte: 5.53.7 + svelte: 5.53.13 abbrev@1.1.1: {} @@ -17894,15 +18115,15 @@ snapshots: binary-extensions@2.3.0: {} - bits-ui@2.16.0(@internationalized/date@3.10.0)(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7): + bits-ui@2.16.0(@internationalized/date@3.10.0)(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13): dependencies: '@floating-ui/core': 1.7.3 '@floating-ui/dom': 1.7.4 '@internationalized/date': 3.10.0 esm-env: 1.2.2 - runed: 0.35.1(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7) - svelte: 5.53.7 - svelte-toolbelt: 0.10.6(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7) + runed: 0.35.1(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13) + svelte: 5.53.13 + svelte-toolbelt: 0.10.6(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13) tabbable: 6.4.0 transitivePeerDependencies: - '@sveltejs/kit' @@ -18995,6 +19216,8 @@ snapshots: devalue@5.6.3: {} + devalue@5.6.4: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -19403,7 +19626,7 @@ snapshots: '@types/eslint': 9.6.1 eslint-config-prettier: 10.1.8(eslint@10.0.2(jiti@2.6.1)) - eslint-plugin-svelte@3.15.0(eslint@10.0.2(jiti@2.6.1))(svelte@5.53.7): + eslint-plugin-svelte@3.15.0(eslint@10.0.2(jiti@2.6.1))(svelte@5.53.13): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.0.2(jiti@2.6.1)) '@jridgewell/sourcemap-codec': 1.5.5 @@ -19415,9 +19638,9 @@ snapshots: postcss-load-config: 3.1.4(postcss@8.5.8) postcss-safe-parser: 7.0.1(postcss@8.5.8) semver: 7.7.4 - svelte-eslint-parser: 1.6.0(svelte@5.53.7) + svelte-eslint-parser: 1.6.0(svelte@5.53.13) optionalDependencies: - svelte: 5.53.7 + svelte: 5.53.13 transitivePeerDependencies: - ts-node @@ -19882,7 +20105,7 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3)): dependencies: '@babel/code-frame': 7.29.0 chalk: 4.1.2 @@ -19897,7 +20120,7 @@ snapshots: semver: 7.7.4 tapable: 2.3.0 typescript: 5.9.3 - webpack: 5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17)) + webpack: 5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3) form-data-encoder@2.1.4: {} @@ -21102,54 +21325,54 @@ snapshots: libphonenumber-js@1.12.38: {} - lightningcss-android-arm64@1.31.1: + lightningcss-android-arm64@1.32.0: optional: true - lightningcss-darwin-arm64@1.31.1: + lightningcss-darwin-arm64@1.32.0: optional: true - lightningcss-darwin-x64@1.31.1: + lightningcss-darwin-x64@1.32.0: optional: true - lightningcss-freebsd-x64@1.31.1: + lightningcss-freebsd-x64@1.32.0: optional: true - lightningcss-linux-arm-gnueabihf@1.31.1: + lightningcss-linux-arm-gnueabihf@1.32.0: optional: true - lightningcss-linux-arm64-gnu@1.31.1: + lightningcss-linux-arm64-gnu@1.32.0: optional: true - lightningcss-linux-arm64-musl@1.31.1: + lightningcss-linux-arm64-musl@1.32.0: optional: true - lightningcss-linux-x64-gnu@1.31.1: + lightningcss-linux-x64-gnu@1.32.0: optional: true - lightningcss-linux-x64-musl@1.31.1: + lightningcss-linux-x64-musl@1.32.0: optional: true - lightningcss-win32-arm64-msvc@1.31.1: + lightningcss-win32-arm64-msvc@1.32.0: optional: true - lightningcss-win32-x64-msvc@1.31.1: + lightningcss-win32-x64-msvc@1.32.0: optional: true - lightningcss@1.31.1: + lightningcss@1.32.0: dependencies: detect-libc: 2.1.2 optionalDependencies: - lightningcss-android-arm64: 1.31.1 - lightningcss-darwin-arm64: 1.31.1 - lightningcss-darwin-x64: 1.31.1 - lightningcss-freebsd-x64: 1.31.1 - lightningcss-linux-arm-gnueabihf: 1.31.1 - lightningcss-linux-arm64-gnu: 1.31.1 - lightningcss-linux-arm64-musl: 1.31.1 - lightningcss-linux-x64-gnu: 1.31.1 - lightningcss-linux-x64-musl: 1.31.1 - lightningcss-win32-arm64-msvc: 1.31.1 - lightningcss-win32-x64-msvc: 1.31.1 + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 lilconfig@2.1.0: {} @@ -23155,10 +23378,10 @@ snapshots: dependencies: prettier: 3.8.1 - prettier-plugin-svelte@3.5.1(prettier@3.8.1)(svelte@5.53.7): + prettier-plugin-svelte@3.5.1(prettier@3.8.1)(svelte@5.53.13): dependencies: prettier: 3.8.1 - svelte: 5.53.7 + svelte: 5.53.13 prettier@3.8.1: {} @@ -23688,13 +23911,35 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@6.0.11(rollup@4.55.1): + rolldown@1.0.0-rc.9: + dependencies: + '@oxc-project/types': 0.115.0 + '@rolldown/pluginutils': 1.0.0-rc.9 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.9 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.9 + '@rolldown/binding-darwin-x64': 1.0.0-rc.9 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.9 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.9 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.9 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.9 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.9 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.9 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.9 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.9 + + rollup-plugin-visualizer@6.0.11(rolldown@1.0.0-rc.9)(rollup@4.55.1): dependencies: open: 8.4.2 picomatch: 4.0.3 source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: + rolldown: 1.0.0-rc.9 rollup: 4.55.1 rollup@4.55.1: @@ -23763,14 +24008,14 @@ snapshots: dependencies: queue-microtask: 1.2.3 - runed@0.35.1(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7): + runed@0.35.1(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13): dependencies: dequal: 2.0.3 esm-env: 1.2.2 lz-string: 1.5.0 - svelte: 5.53.7 + svelte: 5.53.13 optionalDependencies: - '@sveltejs/kit': 2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@sveltejs/kit': 2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) rw@1.3.3: {} @@ -24394,23 +24639,23 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-awesome@3.3.5(svelte@5.53.7): + svelte-awesome@3.3.5(svelte@5.53.13): dependencies: - svelte: 5.53.7 + svelte: 5.53.13 - svelte-check@4.4.4(picomatch@4.0.3)(svelte@5.53.7)(typescript@5.9.3): + svelte-check@4.4.4(picomatch@4.0.3)(svelte@5.53.13)(typescript@5.9.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.3) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.53.7 + svelte: 5.53.13 typescript: 5.9.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.6.0(svelte@5.53.7): + svelte-eslint-parser@1.6.0(svelte@5.53.13): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -24420,7 +24665,7 @@ snapshots: postcss-selector-parser: 7.1.1 semver: 7.7.4 optionalDependencies: - svelte: 5.53.7 + svelte: 5.53.13 svelte-floating-ui@1.5.8: dependencies: @@ -24433,7 +24678,7 @@ snapshots: dependencies: highlight.js: 11.11.1 - svelte-i18n@4.0.1(svelte@5.53.7): + svelte-i18n@4.0.1(svelte@5.53.13): dependencies: cli-color: 2.0.4 deepmerge: 4.3.1 @@ -24441,10 +24686,10 @@ snapshots: estree-walker: 2.0.2 intl-messageformat: 10.7.18 sade: 1.8.1 - svelte: 5.53.7 + svelte: 5.53.13 tiny-glob: 0.2.9 - svelte-jsoneditor@3.11.0(svelte@5.53.7): + svelte-jsoneditor@3.11.0(svelte@5.53.13): dependencies: '@codemirror/autocomplete': 6.20.0 '@codemirror/commands': 6.10.1 @@ -24471,42 +24716,42 @@ snapshots: memoize-one: 6.0.0 natural-compare-lite: 1.4.0 sass: 1.97.1 - svelte: 5.53.7 - svelte-awesome: 3.3.5(svelte@5.53.7) + svelte: 5.53.13 + svelte-awesome: 3.3.5(svelte@5.53.13) svelte-select: 5.8.3 vanilla-picker: 2.12.3 - svelte-maplibre@1.2.6(svelte@5.53.7): + svelte-maplibre@1.2.6(svelte@5.53.13): dependencies: d3-geo: 3.1.1 dequal: 2.0.3 just-compare: 2.3.0 maplibre-gl: 5.19.0 pmtiles: 3.2.1 - svelte: 5.53.7 + svelte: 5.53.13 - svelte-parse-markup@0.1.5(svelte@5.53.7): + svelte-parse-markup@0.1.5(svelte@5.53.13): dependencies: - svelte: 5.53.7 + svelte: 5.53.13 - svelte-persisted-store@0.12.0(svelte@5.53.7): + svelte-persisted-store@0.12.0(svelte@5.53.13): dependencies: - svelte: 5.53.7 + svelte: 5.53.13 svelte-select@5.8.3: dependencies: svelte-floating-ui: 1.5.8 - svelte-toolbelt@0.10.6(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7): + svelte-toolbelt@0.10.6(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13): dependencies: clsx: 2.1.1 - runed: 0.35.1(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.53.7)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7)(typescript@5.9.3)(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.7) + runed: 0.35.1(@sveltejs/kit@2.53.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@7.0.0(svelte@5.53.13)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13)(typescript@5.9.3)(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)))(svelte@5.53.13) style-to-object: 1.0.14 - svelte: 5.53.7 + svelte: 5.53.13 transitivePeerDependencies: - '@sveltejs/kit' - svelte@5.53.7: + svelte@5.53.13: dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -24517,7 +24762,7 @@ snapshots: aria-query: 5.3.1 axobject-query: 4.1.0 clsx: 2.1.1 - devalue: 5.6.3 + devalue: 5.6.4 esm-env: 1.2.2 esrap: 2.2.3 is-reference: 3.0.3 @@ -24562,9 +24807,9 @@ snapshots: tailwind-merge@3.5.0: {} - tailwind-variants@3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.1): + tailwind-variants@3.2.2(tailwind-merge@3.5.0)(tailwindcss@4.2.2): dependencies: - tailwindcss: 4.2.1 + tailwindcss: 4.2.2 optionalDependencies: tailwind-merge: 3.5.0 @@ -24610,7 +24855,7 @@ snapshots: - tsx - yaml - tailwindcss@4.2.1: {} + tailwindcss@4.2.2: {} tapable@2.3.0: {} @@ -24675,16 +24920,17 @@ snapshots: - react-native-b4a optional: true - terser-webpack-plugin@5.3.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))): + terser-webpack-plugin@5.3.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3)(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3)): dependencies: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 serialize-javascript: 6.0.2 terser: 5.44.1 - webpack: 5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17)) + webpack: 5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3) optionalDependencies: '@swc/core': 1.15.18(@swc/helpers@0.5.17) + esbuild: 0.27.3 terser-webpack-plugin@5.3.16(webpack@5.104.1): dependencies: @@ -25199,13 +25445,13 @@ snapshots: - rollup - supports-color - vite-node@3.2.4(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite-node@3.2.4(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -25220,17 +25466,17 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color - typescript - vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) @@ -25242,13 +25488,13 @@ snapshots: '@types/node': 24.12.0 fsevents: 2.3.3 jiti: 2.6.1 - lightningcss: 1.31.1 + lightningcss: 1.32.0 sass: 1.97.1 terser: 5.44.1 tsx: 4.21.0 yaml: 2.8.2 - vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.27.3 fdir: 6.5.0(picomatch@4.0.3) @@ -25260,25 +25506,61 @@ snapshots: '@types/node': 25.4.0 fsevents: 2.3.3 jiti: 2.6.1 - lightningcss: 1.31.1 + lightningcss: 1.32.0 sass: 1.97.1 terser: 5.44.1 tsx: 4.21.0 yaml: 2.8.2 - vitefu@1.1.1(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): - optionalDependencies: - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - - vitest-fetch-mock@0.4.5(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + vite@8.0.0(@types/node@24.12.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: - vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + '@oxc-project/runtime': 0.115.0 + lightningcss: 1.32.0 + picomatch: 4.0.3 + postcss: 8.5.8 + rolldown: 1.0.0-rc.9 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.12.0 + esbuild: 0.27.3 + fsevents: 2.3.3 + jiti: 2.6.1 + sass: 1.97.1 + terser: 5.44.1 + tsx: 4.21.0 + yaml: 2.8.2 - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + '@oxc-project/runtime': 0.115.0 + lightningcss: 1.32.0 + picomatch: 4.0.3 + postcss: 8.5.8 + rolldown: 1.0.0-rc.9 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.4.0 + esbuild: 0.27.3 + fsevents: 2.3.3 + jiti: 2.6.1 + sass: 1.97.1 + terser: 5.44.1 + tsx: 4.21.0 + yaml: 2.8.2 + + vitefu@1.1.2(vite@8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + optionalDependencies: + vite: 8.0.0(@types/node@25.4.0)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + + vitest-fetch-mock@0.4.5(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)): + dependencies: + vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -25296,8 +25578,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 @@ -25318,10 +25600,10 @@ snapshots: - tsx - yaml - vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -25338,7 +25620,7 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 @@ -25358,10 +25640,10 @@ snapshots: - tsx - yaml - vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.12.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -25378,7 +25660,7 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@24.12.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 @@ -25398,10 +25680,10 @@ snapshots: - tsx - yaml - vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): + vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@25.4.0)(happy-dom@20.8.3)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.18 - '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.18 '@vitest/runner': 4.0.18 '@vitest/snapshot': 4.0.18 @@ -25418,7 +25700,7 @@ snapshots: tinyexec: 1.0.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.31.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 @@ -25601,7 +25883,7 @@ snapshots: - esbuild - uglify-js - webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17)): + webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -25625,7 +25907,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))) + terser-webpack-plugin: 5.3.16(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3)(webpack@5.104.1(@swc/core@1.15.18(@swc/helpers@0.5.17))(esbuild@0.27.3)) watchpack: 2.5.1 webpack-sources: 3.3.3 transitivePeerDependencies: diff --git a/server/package.json b/server/package.json index 0af90c4ae5..554f2540d5 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "immich", - "version": "2.6.1", + "version": "2.6.2", "description": "", "author": "", "private": true, @@ -24,7 +24,7 @@ "typeorm": "typeorm", "migrations:debug": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} migrations generate --debug", "migrations:generate": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} migrations generate", - "migrations:create": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} migrations generate", + "migrations:create": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} migrations create", "migrations:run": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} migrations run", "migrations:revert": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} migrations revert", "schema:drop": "sql-tools -u ${DB_URL:-postgres://postgres:postgres@localhost:5432/immich} query 'DROP schema public cascade; CREATE schema public;'", diff --git a/server/src/database.ts b/server/src/database.ts index 3e3192c21a..eb558c6d28 100644 --- a/server/src/database.ts +++ b/server/src/database.ts @@ -169,6 +169,7 @@ export type AuthSharedLink = { id: string; expiresAt: Date | null; userId: string; + albumId: string | null; showExif: boolean; allowUpload: boolean; allowDownload: boolean; @@ -357,15 +358,6 @@ export const columns = { authUser: ['user.id', 'user.name', 'user.email', 'user.isAdmin', 'user.quotaUsageInBytes', 'user.quotaSizeInBytes'], authApiKey: ['api_key.id', 'api_key.permissions'], authSession: ['session.id', 'session.updatedAt', 'session.pinExpiresAt', 'session.appVersion'], - authSharedLink: [ - 'shared_link.id', - 'shared_link.userId', - 'shared_link.expiresAt', - 'shared_link.showExif', - 'shared_link.allowUpload', - 'shared_link.allowDownload', - 'shared_link.password', - ], user: userColumns, userWithPrefix: userWithPrefixColumns, userAdmin: [ diff --git a/server/src/queries/shared.link.repository.sql b/server/src/queries/shared.link.repository.sql index 2630e384fc..f002110735 100644 --- a/server/src/queries/shared.link.repository.sql +++ b/server/src/queries/shared.link.repository.sql @@ -173,6 +173,7 @@ order by select "shared_link"."id", "shared_link"."userId", + "shared_link"."albumId", "shared_link"."expiresAt", "shared_link"."showExif", "shared_link"."allowUpload", @@ -211,6 +212,7 @@ where select "shared_link"."id", "shared_link"."userId", + "shared_link"."albumId", "shared_link"."expiresAt", "shared_link"."showExif", "shared_link"."allowUpload", diff --git a/server/src/repositories/album.repository.ts b/server/src/repositories/album.repository.ts index 9a76b379ed..f74356c924 100644 --- a/server/src/repositories/album.repository.ts +++ b/server/src/repositories/album.repository.ts @@ -330,6 +330,7 @@ export class AlbumRepository { await db .insertInto('album_asset') .values(assetIds.map((assetId) => ({ albumId, assetId }))) + .onConflict((oc) => oc.doNothing()) .execute(); } diff --git a/server/src/repositories/shared-link.repository.ts b/server/src/repositories/shared-link.repository.ts index bc81e75c81..1ad5d7bd77 100644 --- a/server/src/repositories/shared-link.repository.ts +++ b/server/src/repositories/shared-link.repository.ts @@ -202,7 +202,14 @@ export class SharedLinkRepository { .leftJoin('album', 'album.id', 'shared_link.albumId') .where('album.deletedAt', 'is', null) .select((eb) => [ - ...columns.authSharedLink, + 'shared_link.id', + 'shared_link.userId', + 'shared_link.albumId', + 'shared_link.expiresAt', + 'shared_link.showExif', + 'shared_link.allowUpload', + 'shared_link.allowDownload', + 'shared_link.password', jsonObjectFrom( eb.selectFrom('user').select(columns.authUser).whereRef('user.id', '=', 'shared_link.userId'), ).as('user'), diff --git a/server/src/schema/migrations/1773956345315-DuplicateSharedLinkAssets.ts b/server/src/schema/migrations/1773956345315-DuplicateSharedLinkAssets.ts new file mode 100644 index 0000000000..d3a83d53dc --- /dev/null +++ b/server/src/schema/migrations/1773956345315-DuplicateSharedLinkAssets.ts @@ -0,0 +1,13 @@ +import { Kysely, sql } from 'kysely'; + +export async function up(db: Kysely): Promise { + await sql` + DELETE FROM "shared_link_asset" + USING "shared_link" + WHERE "shared_link_asset"."sharedLinkId" = "shared_link"."id" AND "shared_link"."type" = 'ALBUM'; +`.execute(db); +} + +export async function down(): Promise { + // noop +} diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index 24b9b165c9..547ec63bf8 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -165,6 +165,12 @@ export class AlbumService extends BaseService { } async addAssets(auth: AuthDto, id: string, dto: BulkIdsDto): Promise { + if (auth.sharedLink) { + this.logger.deprecate( + 'Assets uploaded to a shared link are automatically added and calling this endpoint is no longer necessary. It will be removed in the next major release.', + ); + } + const album = await this.findOrFail(id, { withAssets: false }); await this.requireAccess({ auth, permission: Permission.AlbumAssetCreate, ids: [id] }); @@ -195,6 +201,12 @@ export class AlbumService extends BaseService { } async addAssetsToAlbums(auth: AuthDto, dto: AlbumsAddAssetsDto): Promise { + if (auth.sharedLink) { + this.logger.deprecate( + 'Assets uploaded to a shared link are automatically added and calling this endpoint is no longer necessary. It will be removed in the next major release.', + ); + } + const results: AlbumsAddAssetsResponseDto = { success: false, error: BulkIdErrorReason.DUPLICATE, diff --git a/server/src/services/asset-media.service.ts b/server/src/services/asset-media.service.ts index 3c981ea61e..10132bbb07 100644 --- a/server/src/services/asset-media.service.ts +++ b/server/src/services/asset-media.service.ts @@ -2,7 +2,7 @@ import { BadRequestException, Injectable, InternalServerErrorException, NotFound import { extname } from 'node:path'; import sanitize from 'sanitize-filename'; import { StorageCore } from 'src/cores/storage.core'; -import { Asset } from 'src/database'; +import { Asset, AuthSharedLink } from 'src/database'; import { AssetBulkUploadCheckResponseDto, AssetMediaResponseDto, @@ -152,7 +152,7 @@ export class AssetMediaService extends BaseService { const asset = await this.create(auth.user.id, dto, file, sidecarFile); if (auth.sharedLink) { - await this.sharedLinkRepository.addAssets(auth.sharedLink.id, [asset.id]); + await this.addToSharedLink(auth.sharedLink, asset.id); } await this.userRepository.updateUsage(auth.user.id, file.size); @@ -326,6 +326,12 @@ export class AssetMediaService extends BaseService { }; } + private async addToSharedLink(sharedLink: AuthSharedLink, assetId: string) { + await (sharedLink.albumId + ? this.albumRepository.addAssetIds(sharedLink.albumId, [assetId]) + : this.sharedLinkRepository.addAssets(sharedLink.id, [assetId])); + } + private async handleUploadError( error: any, auth: AuthDto, @@ -347,7 +353,7 @@ export class AssetMediaService extends BaseService { } if (auth.sharedLink) { - await this.sharedLinkRepository.addAssets(auth.sharedLink.id, [duplicateId]); + await this.addToSharedLink(auth.sharedLink, duplicateId); } return { status: AssetMediaStatus.DUPLICATE, id: duplicateId }; diff --git a/server/src/services/version.service.spec.ts b/server/src/services/version.service.spec.ts index 7872f720a9..eacae928eb 100644 --- a/server/src/services/version.service.spec.ts +++ b/server/src/services/version.service.spec.ts @@ -1,5 +1,6 @@ import { DateTime } from 'luxon'; import { SemVer } from 'semver'; +import { defaults } from 'src/config'; import { serverVersion } from 'src/constants'; import { ImmichEnvironment, JobName, JobStatus, SystemMetadataKey } from 'src/enum'; import { VersionService } from 'src/services/version.service'; @@ -130,6 +131,32 @@ describe(VersionService.name, () => { }); }); + describe('onConfigUpdate', () => { + it('should queue a version check job when newVersionCheck is enabled', async () => { + await sut.onConfigUpdate({ + oldConfig: { ...defaults, newVersionCheck: { enabled: false } }, + newConfig: { ...defaults, newVersionCheck: { enabled: true } }, + }); + expect(mocks.job.queue).toHaveBeenCalledWith({ name: JobName.VersionCheck, data: {} }); + }); + + it('should not queue a version check job when newVersionCheck is disabled', async () => { + await sut.onConfigUpdate({ + oldConfig: { ...defaults, newVersionCheck: { enabled: true } }, + newConfig: { ...defaults, newVersionCheck: { enabled: false } }, + }); + expect(mocks.job.queue).not.toHaveBeenCalled(); + }); + + it('should not queue a version check job when newVersionCheck was already enabled', async () => { + await sut.onConfigUpdate({ + oldConfig: { ...defaults, newVersionCheck: { enabled: true } }, + newConfig: { ...defaults, newVersionCheck: { enabled: true } }, + }); + expect(mocks.job.queue).not.toHaveBeenCalled(); + }); + }); + describe('onWebsocketConnection', () => { it('should send on_server_version client event', async () => { await sut.onWebsocketConnection({ userId: '42' }); diff --git a/server/src/services/version.service.ts b/server/src/services/version.service.ts index fd51fa9adf..fc51481cad 100644 --- a/server/src/services/version.service.ts +++ b/server/src/services/version.service.ts @@ -55,6 +55,13 @@ export class VersionService extends BaseService { return this.versionRepository.getAll(); } + @OnEvent({ name: 'ConfigUpdate' }) + async onConfigUpdate({ oldConfig, newConfig }: ArgOf<'ConfigUpdate'>) { + if (!oldConfig.newVersionCheck.enabled && newConfig.newVersionCheck.enabled) { + await this.handleQueueVersionCheck(); + } + } + async handleQueueVersionCheck() { await this.jobRepository.queue({ name: JobName.VersionCheck, data: {} }); } diff --git a/server/src/utils/access.ts b/server/src/utils/access.ts index 7431cb3293..2e0f7d10d0 100644 --- a/server/src/utils/access.ts +++ b/server/src/utils/access.ts @@ -190,7 +190,13 @@ const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRe } case Permission.AlbumUpdate: { - return await access.album.checkOwnerAccess(auth.user.id, ids); + const isOwner = await access.album.checkOwnerAccess(auth.user.id, ids); + const isShared = await access.album.checkSharedAlbumAccess( + auth.user.id, + setDifference(ids, isOwner), + AlbumUserRole.Editor, + ); + return setUnion(isOwner, isShared); } case Permission.AlbumDelete: { @@ -198,7 +204,13 @@ const checkOtherAccess = async (access: AccessRepository, request: OtherAccessRe } case Permission.AlbumShare: { - return await access.album.checkOwnerAccess(auth.user.id, ids); + const isOwner = await access.album.checkOwnerAccess(auth.user.id, ids); + const isShared = await access.album.checkSharedAlbumAccess( + auth.user.id, + setDifference(ids, isOwner), + AlbumUserRole.Editor, + ); + return setUnion(isOwner, isShared); } case Permission.AlbumDownload: { diff --git a/server/test/fixtures/auth.stub.ts b/server/test/fixtures/auth.stub.ts index 3e5825c0cc..85d52f14a1 100644 --- a/server/test/fixtures/auth.stub.ts +++ b/server/test/fixtures/auth.stub.ts @@ -48,6 +48,7 @@ export const authStub = { showExif: true, allowDownload: true, allowUpload: true, + albumId: null, expiresAt: null, password: null, userId: '42', diff --git a/server/test/medium.factory.ts b/server/test/medium.factory.ts index 53bf78b5b8..a8aa00c2a3 100644 --- a/server/test/medium.factory.ts +++ b/server/test/medium.factory.ts @@ -220,9 +220,9 @@ export class MediumTestContext { return { result }; } - async newAlbum(dto: Insertable) { + async newAlbum(dto: Insertable, assetIds?: string[]) { const album = mediumFactory.albumInsert(dto); - const result = await this.get(AlbumRepository).create(album, [], []); + const result = await this.get(AlbumRepository).create(album, assetIds ?? [], []); return { album, result }; } diff --git a/server/test/medium/specs/services/asset-media.service.spec.ts b/server/test/medium/specs/services/asset-media.service.spec.ts index cdd47e3dc4..f10844ca4a 100644 --- a/server/test/medium/specs/services/asset-media.service.spec.ts +++ b/server/test/medium/specs/services/asset-media.service.spec.ts @@ -1,12 +1,15 @@ import { Kysely } from 'kysely'; +import { randomBytes } from 'node:crypto'; import { AssetMediaStatus } from 'src/dtos/asset-media-response.dto'; import { AssetMediaSize } from 'src/dtos/asset-media.dto'; -import { AssetFileType } from 'src/enum'; +import { AssetFileType, SharedLinkType } from 'src/enum'; import { AccessRepository } from 'src/repositories/access.repository'; +import { AlbumRepository } from 'src/repositories/album.repository'; import { AssetRepository } from 'src/repositories/asset.repository'; import { EventRepository } from 'src/repositories/event.repository'; import { JobRepository } from 'src/repositories/job.repository'; import { LoggingRepository } from 'src/repositories/logging.repository'; +import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; import { UserRepository } from 'src/repositories/user.repository'; import { DB } from 'src/schema'; @@ -22,7 +25,7 @@ let defaultDatabase: Kysely; const setup = (db?: Kysely) => { return newMediumService(AssetMediaService, { database: db || defaultDatabase, - real: [AccessRepository, AssetRepository, UserRepository], + real: [AccessRepository, AlbumRepository, AssetRepository, SharedLinkRepository, UserRepository], mock: [EventRepository, LoggingRepository, JobRepository, StorageRepository], }); }; @@ -44,7 +47,6 @@ describe(AssetService.name, () => { const { asset } = await ctx.newAsset({ ownerId: user.id }); await ctx.newExif({ assetId: asset.id, fileSizeInByte: 12_345 }); const auth = factory.auth({ user: { id: user.id } }); - const file = mediumFactory.uploadFile(); await expect( sut.uploadAsset( @@ -56,7 +58,7 @@ describe(AssetService.name, () => { fileCreatedAt: new Date(), assetData: Buffer.from('some data'), }, - file, + mediumFactory.uploadFile(), ), ).resolves.toEqual({ id: expect.any(String), @@ -99,6 +101,168 @@ describe(AssetService.name, () => { status: AssetMediaStatus.CREATED, }); }); + + it('should add to a shared link', async () => { + const { sut, ctx } = setup(); + + const sharedLinkRepo = ctx.get(SharedLinkRepository); + + ctx.getMock(StorageRepository).utimes.mockResolvedValue(); + ctx.getMock(EventRepository).emit.mockResolvedValue(); + ctx.getMock(JobRepository).queue.mockResolvedValue(); + + const { user } = await ctx.newUser(); + + const sharedLink = await sharedLinkRepo.create({ + key: randomBytes(50), + type: SharedLinkType.Individual, + description: 'Shared link description', + userId: user.id, + allowDownload: true, + allowUpload: true, + }); + + const auth = factory.auth({ user: { id: user.id }, sharedLink }); + const file = mediumFactory.uploadFile(); + const uploadDto = { + deviceId: 'some-id', + deviceAssetId: 'some-id', + fileModifiedAt: new Date(), + fileCreatedAt: new Date(), + assetData: Buffer.from('some data'), + }; + + const response = await sut.uploadAsset(auth, uploadDto, file); + expect(response).toEqual({ id: expect.any(String), status: AssetMediaStatus.CREATED }); + + const update = await sharedLinkRepo.get(user.id, sharedLink.id); + const assets = update!.assets; + expect(assets).toHaveLength(1); + expect(assets[0]).toMatchObject({ id: response.id }); + }); + + it('should handle adding a duplicate asset to a shared link', async () => { + const { sut, ctx } = setup(); + + ctx.getMock(StorageRepository).utimes.mockResolvedValue(); + ctx.getMock(EventRepository).emit.mockResolvedValue(); + ctx.getMock(JobRepository).queue.mockResolvedValue(); + + const sharedLinkRepo = ctx.get(SharedLinkRepository); + + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + await ctx.newExif({ assetId: asset.id, fileSizeInByte: 12_345 }); + + const sharedLink = await sharedLinkRepo.create({ + key: randomBytes(50), + type: SharedLinkType.Individual, + description: 'Shared link description', + userId: user.id, + allowDownload: true, + allowUpload: true, + assetIds: [asset.id], + }); + + const auth = factory.auth({ user: { id: user.id }, sharedLink }); + const uploadDto = { + deviceId: 'some-id', + deviceAssetId: 'some-id', + fileModifiedAt: new Date(), + fileCreatedAt: new Date(), + assetData: Buffer.from('some data'), + }; + + const response = await sut.uploadAsset(auth, uploadDto, mediumFactory.uploadFile({ checksum: asset.checksum })); + expect(response).toEqual({ id: expect.any(String), status: AssetMediaStatus.DUPLICATE }); + + const update = await sharedLinkRepo.get(user.id, sharedLink.id); + const assets = update!.assets; + expect(assets).toHaveLength(1); + expect(assets[0]).toMatchObject({ id: response.id }); + }); + + it('should add to an album shared link', async () => { + const { sut, ctx } = setup(); + + const sharedLinkRepo = ctx.get(SharedLinkRepository); + + ctx.getMock(StorageRepository).utimes.mockResolvedValue(); + ctx.getMock(EventRepository).emit.mockResolvedValue(); + ctx.getMock(JobRepository).queue.mockResolvedValue(); + + const { user } = await ctx.newUser(); + const { album } = await ctx.newAlbum({ ownerId: user.id }); + + const sharedLink = await sharedLinkRepo.create({ + key: randomBytes(50), + type: SharedLinkType.Album, + albumId: album.id, + description: 'Shared link description', + userId: user.id, + allowDownload: true, + allowUpload: true, + }); + + const auth = factory.auth({ user: { id: user.id }, sharedLink }); + const uploadDto = { + deviceId: 'some-id', + deviceAssetId: 'some-id', + fileModifiedAt: new Date(), + fileCreatedAt: new Date(), + assetData: Buffer.from('some data'), + }; + + const response = await sut.uploadAsset(auth, uploadDto, mediumFactory.uploadFile()); + expect(response).toEqual({ id: expect.any(String), status: AssetMediaStatus.CREATED }); + + const result = await ctx.get(AlbumRepository).getAssetIds(album.id, [response.id]); + const assets = [...result]; + expect(assets).toHaveLength(1); + expect(assets[0]).toEqual(response.id); + }); + + it('should handle adding a duplicate asset to an album shared link', async () => { + const { sut, ctx } = setup(); + + const sharedLinkRepo = ctx.get(SharedLinkRepository); + + ctx.getMock(StorageRepository).utimes.mockResolvedValue(); + ctx.getMock(EventRepository).emit.mockResolvedValue(); + ctx.getMock(JobRepository).queue.mockResolvedValue(); + + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + const { album } = await ctx.newAlbum({ ownerId: user.id }, [asset.id]); + // await ctx.newExif({ assetId: asset.id, fileSizeInByte: 12_345 }); + + const sharedLink = await sharedLinkRepo.create({ + key: randomBytes(50), + type: SharedLinkType.Album, + albumId: album.id, + description: 'Shared link description', + userId: user.id, + allowDownload: true, + allowUpload: true, + }); + + const auth = factory.auth({ user: { id: user.id }, sharedLink }); + const uploadDto = { + deviceId: 'some-id', + deviceAssetId: 'some-id', + fileModifiedAt: new Date(), + fileCreatedAt: new Date(), + assetData: Buffer.from('some data'), + }; + + const response = await sut.uploadAsset(auth, uploadDto, mediumFactory.uploadFile({ checksum: asset.checksum })); + expect(response).toEqual({ id: expect.any(String), status: AssetMediaStatus.DUPLICATE }); + + const result = await ctx.get(AlbumRepository).getAssetIds(album.id, [response.id]); + const assets = [...result]; + expect(assets).toHaveLength(1); + expect(assets[0]).toEqual(response.id); + }); }); describe('viewThumbnail', () => { diff --git a/server/test/small.factory.ts b/server/test/small.factory.ts index 57098e01ee..e4001d18ab 100644 --- a/server/test/small.factory.ts +++ b/server/test/small.factory.ts @@ -63,12 +63,22 @@ const authSharedLinkFactory = (sharedLink: Partial = {}) => { expiresAt = null, userId = newUuid(), showExif = true, + albumId = null, allowUpload = false, allowDownload = true, password = null, } = sharedLink; - return { id, expiresAt, userId, showExif, allowUpload, allowDownload, password }; + return { + id, + albumId, + expiresAt, + userId, + showExif, + allowUpload, + allowDownload, + password, + }; }; const authApiKeyFactory = (apiKey: Partial = {}) => ({ diff --git a/web/package.json b/web/package.json index ef0310f6be..0288aeae6d 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "immich-web", - "version": "2.6.1", + "version": "2.6.2", "license": "GNU Affero General Public License version 3", "type": "module", "scripts": { @@ -72,10 +72,10 @@ "@koddsson/eslint-plugin-tscompat": "^0.2.0", "@socket.io/component-emitter": "^3.1.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/enhanced-img": "^0.10.0", + "@sveltejs/enhanced-img": "^0.10.4", "@sveltejs/kit": "^2.27.1", - "@sveltejs/vite-plugin-svelte": "6.2.4", - "@tailwindcss/vite": "^4.1.7", + "@sveltejs/vite-plugin-svelte": "7.0.0", + "@tailwindcss/vite": "^4.2.2", "@testing-library/jest-dom": "^6.4.2", "@testing-library/svelte": "^5.2.8", "@testing-library/user-event": "^14.5.2", @@ -100,13 +100,13 @@ "prettier-plugin-sort-json": "^4.1.1", "prettier-plugin-svelte": "^3.3.3", "rollup-plugin-visualizer": "^6.0.0", - "svelte": "5.53.7", + "svelte": "5.53.13", "svelte-check": "^4.1.5", "svelte-eslint-parser": "^1.3.3", - "tailwindcss": "^4.1.7", + "tailwindcss": "^4.2.2", "typescript": "^5.8.3", "typescript-eslint": "^8.45.0", - "vite": "^7.1.2", + "vite": "^8.0.0", "vitest": "^4.0.0" }, "volta": { diff --git a/web/src/lib/components/shared-components/combobox.svelte b/web/src/lib/components/shared-components/combobox.svelte index 4721357012..803087feef 100644 --- a/web/src/lib/components/shared-components/combobox.svelte +++ b/web/src/lib/components/shared-components/combobox.svelte @@ -212,12 +212,12 @@ bottom: `${rootHeight - top}px`, left: `${left}px`, width: `${boundary.width}px`, - maxHeight: maxHeight(top - dropdownOffset), + maxHeight: maxHeight(boundary.top - dropdownOffset), }; } - const viewportHeight = visualViewport?.height || rootHeight; - const availableHeight = modalBounds ? rootHeight - bottom : viewportHeight - boundary.bottom; + const viewportHeight = visualViewport?.height || window.innerHeight; + const availableHeight = viewportHeight - boundary.bottom; return { top: `${bottom}px`, left: `${left}px`, diff --git a/web/src/lib/modals/AlbumPickerModal.svelte b/web/src/lib/modals/AlbumPickerModal.svelte index 081c7f49d7..ed0066f9f3 100644 --- a/web/src/lib/modals/AlbumPickerModal.svelte +++ b/web/src/lib/modals/AlbumPickerModal.svelte @@ -28,7 +28,10 @@ let { onClose }: Props = $props(); onMount(async () => { - albums = await getAllAlbums({}); + // TODO the server should *really* just return all albums (paginated ideally) + const ownedAlbums = await getAllAlbums({ shared: false }); + ownedAlbums.push.apply(ownedAlbums, await getAllAlbums({ shared: true })); + albums = ownedAlbums; recentAlbums = albums.sort((a, b) => (new Date(a.updatedAt) > new Date(b.updatedAt) ? -1 : 1)).slice(0, 3); loading = false; }); diff --git a/web/src/lib/services/asset.service.ts b/web/src/lib/services/asset.service.ts index c8614186fd..76ac0b7fc0 100644 --- a/web/src/lib/services/asset.service.ts +++ b/web/src/lib/services/asset.service.ts @@ -8,17 +8,16 @@ import SharedLinkCreateModal from '$lib/modals/SharedLinkCreateModal.svelte'; import { isFaceEditMode } from '$lib/stores/face-edit.svelte'; import { user as authUser, preferences } from '$lib/stores/user.store'; import type { AssetControlContext } from '$lib/types'; -import { getSharedLink, sleep } from '$lib/utils'; +import { getAssetMediaUrl, getSharedLink, sleep } from '$lib/utils'; import { downloadUrl } from '$lib/utils/asset-utils'; import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; -import { asQueryString } from '$lib/utils/shared-links'; import { AssetJobName, + AssetMediaSize, AssetTypeEnum, AssetVisibility, getAssetInfo, - getBaseUrl, runAssetJobs, updateAsset, type AssetJobsDto, @@ -308,6 +307,7 @@ export const handleDownloadAsset = async (asset: AssetResponseDto, { edited }: { { filename: asset.originalFileName, id: asset.id, + cacheKey: asset.thumbhash, }, ]; @@ -321,13 +321,12 @@ export const handleDownloadAsset = async (asset: AssetResponseDto, { edited }: { assets.push({ filename: motionAsset.originalFileName, id: asset.livePhotoVideoId, + cacheKey: motionAsset.thumbhash, }); } } - const queryParams = asQueryString(authManager.params); - - for (const [i, { filename, id }] of assets.entries()) { + for (const [i, { filename, id, cacheKey }] of assets.entries()) { if (i !== 0) { // play nice with Safari await sleep(500); @@ -335,12 +334,7 @@ export const handleDownloadAsset = async (asset: AssetResponseDto, { edited }: { try { toastManager.primary($t('downloading_asset_filename', { values: { filename } })); - downloadUrl( - getBaseUrl() + - `/assets/${id}/original` + - (queryParams ? `?${queryParams}&edited=${edited}` : `?edited=${edited}`), - filename, - ); + downloadUrl(getAssetMediaUrl({ id, size: AssetMediaSize.Original, edited, cacheKey }), filename); } catch (error) { handleError(error, $t('errors.error_downloading', { values: { filename } })); } diff --git a/web/src/lib/stores/upload.ts b/web/src/lib/stores/upload.ts index 8e775b7b79..b36a2e5e70 100644 --- a/web/src/lib/stores/upload.ts +++ b/web/src/lib/stores/upload.ts @@ -80,7 +80,34 @@ function createUploadStore() { }; const removeItem = (id: string) => { - uploadAssets.update((uploadingAsset) => uploadingAsset.filter((a) => a.id != id)); + uploadAssets.update((uploadingAsset) => { + const assetToRemove = uploadingAsset.find((a) => a.id === id); + if (assetToRemove) { + stats.update((stats) => { + switch (assetToRemove.state) { + case UploadState.DONE: { + stats.success--; + break; + } + + case UploadState.DUPLICATED: { + stats.duplicates--; + break; + } + + case UploadState.ERROR: { + stats.errors--; + break; + } + } + + stats.total--; + return stats; + }); + } + + return uploadingAsset.filter((a) => a.id != id); + }); }; const dismissErrors = () => diff --git a/web/src/lib/utils/file-uploader.ts b/web/src/lib/utils/file-uploader.ts index f2a4cdec4f..2950563a85 100644 --- a/web/src/lib/utils/file-uploader.ts +++ b/web/src/lib/utils/file-uploader.ts @@ -216,7 +216,7 @@ async function fileUploader({ uploadAssetsStore.track('success'); } - if (albumId) { + if (albumId && !authManager.isSharedLink) { uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_adding_to_album') }); await addAssetsToAlbums([albumId], [responseData.id], { notify: false }); uploadAssetsStore.updateItem(deviceAssetId, { message: $t('asset_added_to_album') }); diff --git a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte index 2e911d8330..9a2d36ed95 100644 --- a/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId=id]/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -287,7 +287,11 @@ } }; - const onAlbumAddAssets = async () => { + const onAlbumAddAssets = async ({ albumIds }: { albumIds: string[] }) => { + if (!albumIds.includes(album.id)) { + return; + } + await refreshAlbum(); timelineInteraction.clearMultiselect(); await setModeToView(); @@ -472,13 +476,6 @@ - {#if assetInteraction.selectedAssets.length === 1} - updateThumbnailUsingCurrentSelection()} - /> - {/if} {/if} + {#if assetInteraction.selectedAssets.length === 1} + updateThumbnailUsingCurrentSelection()} + /> + {/if} {#if $preferences.tags.enabled && assetInteraction.isAllUserOwned} diff --git a/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte index f1b9ca7614..c7c0c146ad 100644 --- a/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/utilities/duplicates/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -178,19 +178,7 @@ const handleFirst = () => navigateToIndex(0); const handlePrevious = () => navigateToIndex(Math.max(duplicatesIndex - 1, 0)); - const handlePreviousShortcut = async () => { - if ($showAssetViewer) { - return; - } - await handlePrevious(); - }; const handleNext = async () => navigateToIndex(Math.min(duplicatesIndex + 1, duplicates.length - 1)); - const handleNextShortcut = async () => { - if ($showAssetViewer) { - return; - } - await handleNext(); - }; const handleLast = () => navigateToIndex(duplicates.length - 1); const navigateToIndex = async (index: number) => @@ -198,10 +186,12 @@