diff --git a/.github/package.json b/.github/package.json index 1cb0262c74..9b41cc7b4e 100644 --- a/.github/package.json +++ b/.github/package.json @@ -4,6 +4,6 @@ "format:fix": "prettier --write ." }, "devDependencies": { - "prettier": "^3.5.3" + "prettier": "^3.7.4" } } diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml index 9495d03bb9..10dc88088f 100644 --- a/.github/workflows/build-mobile.yml +++ b/.github/workflows/build-mobile.yml @@ -108,7 +108,7 @@ jobs: working-directory: ./mobile run: printf "%s" $KEY_JKS | base64 -d > android/key.jks - - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 + - uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # v5.1.0 with: distribution: 'zulu' java-version: '17' @@ -222,6 +222,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: '3.3' + bundler-cache: true working-directory: ./mobile/ios - name: Install CocoaPods dependencies @@ -229,13 +230,6 @@ jobs: run: | pod install - - name: Install Fastlane - working-directory: ./mobile/ios - run: | - gem install bundler - bundle config set --local path 'vendor/bundle' - bundle install - - name: Create API Key env: API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index ef7300f7d4..8bf8da30d7 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -44,7 +44,7 @@ jobs: uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './cli/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index dafc6eee3b..20a5e23c0c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -57,7 +57,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5 + uses: github/codeql-action/init@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -70,7 +70,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5 + uses: github/codeql-action/autobuild@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -83,6 +83,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fdbfb4d2750291e159f0156def62b853c2798ca2 # v4.31.5 + uses: github/codeql-action/analyze@cf1bb45a277cb3c205638b2cd5c984db1c46a412 # v4.31.7 with: category: '/language:${{matrix.language}}' diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 24cb804e77..680cd0318c 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -69,7 +69,7 @@ jobs: uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './docs/.nvmrc' cache: 'pnpm' diff --git a/.github/workflows/fix-format.yml b/.github/workflows/fix-format.yml index d3db51348b..f77ca48b41 100644 --- a/.github/workflows/fix-format.yml +++ b/.github/workflows/fix-format.yml @@ -16,7 +16,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} @@ -32,7 +32,7 @@ jobs: uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' diff --git a/.github/workflows/merge-translations.yml b/.github/workflows/merge-translations.yml index 92d2783441..392dec5e37 100644 --- a/.github/workflows/merge-translations.yml +++ b/.github/workflows/merge-translations.yml @@ -31,7 +31,7 @@ jobs: - name: Generate a token id: generate_token if: ${{ inputs.skip != true }} - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index e2543a53d0..6aada80220 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -49,7 +49,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} @@ -68,7 +68,7 @@ jobs: uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -126,7 +126,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} @@ -144,7 +144,7 @@ jobs: github-token: ${{ steps.generate-token.outputs.token }} - name: Create draft release - uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: draft: true tag_name: ${{ env.IMMICH_VERSION }} diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 204c0a853c..4a06957203 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} @@ -36,7 +36,7 @@ jobs: uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -159,7 +159,7 @@ jobs: - name: Create PR id: create-pr - uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9 + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7.0.11 with: token: ${{ steps.generate-token.outputs.token }} commit-message: 'chore: release ${{ steps.bump-type.outputs.next }}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f6f7cf5cf..cb64cd37cf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,7 +52,7 @@ jobs: steps: - name: Generate a token id: generate-token - uses: actions/create-github-app-token@7e473efe3cb98aa54f8d4bac15400b15fad77d94 # v2.2.0 + uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1 with: app-id: ${{ secrets.PUSH_O_MATIC_APP_ID }} private-key: ${{ secrets.PUSH_O_MATIC_APP_KEY }} @@ -80,7 +80,7 @@ jobs: github-token: ${{ steps.generate-token.outputs.token }} - name: Create draft release - uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: tag_name: ${{ steps.version.outputs.result }} token: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index dc8cc34cb2..9c70922df1 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -31,7 +31,7 @@ jobs: uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 # Setup .npmrc file to publish to npm - - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './open-api/typescript-sdk/.nvmrc' registry-url: 'https://registry.npmjs.org' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f02114a39a..c5d196a084 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -77,7 +77,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -121,7 +121,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './cli/.nvmrc' cache: 'pnpm' @@ -168,7 +168,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './cli/.nvmrc' cache: 'pnpm' @@ -210,7 +210,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './web/.nvmrc' cache: 'pnpm' @@ -254,7 +254,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './web/.nvmrc' cache: 'pnpm' @@ -292,7 +292,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './web/.nvmrc' cache: 'pnpm' @@ -340,7 +340,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './e2e/.nvmrc' cache: 'pnpm' @@ -387,7 +387,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -426,7 +426,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './e2e/.nvmrc' cache: 'pnpm' @@ -481,7 +481,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './e2e/.nvmrc' cache: 'pnpm' @@ -617,7 +617,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './.github/.nvmrc' cache: 'pnpm' @@ -668,7 +668,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' @@ -730,7 +730,7 @@ jobs: - name: Setup pnpm uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 - name: Setup Node - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 with: node-version-file: './server/.nvmrc' cache: 'pnpm' diff --git a/cli/package.json b/cli/package.json index b64354ee4a..3c65605330 100644 --- a/cli/package.json +++ b/cli/package.json @@ -20,7 +20,7 @@ "@types/lodash-es": "^4.17.12", "@types/micromatch": "^4.0.9", "@types/mock-fs": "^4.13.1", - "@types/node": "^24.10.1", + "@types/node": "^24.10.3", "@vitest/coverage-v8": "^3.0.0", "byte-size": "^9.0.0", "cli-progress": "^3.12.0", @@ -31,7 +31,7 @@ "eslint-plugin-unicorn": "^62.0.0", "globals": "^16.0.0", "mock-fs": "^5.2.0", - "prettier": "^3.2.5", + "prettier": "^3.7.4", "prettier-plugin-organize-imports": "^4.0.0", "typescript": "^5.3.3", "typescript-eslint": "^8.28.0", diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 6fa1c51bdd..4c74d1d640 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -58,10 +58,6 @@ services: IMMICH_THIRD_PARTY_BUG_FEATURE_URL: https://github.com/immich-app/immich/issues IMMICH_THIRD_PARTY_DOCUMENTATION_URL: https://docs.immich.app IMMICH_THIRD_PARTY_SUPPORT_URL: https://docs.immich.app/community-guides - ulimits: - nofile: - soft: 1048576 - hard: 1048576 ports: - 9230:9230 - 9231:9231 @@ -100,10 +96,6 @@ services: - app-node_modules:/usr/src/app/node_modules - sveltekit:/usr/src/app/web/.svelte-kit - coverage:/usr/src/app/web/coverage - ulimits: - nofile: - soft: 1048576 - hard: 1048576 restart: unless-stopped depends_on: immich-server: @@ -135,7 +127,7 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:9@sha256:4503e204c900a00ad393bec83c8c7c4c76b0529cd629e23b34b52011aefd1d27 + image: docker.io/valkey/valkey:9@sha256:fb8d272e529ea567b9bf1302245796f21a2672b8368ca3fcb938ac334e613c8f healthcheck: test: redis-cli ping || exit 1 diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 1aae886bc6..21178d8d76 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -56,7 +56,7 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:9@sha256:4503e204c900a00ad393bec83c8c7c4c76b0529cd629e23b34b52011aefd1d27 + image: docker.io/valkey/valkey:9@sha256:fb8d272e529ea567b9bf1302245796f21a2672b8368ca3fcb938ac334e613c8f healthcheck: test: redis-cli ping || exit 1 restart: always @@ -83,7 +83,7 @@ services: container_name: immich_prometheus ports: - 9090:9090 - image: prom/prometheus@sha256:49214755b6153f90a597adcbff0252cc61069f8ab69ce8411285cd4a560e8038 + image: prom/prometheus@sha256:d936808bdea528155c0154a922cd42fd75716b8bb7ba302641350f9f3eaeba09 volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 51b6d3e860..f5dfb1233f 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -49,7 +49,7 @@ services: redis: container_name: immich_redis - image: docker.io/valkey/valkey:9@sha256:4503e204c900a00ad393bec83c8c7c4c76b0529cd629e23b34b52011aefd1d27 + image: docker.io/valkey/valkey:9@sha256:fb8d272e529ea567b9bf1302245796f21a2672b8368ca3fcb938ac334e613c8f healthcheck: test: redis-cli ping || exit 1 restart: always diff --git a/docs/docs/administration/backup-and-restore.md b/docs/docs/administration/backup-and-restore.md index fbb4cd8c23..2ca965624f 100644 --- a/docs/docs/administration/backup-and-restore.md +++ b/docs/docs/administration/backup-and-restore.md @@ -41,7 +41,7 @@ By default, Immich will keep the last 14 database dumps and create a new dump ev #### Trigger Dump -You are able to trigger a database dump in the [admin job status page](http://my.immich.app/admin/jobs-status). +You are able to trigger a database dump in the [admin job status page](http://my.immich.app/admin/queues). Visit the page, open the "Create job" modal from the top right, select "Create Database Dump" and click "Confirm". A job will run and trigger a dump, you can verify this worked correctly by checking the logs or the `backups/` folder. This dumps will count towards the last `X` dumps that will be kept based on your settings. diff --git a/docs/docs/administration/reverse-proxy.md b/docs/docs/administration/reverse-proxy.md index 5c9e47b010..8dd1674448 100644 --- a/docs/docs/administration/reverse-proxy.md +++ b/docs/docs/administration/reverse-proxy.md @@ -21,6 +21,12 @@ server { # allow large file uploads client_max_body_size 50000M; + # disable buffering uploads to prevent OOM on reverse proxy server and make uploads twice as fast (no pause) + proxy_request_buffering off; + + # increase body buffer to avoid limiting upload speed + client_body_buffer_size 1024k; + # Set headers proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; @@ -29,8 +35,6 @@ server { # enable websockets: http://nginx.org/en/docs/http/websocket.html proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; proxy_redirect off; # set timeout @@ -40,6 +44,8 @@ server { location / { proxy_pass http://:2283; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; } # useful when using Let's Encrypt http-01 challenge diff --git a/docs/docs/administration/server-commands.md b/docs/docs/administration/server-commands.md index 8c58baac17..cbd029296f 100644 --- a/docs/docs/administration/server-commands.md +++ b/docs/docs/administration/server-commands.md @@ -52,7 +52,7 @@ Password login has been enabled. Disable Maintenance Mode ``` -immich-admin disable-maintenace-mode +immich-admin disable-maintenance-mode Maintenance mode has been disabled. ``` diff --git a/docs/docs/developer/setup.md b/docs/docs/developer/setup.md index f262743dcd..23c1862c19 100644 --- a/docs/docs/developer/setup.md +++ b/docs/docs/developer/setup.md @@ -48,7 +48,6 @@ You can access the web from `http://your-machine-ip:3000` or `http://localhost:3 **Notes:** - The "web" development container runs with uid 1000. If that uid does not have read/write permissions on the mounted volumes, you may encounter errors -- In case of rootless docker setup, you need to use root within the container, otherwise you will encounter read/write permission related errors, see comments in `docker/docker-compose.dev.yml`. #### Connect web to a remote backend diff --git a/docs/docs/features/searching.md b/docs/docs/features/searching.md index d7ebd1a468..e8985b0c92 100644 --- a/docs/docs/features/searching.md +++ b/docs/docs/features/searching.md @@ -1222,4 +1222,4 @@ Feel free to make a feature request if there's a model you want to use that we d [huggingface-clip]: https://huggingface.co/collections/immich-app/clip-654eaefb077425890874cd07 [huggingface-multilingual-clip]: https://huggingface.co/collections/immich-app/multilingual-clip-654eb08c2382f591eeb8c2a7 [smart-search-settings]: https://my.immich.app/admin/system-settings?isOpen=machine-learning+smart-search -[job-status-page]: https://my.immich.app/admin/jobs-status +[job-status-page]: https://my.immich.app/admin/queues diff --git a/docs/docs/guides/remote-machine-learning.md b/docs/docs/guides/remote-machine-learning.md index 0a8ddf2577..b677d83b0d 100644 --- a/docs/docs/guides/remote-machine-learning.md +++ b/docs/docs/guides/remote-machine-learning.md @@ -53,7 +53,7 @@ Version mismatches between both hosts may cause bugs and instability, so remembe Adding a new URL to the settings is recommended over replacing the existing URL. This is because it will allow machine learning tasks to be processed successfully when the remote server is down by falling back to the local machine learning container. If you do not want machine learning tasks to be processed locally when the remote server is not available, you can instead replace the existing URL and only provide the remote container's URL. If doing this, you can remove the `immich-machine-learning` section of the local `docker-compose.yml` file to save resources, as this service will never be used. -Do note that this will mean that Smart Search and Face Detection jobs will fail to be processed when the remote instance is not available. This in turn means that tasks dependent on these features—Duplicate Detection and Facial Recognition—will not run for affected assets. If this occurs, you must manually click the _Missing_ button next to Smart Search and Face Detection in the [Job Status](http://my.immich.app/admin/jobs-status) page for the jobs to be retried. +Do note that this will mean that Smart Search and Face Detection jobs will fail to be processed when the remote instance is not available. This in turn means that tasks dependent on these features—Duplicate Detection and Facial Recognition—will not run for affected assets. If this occurs, you must manually click the _Missing_ button next to Smart Search and Face Detection in the [Job Status](http://my.immich.app/admin/queues) page for the jobs to be retried. ## Load balancing diff --git a/docs/package.json b/docs/package.json index b96059c523..d37b256a3f 100644 --- a/docs/package.json +++ b/docs/package.json @@ -38,7 +38,7 @@ "@docusaurus/module-type-aliases": "~3.9.0", "@docusaurus/tsconfig": "^3.7.0", "@docusaurus/types": "^3.7.0", - "prettier": "^3.2.4", + "prettier": "^3.7.4", "typescript": "^5.1.6" }, "browserslist": { diff --git a/e2e/package.json b/e2e/package.json index 7bf61ea232..07d02f0cbc 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -26,7 +26,7 @@ "@playwright/test": "^1.44.1", "@socket.io/component-emitter": "^3.1.2", "@types/luxon": "^3.4.2", - "@types/node": "^24.10.1", + "@types/node": "^24.10.3", "@types/oidc-provider": "^9.0.0", "@types/pg": "^8.15.1", "@types/pngjs": "^6.0.4", @@ -36,14 +36,14 @@ "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-unicorn": "^62.0.0", - "exiftool-vendored": "^33.0.0", + "exiftool-vendored": "^34.0.0", "globals": "^16.0.0", "jose": "^5.6.3", "luxon": "^3.4.4", "oidc-provider": "^9.0.0", "pg": "^8.11.3", "pngjs": "^7.0.0", - "prettier": "^3.2.5", + "prettier": "^3.7.4", "prettier-plugin-organize-imports": "^4.0.0", "sharp": "^0.34.5", "socket.io-client": "^4.7.4", diff --git a/i18n/en.json b/i18n/en.json index 2ea5896eab..a050738f5c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -7,6 +7,7 @@ "action_common_update": "Update", "actions": "Actions", "active": "Active", + "active_count": "Active: {count}", "activity": "Activity", "activity_changed": "Activity is {enabled, select, true {enabled} other {disabled}}", "add": "Add", @@ -77,7 +78,6 @@ "exclusion_pattern_description": "Exclusion patterns lets you ignore files and folders when scanning your library. This is useful if you have folders that contain files you don't want to import, such as RAW files.", "export_config_as_json_description": "Download the current system config as a JSON file", "external_libraries_page_description": "Admin external library page", - "external_library_management": "External Library Management", "face_detection": "Face detection", "face_detection_description": "Detect the faces in assets using machine learning. For videos, only the thumbnail is considered. \"Refresh\" (re-)processes all assets. \"Reset\" additionally clears all current face data. \"Missing\" queues assets that haven't been processed yet. Detected faces will be queued for Facial Recognition after Face Detection is complete, grouping them into existing or new people.", "facial_recognition_job_description": "Group detected faces into people. This step runs after Face Detection is complete. \"Reset\" (re-)clusters all faces. \"Missing\" queues faces that don't have a person assigned.", @@ -111,10 +111,9 @@ "job_not_concurrency_safe": "This job is not concurrency-safe.", "job_settings": "Job Settings", "job_settings_description": "Manage job concurrency", - "job_status": "Job Status", "jobs_delayed": "{jobCount, plural, other {# delayed}}", "jobs_failed": "{jobCount, plural, other {# failed}}", - "jobs_page_description": "Admin jobs page", + "jobs_over_time": "Jobs over time", "library_created": "Created library: {library}", "library_deleted": "Library deleted", "library_details": "Library details", @@ -286,10 +285,14 @@ "password_settings_description": "Manage password login settings", "paths_validated_successfully": "All paths validated successfully", "person_cleanup_job": "Person cleanup", + "queue_details": "Queue Details", + "queues": "Job Queues", + "queues_page_description": "Admin job queues page", "quota_size_gib": "Quota Size (GiB)", "refreshing_all_libraries": "Refreshing all libraries", "registration": "Admin Registration", "registration_description": "Since you are the first user on the system, you will be assigned as the Admin and are responsible for administrative tasks, and additional users will be created by you.", + "remove_failed_jobs": "Remove failed jobs", "require_password_change_on_login": "Require user to change password on first login", "reset_settings_to_default": "Reset settings to default", "reset_settings_to_recent_saved": "Reset settings to the recent saved settings", @@ -658,6 +661,7 @@ "backup_options_page_title": "Backup options", "backup_setting_subtitle": "Manage background and foreground upload settings", "backup_settings_subtitle": "Manage upload settings", + "backup_upload_details_page_more_details": "Tap for more details", "backward": "Backward", "biometric_auth_enabled": "Biometric authentication enabled", "biometric_locked_out": "You are locked out of biometric authentication", @@ -724,6 +728,7 @@ "check_corrupt_asset_backup_button": "Perform check", "check_corrupt_asset_backup_description": "Run this check only over Wi-Fi and once all assets have been backed-up. The procedure might take a few minutes.", "check_logs": "Check Logs", + "checksum": "Checksum", "choose_matching_people_to_merge": "Choose matching people to merge", "city": "City", "clear": "Clear", @@ -1117,6 +1122,7 @@ "external_network_sheet_info": "When not on the preferred Wi-Fi network, the app will connect to the server through the first of the below URLs it can reach, starting from top to bottom", "face_unassigned": "Unassigned", "failed": "Failed", + "failed_count": "Failed: {count}", "failed_to_authenticate": "Failed to authenticate", "failed_to_load_assets": "Failed to load assets", "failed_to_load_folder": "Failed to load folder", @@ -1177,6 +1183,7 @@ "header_settings_header_name_input": "Header name", "header_settings_header_value_input": "Header value", "headers_settings_tile_title": "Custom proxy headers", + "height": "Height", "hi_user": "Hi {name} ({email})", "hide_all_people": "Hide all people", "hide_gallery": "Hide gallery", @@ -1299,6 +1306,7 @@ "local": "Local", "local_asset_cast_failed": "Unable to cast an asset that is not uploaded to the server", "local_assets": "Local Assets", + "local_id": "Local ID", "local_media_summary": "Local Media Summary", "local_network": "Local network", "local_network_sheet_info": "The app will connect to the server through this URL when using the specified Wi-Fi network", @@ -2240,10 +2248,12 @@ "viewer_unstack": "Un-Stack", "visibility_changed": "Visibility changed for {count, plural, one {# person} other {# people}}", "waiting": "Waiting", + "waiting_count": "Waiting: {count}", "warning": "Warning", "week": "Week", "welcome": "Welcome", "welcome_to_immich": "Welcome to Immich", + "width": "Width", "wifi_name": "Wi-Fi Name", "workflow": "Workflow", "wrong_pin_code": "Wrong PIN code", diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt index e6cf92f573..d3282f4dfd 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt @@ -89,7 +89,10 @@ data class PlatformAsset ( val height: Long? = null, val durationInSeconds: Long, val orientation: Long, - val isFavorite: Boolean + val isFavorite: Boolean, + val adjustmentTime: Long? = null, + val latitude: Double? = null, + val longitude: Double? = null ) { companion object { @@ -104,7 +107,10 @@ data class PlatformAsset ( val durationInSeconds = pigeonVar_list[7] as Long val orientation = pigeonVar_list[8] as Long val isFavorite = pigeonVar_list[9] as Boolean - return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite) + val adjustmentTime = pigeonVar_list[10] as Long? + val latitude = pigeonVar_list[11] as Double? + val longitude = pigeonVar_list[12] as Double? + return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite, adjustmentTime, latitude, longitude) } } fun toList(): List { @@ -119,6 +125,9 @@ data class PlatformAsset ( durationInSeconds, orientation, isFavorite, + adjustmentTime, + latitude, + longitude, ) } override fun equals(other: Any?): Boolean { diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt index b1e9dd7d44..b374ef50f0 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/sync/MessagesImplBase.kt @@ -4,7 +4,6 @@ import android.annotation.SuppressLint import android.content.ContentUris import android.content.Context import android.database.Cursor -import android.net.Uri import android.os.Bundle import android.provider.MediaStore import android.util.Base64 diff --git a/mobile/drift_schemas/main/drift_schema_v14.json b/mobile/drift_schemas/main/drift_schema_v14.json new file mode 100644 index 0000000000..40a1af8423 --- /dev/null +++ b/mobile/drift_schemas/main/drift_schema_v14.json @@ -0,0 +1 @@ +{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"remote_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"local_date_time","getter_name":"localDateTime","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"thumb_hash","getter_name":"thumbHash","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"live_photo_video_id","getter_name":"livePhotoVideoId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"visibility","getter_name":"visibility","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetVisibility.values)","dart_type_name":"AssetVisibility"}},{"name":"stack_id","getter_name":"stackId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"library_id","getter_name":"libraryId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":2,"references":[0],"type":"table","data":{"name":"stack_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"primary_asset_id","getter_name":"primaryAssetId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":3,"references":[],"type":"table","data":{"name":"local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"orientation","getter_name":"orientation","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"adjustment_time","getter_name":"adjustmentTime","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":4,"references":[0,1],"type":"table","data":{"name":"remote_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"thumbnail_asset_id","getter_name":"thumbnailAssetId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_activity_enabled","getter_name":"isActivityEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_activity_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_activity_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"order","getter_name":"order","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumAssetOrder.values)","dart_type_name":"AlbumAssetOrder"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":5,"references":[4],"type":"table","data":{"name":"local_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"backup_selection","getter_name":"backupSelection","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(BackupSelection.values)","dart_type_name":"BackupSelection"}},{"name":"is_ios_shared_album","getter_name":"isIosSharedAlbum","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_ios_shared_album\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_ios_shared_album\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"linked_remote_album_id","getter_name":"linkedRemoteAlbumId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":6,"references":[3,5],"type":"table","data":{"name":"local_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":7,"references":[3],"type":"index","data":{"on":3,"name":"idx_local_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)","unique":false,"columns":[]}},{"id":8,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_owner_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)","unique":false,"columns":[]}},{"id":9,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum\nON remote_asset_entity (owner_id, checksum)\nWHERE (library_id IS NULL);\n","unique":true,"columns":[]}},{"id":10,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_assets_owner_library_checksum","sql":"CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum\nON remote_asset_entity (owner_id, library_id, checksum)\nWHERE (library_id IS NOT NULL);\n","unique":true,"columns":[]}},{"id":11,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)","unique":false,"columns":[]}},{"id":12,"references":[],"type":"table","data":{"name":"auth_user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"has_profile_image","getter_name":"hasProfileImage","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"has_profile_image\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"has_profile_image\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"profile_changed_at","getter_name":"profileChangedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"avatar_color","getter_name":"avatarColor","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AvatarColor.values)","dart_type_name":"AvatarColor"}},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"pin_code","getter_name":"pinCode","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":13,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"key","getter_name":"key","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(UserMetadataKey.values)","dart_type_name":"UserMetadataKey"}},{"name":"value","getter_name":"value","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userMetadataConverter","dart_type_name":"Map"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id","key"]}},{"id":14,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}},{"id":15,"references":[1],"type":"table","data":{"name":"remote_exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"city","getter_name":"city","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"state","getter_name":"state","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"country","getter_name":"country","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"date_time_original","getter_name":"dateTimeOriginal","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"exposure_time","getter_name":"exposureTime","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"f_number","getter_name":"fNumber","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"file_size","getter_name":"fileSize","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"focal_length","getter_name":"focalLength","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"iso","getter_name":"iso","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"make","getter_name":"make","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"model","getter_name":"model","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"lens","getter_name":"lens","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"orientation","getter_name":"orientation","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"time_zone","getter_name":"timeZone","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"rating","getter_name":"rating","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"projection_type","getter_name":"projectionType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id"]}},{"id":16,"references":[1,4],"type":"table","data":{"name":"remote_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":17,"references":[4,0],"type":"table","data":{"name":"remote_album_user_entity","was_declared_in_moor":false,"columns":[{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"user_id","getter_name":"userId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"role","getter_name":"role","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumUserRole.values)","dart_type_name":"AlbumUserRole"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["album_id","user_id"]}},{"id":18,"references":[0],"type":"table","data":{"name":"memory_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(MemoryTypeEnum.values)","dart_type_name":"MemoryTypeEnum"}},{"name":"data","getter_name":"data","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_saved","getter_name":"isSaved","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_saved\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_saved\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"memory_at","getter_name":"memoryAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"seen_at","getter_name":"seenAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"show_at","getter_name":"showAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"hide_at","getter_name":"hideAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":19,"references":[1,18],"type":"table","data":{"name":"memory_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"memory_id","getter_name":"memoryId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES memory_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES memory_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","memory_id"]}},{"id":20,"references":[0],"type":"table","data":{"name":"person_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"face_asset_id","getter_name":"faceAssetId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_hidden","getter_name":"isHidden","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_hidden\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_hidden\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"color","getter_name":"color","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"birth_date","getter_name":"birthDate","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":21,"references":[1,20],"type":"table","data":{"name":"asset_face_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"person_id","getter_name":"personId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES person_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES person_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"image_width","getter_name":"imageWidth","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"image_height","getter_name":"imageHeight","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x1","getter_name":"boundingBoxX1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y1","getter_name":"boundingBoxY1","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_x2","getter_name":"boundingBoxX2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"bounding_box_y2","getter_name":"boundingBoxY2","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"source_type","getter_name":"sourceType","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":22,"references":[],"type":"table","data":{"name":"store_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"string_value","getter_name":"stringValue","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"int_value","getter_name":"intValue","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":23,"references":[],"type":"table","data":{"name":"trashed_local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"orientation","getter_name":"orientation","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id","album_id"]}},{"id":24,"references":[15],"type":"index","data":{"on":15,"name":"idx_lat_lng","sql":"CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)","unique":false,"columns":[]}},{"id":25,"references":[23],"type":"index","data":{"on":23,"name":"idx_trashed_local_asset_checksum","sql":"CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)","unique":false,"columns":[]}},{"id":26,"references":[23],"type":"index","data":{"on":23,"name":"idx_trashed_local_asset_album","sql":"CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)","unique":false,"columns":[]}}]} \ No newline at end of file diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index 7a3a9261ae..b597912d0f 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -137,8 +137,7 @@ NSFaceIDUsageDescription We need to use FaceID to allow access to your locked folder NSLocalNetworkUsageDescription - We need local network permission to connect to the local server using IP address and - allow the casting feature to work + We need local network permission to connect to the local server using IP address and allow the casting feature to work NSLocationAlwaysAndWhenInUseUsageDescription We require this permission to access the local WiFi name for background upload mechanism NSLocationUsageDescription diff --git a/mobile/ios/Runner/Sync/Messages.g.swift b/mobile/ios/Runner/Sync/Messages.g.swift index bbe18e7375..c1cc98014b 100644 --- a/mobile/ios/Runner/Sync/Messages.g.swift +++ b/mobile/ios/Runner/Sync/Messages.g.swift @@ -140,6 +140,9 @@ struct PlatformAsset: Hashable { var durationInSeconds: Int64 var orientation: Int64 var isFavorite: Bool + var adjustmentTime: Int64? = nil + var latitude: Double? = nil + var longitude: Double? = nil // swift-format-ignore: AlwaysUseLowerCamelCase @@ -154,6 +157,9 @@ struct PlatformAsset: Hashable { let durationInSeconds = pigeonVar_list[7] as! Int64 let orientation = pigeonVar_list[8] as! Int64 let isFavorite = pigeonVar_list[9] as! Bool + let adjustmentTime: Int64? = nilOrValue(pigeonVar_list[10]) + let latitude: Double? = nilOrValue(pigeonVar_list[11]) + let longitude: Double? = nilOrValue(pigeonVar_list[12]) return PlatformAsset( id: id, @@ -165,7 +171,10 @@ struct PlatformAsset: Hashable { height: height, durationInSeconds: durationInSeconds, orientation: orientation, - isFavorite: isFavorite + isFavorite: isFavorite, + adjustmentTime: adjustmentTime, + latitude: latitude, + longitude: longitude ) } func toList() -> [Any?] { @@ -180,6 +189,9 @@ struct PlatformAsset: Hashable { durationInSeconds, orientation, isFavorite, + adjustmentTime, + latitude, + longitude, ] } static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool { diff --git a/mobile/ios/Runner/Sync/PHAssetExtensions.swift b/mobile/ios/Runner/Sync/PHAssetExtensions.swift index 2b1ef6ac88..f555d75bd0 100644 --- a/mobile/ios/Runner/Sync/PHAssetExtensions.swift +++ b/mobile/ios/Runner/Sync/PHAssetExtensions.swift @@ -12,7 +12,10 @@ extension PHAsset { height: Int64(pixelHeight), durationInSeconds: Int64(duration), orientation: 0, - isFavorite: isFavorite + isFavorite: isFavorite, + adjustmentTime: adjustmentTimestamp, + latitude: location?.coordinate.latitude, + longitude: location?.coordinate.longitude ) } @@ -23,6 +26,13 @@ extension PHAsset { var filename: String? { return value(forKey: "filename") as? String } + + var adjustmentTimestamp: Int64? { + if let date = value(forKey: "adjustmentTimestamp") as? Date { + return Int64(date.timeIntervalSince1970) + } + return nil + } // This method is expected to be slow as it goes through the asset resources to fetch the originalFilename var originalFilename: String? { diff --git a/mobile/lib/domain/models/asset/local_asset.model.dart b/mobile/lib/domain/models/asset/local_asset.model.dart index 6f2f4c06ba..ba64cc40b8 100644 --- a/mobile/lib/domain/models/asset/local_asset.model.dart +++ b/mobile/lib/domain/models/asset/local_asset.model.dart @@ -5,6 +5,10 @@ class LocalAsset extends BaseAsset { final String? remoteAssetId; final int orientation; + final DateTime? adjustmentTime; + final double? latitude; + final double? longitude; + const LocalAsset({ required this.id, String? remoteId, @@ -19,6 +23,9 @@ class LocalAsset extends BaseAsset { super.isFavorite = false, super.livePhotoVideoId, this.orientation = 0, + this.adjustmentTime, + this.latitude, + this.longitude, }) : remoteAssetId = remoteId; @override @@ -33,6 +40,8 @@ class LocalAsset extends BaseAsset { @override String get heroTag => '${id}_${remoteId ?? checksum}'; + bool get hasCoordinates => latitude != null && longitude != null && latitude != 0 && longitude != 0; + @override String toString() { return '''LocalAsset { @@ -47,6 +56,9 @@ class LocalAsset extends BaseAsset { remoteId: ${remoteId ?? ""} isFavorite: $isFavorite, orientation: $orientation, + adjustmentTime: $adjustmentTime, + latitude: ${latitude ?? ""}, + longitude: ${longitude ?? ""}, }'''; } @@ -55,11 +67,23 @@ class LocalAsset extends BaseAsset { bool operator ==(Object other) { if (other is! LocalAsset) return false; if (identical(this, other)) return true; - return super == other && id == other.id && orientation == other.orientation; + return super == other && + id == other.id && + orientation == other.orientation && + adjustmentTime == other.adjustmentTime && + latitude == other.latitude && + longitude == other.longitude; } @override - int get hashCode => super.hashCode ^ id.hashCode ^ remoteId.hashCode ^ orientation.hashCode; + int get hashCode => + super.hashCode ^ + id.hashCode ^ + remoteId.hashCode ^ + orientation.hashCode ^ + adjustmentTime.hashCode ^ + latitude.hashCode ^ + longitude.hashCode; LocalAsset copyWith({ String? id, @@ -74,6 +98,9 @@ class LocalAsset extends BaseAsset { int? durationInSeconds, bool? isFavorite, int? orientation, + DateTime? adjustmentTime, + double? latitude, + double? longitude, }) { return LocalAsset( id: id ?? this.id, @@ -88,6 +115,9 @@ class LocalAsset extends BaseAsset { durationInSeconds: durationInSeconds ?? this.durationInSeconds, isFavorite: isFavorite ?? this.isFavorite, orientation: orientation ?? this.orientation, + adjustmentTime: adjustmentTime ?? this.adjustmentTime, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, ); } } diff --git a/mobile/lib/domain/models/exif.model.dart b/mobile/lib/domain/models/exif.model.dart index 84456b6dcc..46e2352ac8 100644 --- a/mobile/lib/domain/models/exif.model.dart +++ b/mobile/lib/domain/models/exif.model.dart @@ -37,7 +37,7 @@ class ExifInfo { String get fNumber => f == null ? "" : f!.toStringAsFixed(1); - String get focalLength => mm == null ? "" : mm!.toStringAsFixed(1); + String get focalLength => mm == null ? "" : mm!.toStringAsFixed(3); const ExifInfo({ this.assetId, diff --git a/mobile/lib/domain/services/local_sync.service.dart b/mobile/lib/domain/services/local_sync.service.dart index 04eaf04694..c49ac49cce 100644 --- a/mobile/lib/domain/services/local_sync.service.dart +++ b/mobile/lib/domain/services/local_sync.service.dart @@ -286,11 +286,23 @@ class LocalSyncService { } bool _assetsEqual(LocalAsset a, LocalAsset b) { - return a.updatedAt.isAtSameMomentAs(b.updatedAt) && + if (CurrentPlatform.isAndroid) { + return a.updatedAt.isAtSameMomentAs(b.updatedAt) && + a.createdAt.isAtSameMomentAs(b.createdAt) && + a.width == b.width && + a.height == b.height && + a.durationInSeconds == b.durationInSeconds; + } + + final firstAdjustment = a.adjustmentTime?.millisecondsSinceEpoch ?? 0; + final secondAdjustment = b.adjustmentTime?.millisecondsSinceEpoch ?? 0; + return firstAdjustment == secondAdjustment && a.createdAt.isAtSameMomentAs(b.createdAt) && a.width == b.width && a.height == b.height && - a.durationInSeconds == b.durationInSeconds; + a.durationInSeconds == b.durationInSeconds && + a.latitude == b.latitude && + a.longitude == b.longitude; } bool _albumsEqual(LocalAlbum a, LocalAlbum b) { @@ -376,5 +388,8 @@ extension PlatformToLocalAsset on PlatformAsset { durationInSeconds: durationInSeconds, isFavorite: isFavorite, orientation: orientation, + adjustmentTime: tryFromSecondsSinceEpoch(adjustmentTime, isUtc: true), + latitude: latitude, + longitude: longitude, ); } diff --git a/mobile/lib/infrastructure/entities/exif.entity.dart b/mobile/lib/infrastructure/entities/exif.entity.dart index f858e8b463..2dbe05b9d7 100644 --- a/mobile/lib/infrastructure/entities/exif.entity.dart +++ b/mobile/lib/infrastructure/entities/exif.entity.dart @@ -166,5 +166,6 @@ extension RemoteExifEntityDataDomainEx on RemoteExifEntityData { mm: focalLength?.toDouble(), lens: lens, isFlipped: ExifDtoConverter.isOrientationFlipped(orientation), + exposureSeconds: ExifDtoConverter.exposureTimeToSeconds(exposureTime), ); } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.dart b/mobile/lib/infrastructure/entities/local_asset.entity.dart index 8b253f83a3..d2455b744e 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.dart @@ -16,6 +16,12 @@ class LocalAssetEntity extends Table with DriftDefaultsMixin, AssetEntityMixin { IntColumn get orientation => integer().withDefault(const Constant(0))(); + DateTimeColumn get adjustmentTime => dateTime().nullable()(); + + RealColumn get latitude => real().nullable()(); + + RealColumn get longitude => real().nullable()(); + @override Set get primaryKey => {id}; } @@ -34,5 +40,8 @@ extension LocalAssetEntityDataDomainExtension on LocalAssetEntityData { width: width, remoteId: remoteId, orientation: orientation, + adjustmentTime: adjustmentTime, + latitude: latitude, + longitude: longitude, ); } diff --git a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart index d0fe742463..22219b1e6e 100644 --- a/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart +++ b/mobile/lib/infrastructure/entities/local_asset.entity.drift.dart @@ -21,6 +21,9 @@ typedef $$LocalAssetEntityTableCreateCompanionBuilder = i0.Value checksum, i0.Value isFavorite, i0.Value orientation, + i0.Value adjustmentTime, + i0.Value latitude, + i0.Value longitude, }); typedef $$LocalAssetEntityTableUpdateCompanionBuilder = i1.LocalAssetEntityCompanion Function({ @@ -35,6 +38,9 @@ typedef $$LocalAssetEntityTableUpdateCompanionBuilder = i0.Value checksum, i0.Value isFavorite, i0.Value orientation, + i0.Value adjustmentTime, + i0.Value latitude, + i0.Value longitude, }); class $$LocalAssetEntityTableFilterComposer @@ -101,6 +107,21 @@ class $$LocalAssetEntityTableFilterComposer column: $table.orientation, builder: (column) => i0.ColumnFilters(column), ); + + i0.ColumnFilters get adjustmentTime => $composableBuilder( + column: $table.adjustmentTime, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get latitude => $composableBuilder( + column: $table.latitude, + builder: (column) => i0.ColumnFilters(column), + ); + + i0.ColumnFilters get longitude => $composableBuilder( + column: $table.longitude, + builder: (column) => i0.ColumnFilters(column), + ); } class $$LocalAssetEntityTableOrderingComposer @@ -166,6 +187,21 @@ class $$LocalAssetEntityTableOrderingComposer column: $table.orientation, builder: (column) => i0.ColumnOrderings(column), ); + + i0.ColumnOrderings get adjustmentTime => $composableBuilder( + column: $table.adjustmentTime, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get latitude => $composableBuilder( + column: $table.latitude, + builder: (column) => i0.ColumnOrderings(column), + ); + + i0.ColumnOrderings get longitude => $composableBuilder( + column: $table.longitude, + builder: (column) => i0.ColumnOrderings(column), + ); } class $$LocalAssetEntityTableAnnotationComposer @@ -215,6 +251,17 @@ class $$LocalAssetEntityTableAnnotationComposer column: $table.orientation, builder: (column) => column, ); + + i0.GeneratedColumn get adjustmentTime => $composableBuilder( + column: $table.adjustmentTime, + builder: (column) => column, + ); + + i0.GeneratedColumn get latitude => + $composableBuilder(column: $table.latitude, builder: (column) => column); + + i0.GeneratedColumn get longitude => + $composableBuilder(column: $table.longitude, builder: (column) => column); } class $$LocalAssetEntityTableTableManager @@ -268,6 +315,9 @@ class $$LocalAssetEntityTableTableManager i0.Value checksum = const i0.Value.absent(), i0.Value isFavorite = const i0.Value.absent(), i0.Value orientation = const i0.Value.absent(), + i0.Value adjustmentTime = const i0.Value.absent(), + i0.Value latitude = const i0.Value.absent(), + i0.Value longitude = const i0.Value.absent(), }) => i1.LocalAssetEntityCompanion( name: name, type: type, @@ -280,6 +330,9 @@ class $$LocalAssetEntityTableTableManager checksum: checksum, isFavorite: isFavorite, orientation: orientation, + adjustmentTime: adjustmentTime, + latitude: latitude, + longitude: longitude, ), createCompanionCallback: ({ @@ -294,6 +347,9 @@ class $$LocalAssetEntityTableTableManager i0.Value checksum = const i0.Value.absent(), i0.Value isFavorite = const i0.Value.absent(), i0.Value orientation = const i0.Value.absent(), + i0.Value adjustmentTime = const i0.Value.absent(), + i0.Value latitude = const i0.Value.absent(), + i0.Value longitude = const i0.Value.absent(), }) => i1.LocalAssetEntityCompanion.insert( name: name, type: type, @@ -306,6 +362,9 @@ class $$LocalAssetEntityTableTableManager checksum: checksum, isFavorite: isFavorite, orientation: orientation, + adjustmentTime: adjustmentTime, + latitude: latitude, + longitude: longitude, ), withReferenceMapper: (p0) => p0 .map((e) => (e.readTable(table), i0.BaseReferences(db, table, e))) @@ -473,6 +532,39 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity requiredDuringInsert: false, defaultValue: const i4.Constant(0), ); + static const i0.VerificationMeta _adjustmentTimeMeta = + const i0.VerificationMeta('adjustmentTime'); + @override + late final i0.GeneratedColumn adjustmentTime = + i0.GeneratedColumn( + 'adjustment_time', + aliasedName, + true, + type: i0.DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + static const i0.VerificationMeta _latitudeMeta = const i0.VerificationMeta( + 'latitude', + ); + @override + late final i0.GeneratedColumn latitude = i0.GeneratedColumn( + 'latitude', + aliasedName, + true, + type: i0.DriftSqlType.double, + requiredDuringInsert: false, + ); + static const i0.VerificationMeta _longitudeMeta = const i0.VerificationMeta( + 'longitude', + ); + @override + late final i0.GeneratedColumn longitude = i0.GeneratedColumn( + 'longitude', + aliasedName, + true, + type: i0.DriftSqlType.double, + requiredDuringInsert: false, + ); @override List get $columns => [ name, @@ -486,6 +578,9 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity checksum, isFavorite, orientation, + adjustmentTime, + latitude, + longitude, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -566,6 +661,27 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity ), ); } + if (data.containsKey('adjustment_time')) { + context.handle( + _adjustmentTimeMeta, + adjustmentTime.isAcceptableOrUnknown( + data['adjustment_time']!, + _adjustmentTimeMeta, + ), + ); + } + if (data.containsKey('latitude')) { + context.handle( + _latitudeMeta, + latitude.isAcceptableOrUnknown(data['latitude']!, _latitudeMeta), + ); + } + if (data.containsKey('longitude')) { + context.handle( + _longitudeMeta, + longitude.isAcceptableOrUnknown(data['longitude']!, _longitudeMeta), + ); + } return context; } @@ -624,6 +740,18 @@ class $LocalAssetEntityTable extends i3.LocalAssetEntity i0.DriftSqlType.int, data['${effectivePrefix}orientation'], )!, + adjustmentTime: attachedDatabase.typeMapping.read( + i0.DriftSqlType.dateTime, + data['${effectivePrefix}adjustment_time'], + ), + latitude: attachedDatabase.typeMapping.read( + i0.DriftSqlType.double, + data['${effectivePrefix}latitude'], + ), + longitude: attachedDatabase.typeMapping.read( + i0.DriftSqlType.double, + data['${effectivePrefix}longitude'], + ), ); } @@ -653,6 +781,9 @@ class LocalAssetEntityData extends i0.DataClass final String? checksum; final bool isFavorite; final int orientation; + final DateTime? adjustmentTime; + final double? latitude; + final double? longitude; const LocalAssetEntityData({ required this.name, required this.type, @@ -665,6 +796,9 @@ class LocalAssetEntityData extends i0.DataClass this.checksum, required this.isFavorite, required this.orientation, + this.adjustmentTime, + this.latitude, + this.longitude, }); @override Map toColumns(bool nullToAbsent) { @@ -692,6 +826,15 @@ class LocalAssetEntityData extends i0.DataClass } map['is_favorite'] = i0.Variable(isFavorite); map['orientation'] = i0.Variable(orientation); + if (!nullToAbsent || adjustmentTime != null) { + map['adjustment_time'] = i0.Variable(adjustmentTime); + } + if (!nullToAbsent || latitude != null) { + map['latitude'] = i0.Variable(latitude); + } + if (!nullToAbsent || longitude != null) { + map['longitude'] = i0.Variable(longitude); + } return map; } @@ -714,6 +857,9 @@ class LocalAssetEntityData extends i0.DataClass checksum: serializer.fromJson(json['checksum']), isFavorite: serializer.fromJson(json['isFavorite']), orientation: serializer.fromJson(json['orientation']), + adjustmentTime: serializer.fromJson(json['adjustmentTime']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), ); } @override @@ -733,6 +879,9 @@ class LocalAssetEntityData extends i0.DataClass 'checksum': serializer.toJson(checksum), 'isFavorite': serializer.toJson(isFavorite), 'orientation': serializer.toJson(orientation), + 'adjustmentTime': serializer.toJson(adjustmentTime), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), }; } @@ -748,6 +897,9 @@ class LocalAssetEntityData extends i0.DataClass i0.Value checksum = const i0.Value.absent(), bool? isFavorite, int? orientation, + i0.Value adjustmentTime = const i0.Value.absent(), + i0.Value latitude = const i0.Value.absent(), + i0.Value longitude = const i0.Value.absent(), }) => i1.LocalAssetEntityData( name: name ?? this.name, type: type ?? this.type, @@ -762,6 +914,11 @@ class LocalAssetEntityData extends i0.DataClass checksum: checksum.present ? checksum.value : this.checksum, isFavorite: isFavorite ?? this.isFavorite, orientation: orientation ?? this.orientation, + adjustmentTime: adjustmentTime.present + ? adjustmentTime.value + : this.adjustmentTime, + latitude: latitude.present ? latitude.value : this.latitude, + longitude: longitude.present ? longitude.value : this.longitude, ); LocalAssetEntityData copyWithCompanion(i1.LocalAssetEntityCompanion data) { return LocalAssetEntityData( @@ -782,6 +939,11 @@ class LocalAssetEntityData extends i0.DataClass orientation: data.orientation.present ? data.orientation.value : this.orientation, + adjustmentTime: data.adjustmentTime.present + ? data.adjustmentTime.value + : this.adjustmentTime, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, ); } @@ -798,7 +960,10 @@ class LocalAssetEntityData extends i0.DataClass ..write('id: $id, ') ..write('checksum: $checksum, ') ..write('isFavorite: $isFavorite, ') - ..write('orientation: $orientation') + ..write('orientation: $orientation, ') + ..write('adjustmentTime: $adjustmentTime, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude') ..write(')')) .toString(); } @@ -816,6 +981,9 @@ class LocalAssetEntityData extends i0.DataClass checksum, isFavorite, orientation, + adjustmentTime, + latitude, + longitude, ); @override bool operator ==(Object other) => @@ -831,7 +999,10 @@ class LocalAssetEntityData extends i0.DataClass other.id == this.id && other.checksum == this.checksum && other.isFavorite == this.isFavorite && - other.orientation == this.orientation); + other.orientation == this.orientation && + other.adjustmentTime == this.adjustmentTime && + other.latitude == this.latitude && + other.longitude == this.longitude); } class LocalAssetEntityCompanion @@ -847,6 +1018,9 @@ class LocalAssetEntityCompanion final i0.Value checksum; final i0.Value isFavorite; final i0.Value orientation; + final i0.Value adjustmentTime; + final i0.Value latitude; + final i0.Value longitude; const LocalAssetEntityCompanion({ this.name = const i0.Value.absent(), this.type = const i0.Value.absent(), @@ -859,6 +1033,9 @@ class LocalAssetEntityCompanion this.checksum = const i0.Value.absent(), this.isFavorite = const i0.Value.absent(), this.orientation = const i0.Value.absent(), + this.adjustmentTime = const i0.Value.absent(), + this.latitude = const i0.Value.absent(), + this.longitude = const i0.Value.absent(), }); LocalAssetEntityCompanion.insert({ required String name, @@ -872,6 +1049,9 @@ class LocalAssetEntityCompanion this.checksum = const i0.Value.absent(), this.isFavorite = const i0.Value.absent(), this.orientation = const i0.Value.absent(), + this.adjustmentTime = const i0.Value.absent(), + this.latitude = const i0.Value.absent(), + this.longitude = const i0.Value.absent(), }) : name = i0.Value(name), type = i0.Value(type), id = i0.Value(id); @@ -887,6 +1067,9 @@ class LocalAssetEntityCompanion i0.Expression? checksum, i0.Expression? isFavorite, i0.Expression? orientation, + i0.Expression? adjustmentTime, + i0.Expression? latitude, + i0.Expression? longitude, }) { return i0.RawValuesInsertable({ if (name != null) 'name': name, @@ -900,6 +1083,9 @@ class LocalAssetEntityCompanion if (checksum != null) 'checksum': checksum, if (isFavorite != null) 'is_favorite': isFavorite, if (orientation != null) 'orientation': orientation, + if (adjustmentTime != null) 'adjustment_time': adjustmentTime, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, }); } @@ -915,6 +1101,9 @@ class LocalAssetEntityCompanion i0.Value? checksum, i0.Value? isFavorite, i0.Value? orientation, + i0.Value? adjustmentTime, + i0.Value? latitude, + i0.Value? longitude, }) { return i1.LocalAssetEntityCompanion( name: name ?? this.name, @@ -928,6 +1117,9 @@ class LocalAssetEntityCompanion checksum: checksum ?? this.checksum, isFavorite: isFavorite ?? this.isFavorite, orientation: orientation ?? this.orientation, + adjustmentTime: adjustmentTime ?? this.adjustmentTime, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, ); } @@ -969,6 +1161,15 @@ class LocalAssetEntityCompanion if (orientation.present) { map['orientation'] = i0.Variable(orientation.value); } + if (adjustmentTime.present) { + map['adjustment_time'] = i0.Variable(adjustmentTime.value); + } + if (latitude.present) { + map['latitude'] = i0.Variable(latitude.value); + } + if (longitude.present) { + map['longitude'] = i0.Variable(longitude.value); + } return map; } @@ -985,7 +1186,10 @@ class LocalAssetEntityCompanion ..write('id: $id, ') ..write('checksum: $checksum, ') ..write('isFavorite: $isFavorite, ') - ..write('orientation: $orientation') + ..write('orientation: $orientation, ') + ..write('adjustmentTime: $adjustmentTime, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude') ..write(')')) .toString(); } diff --git a/mobile/lib/infrastructure/repositories/db.repository.dart b/mobile/lib/infrastructure/repositories/db.repository.dart index 548aa2e384..b42aa31550 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.dart @@ -10,7 +10,6 @@ import 'package:immich_mobile/infrastructure/entities/exif.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; -import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/memory.entity.dart'; import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.dart'; @@ -21,6 +20,7 @@ import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.d import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/stack.entity.dart'; import 'package:immich_mobile/infrastructure/entities/store.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/trashed_local_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; import 'package:immich_mobile/infrastructure/entities/user_metadata.entity.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.steps.dart'; @@ -95,7 +95,7 @@ class Drift extends $Drift implements IDatabaseRepository { } @override - int get schemaVersion => 13; + int get schemaVersion => 14; @override MigrationStrategy get migration => MigrationStrategy( @@ -185,6 +185,11 @@ class Drift extends $Drift implements IDatabaseRepository { await m.createIndex(v13.idxTrashedLocalAssetChecksum); await m.createIndex(v13.idxTrashedLocalAssetAlbum); }, + from13To14: (m, v14) async { + await m.addColumn(v14.localAssetEntity, v14.localAssetEntity.adjustmentTime); + await m.addColumn(v14.localAssetEntity, v14.localAssetEntity.latitude); + await m.addColumn(v14.localAssetEntity, v14.localAssetEntity.longitude); + }, ), ); diff --git a/mobile/lib/infrastructure/repositories/db.repository.steps.dart b/mobile/lib/infrastructure/repositories/db.repository.steps.dart index f2d87a7f83..21a3db5274 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.steps.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.steps.dart @@ -5485,6 +5485,462 @@ i1.GeneratedColumn _column_95(String aliasedName) => false, type: i1.DriftSqlType.string, ); + +final class Schema14 extends i0.VersionedSchema { + Schema14({required super.database}) : super(version: 14); + @override + late final List entities = [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + trashedLocalAssetEntity, + idxLatLng, + idxTrashedLocalAssetChecksum, + idxTrashedLocalAssetAlbum, + ]; + late final Shape20 userEntity = Shape20( + source: i0.VersionedTable( + entityName: 'user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_84, + _column_85, + _column_91, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape17 remoteAssetEntity = Shape17( + source: i0.VersionedTable( + entityName: 'remote_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_13, + _column_14, + _column_15, + _column_16, + _column_17, + _column_18, + _column_19, + _column_20, + _column_21, + _column_86, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape3 stackEntity = Shape3( + source: i0.VersionedTable( + entityName: 'stack_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_0, _column_9, _column_5, _column_15, _column_75], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape24 localAssetEntity = Shape24( + source: i0.VersionedTable( + entityName: 'local_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_22, + _column_14, + _column_23, + _column_96, + _column_46, + _column_47, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape9 remoteAlbumEntity = Shape9( + source: i0.VersionedTable( + entityName: 'remote_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_56, + _column_9, + _column_5, + _column_15, + _column_57, + _column_58, + _column_59, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape19 localAlbumEntity = Shape19( + source: i0.VersionedTable( + entityName: 'local_album_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_5, + _column_31, + _column_32, + _column_90, + _column_33, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape22 localAlbumAssetEntity = Shape22( + source: i0.VersionedTable( + entityName: 'local_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_34, _column_35, _column_33], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLocalAssetChecksum = i1.Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + final i1.Index idxRemoteAssetOwnerChecksum = i1.Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + final i1.Index uQRemoteAssetsOwnerChecksum = i1.Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + final i1.Index uQRemoteAssetsOwnerLibraryChecksum = i1.Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + final i1.Index idxRemoteAssetChecksum = i1.Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final Shape21 authUserEntity = Shape21( + source: i0.VersionedTable( + entityName: 'auth_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_1, + _column_3, + _column_2, + _column_84, + _column_85, + _column_92, + _column_93, + _column_7, + _column_94, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape4 userMetadataEntity = Shape4( + source: i0.VersionedTable( + entityName: 'user_metadata_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(user_id, "key")'], + columns: [_column_25, _column_26, _column_27], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape5 partnerEntity = Shape5( + source: i0.VersionedTable( + entityName: 'partner_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(shared_by_id, shared_with_id)'], + columns: [_column_28, _column_29, _column_30], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape8 remoteExifEntity = Shape8( + source: i0.VersionedTable( + entityName: 'remote_exif_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id)'], + columns: [ + _column_36, + _column_37, + _column_38, + _column_39, + _column_40, + _column_41, + _column_11, + _column_10, + _column_42, + _column_43, + _column_44, + _column_45, + _column_46, + _column_47, + _column_48, + _column_49, + _column_50, + _column_51, + _column_52, + _column_53, + _column_54, + _column_55, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape7 remoteAlbumAssetEntity = Shape7( + source: i0.VersionedTable( + entityName: 'remote_album_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, album_id)'], + columns: [_column_36, _column_60], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape10 remoteAlbumUserEntity = Shape10( + source: i0.VersionedTable( + entityName: 'remote_album_user_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(album_id, user_id)'], + columns: [_column_60, _column_25, _column_61], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape11 memoryEntity = Shape11( + source: i0.VersionedTable( + entityName: 'memory_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_18, + _column_15, + _column_8, + _column_62, + _column_63, + _column_64, + _column_65, + _column_66, + _column_67, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape12 memoryAssetEntity = Shape12( + source: i0.VersionedTable( + entityName: 'memory_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(asset_id, memory_id)'], + columns: [_column_36, _column_68], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape14 personEntity = Shape14( + source: i0.VersionedTable( + entityName: 'person_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_9, + _column_5, + _column_15, + _column_1, + _column_69, + _column_71, + _column_72, + _column_73, + _column_74, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape15 assetFaceEntity = Shape15( + source: i0.VersionedTable( + entityName: 'asset_face_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [ + _column_0, + _column_36, + _column_76, + _column_77, + _column_78, + _column_79, + _column_80, + _column_81, + _column_82, + _column_83, + ], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape18 storeEntity = Shape18( + source: i0.VersionedTable( + entityName: 'store_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id)'], + columns: [_column_87, _column_88, _column_89], + attachedDatabase: database, + ), + alias: null, + ); + late final Shape23 trashedLocalAssetEntity = Shape23( + source: i0.VersionedTable( + entityName: 'trashed_local_asset_entity', + withoutRowId: true, + isStrict: true, + tableConstraints: ['PRIMARY KEY(id, album_id)'], + columns: [ + _column_1, + _column_8, + _column_9, + _column_5, + _column_10, + _column_11, + _column_12, + _column_0, + _column_95, + _column_22, + _column_14, + _column_23, + ], + attachedDatabase: database, + ), + alias: null, + ); + final i1.Index idxLatLng = i1.Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); + final i1.Index idxTrashedLocalAssetChecksum = i1.Index( + 'idx_trashed_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)', + ); + final i1.Index idxTrashedLocalAssetAlbum = i1.Index( + 'idx_trashed_local_asset_album', + 'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)', + ); +} + +class Shape24 extends i0.VersionedTable { + Shape24({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get name => + columnsByName['name']! as i1.GeneratedColumn; + i1.GeneratedColumn get type => + columnsByName['type']! as i1.GeneratedColumn; + i1.GeneratedColumn get createdAt => + columnsByName['created_at']! as i1.GeneratedColumn; + i1.GeneratedColumn get updatedAt => + columnsByName['updated_at']! as i1.GeneratedColumn; + i1.GeneratedColumn get width => + columnsByName['width']! as i1.GeneratedColumn; + i1.GeneratedColumn get height => + columnsByName['height']! as i1.GeneratedColumn; + i1.GeneratedColumn get durationInSeconds => + columnsByName['duration_in_seconds']! as i1.GeneratedColumn; + i1.GeneratedColumn get id => + columnsByName['id']! as i1.GeneratedColumn; + i1.GeneratedColumn get checksum => + columnsByName['checksum']! as i1.GeneratedColumn; + i1.GeneratedColumn get isFavorite => + columnsByName['is_favorite']! as i1.GeneratedColumn; + i1.GeneratedColumn get orientation => + columnsByName['orientation']! as i1.GeneratedColumn; + i1.GeneratedColumn get adjustmentTime => + columnsByName['adjustment_time']! as i1.GeneratedColumn; + i1.GeneratedColumn get latitude => + columnsByName['latitude']! as i1.GeneratedColumn; + i1.GeneratedColumn get longitude => + columnsByName['longitude']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_96(String aliasedName) => + i1.GeneratedColumn( + 'adjustment_time', + aliasedName, + true, + type: i1.DriftSqlType.dateTime, + ); i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema2 schema) from1To2, required Future Function(i1.Migrator m, Schema3 schema) from2To3, @@ -5498,6 +5954,7 @@ i0.MigrationStepWithVersion migrationSteps({ required Future Function(i1.Migrator m, Schema11 schema) from10To11, required Future Function(i1.Migrator m, Schema12 schema) from11To12, required Future Function(i1.Migrator m, Schema13 schema) from12To13, + required Future Function(i1.Migrator m, Schema14 schema) from13To14, }) { return (currentVersion, database) async { switch (currentVersion) { @@ -5561,6 +6018,11 @@ i0.MigrationStepWithVersion migrationSteps({ final migrator = i1.Migrator(database, schema); await from12To13(migrator, schema); return 13; + case 13: + final schema = Schema14(database: database); + final migrator = i1.Migrator(database, schema); + await from13To14(migrator, schema); + return 14; default: throw ArgumentError.value('Unknown migration from $currentVersion'); } @@ -5580,6 +6042,7 @@ i1.OnUpgrade stepByStep({ required Future Function(i1.Migrator m, Schema11 schema) from10To11, required Future Function(i1.Migrator m, Schema12 schema) from11To12, required Future Function(i1.Migrator m, Schema13 schema) from12To13, + required Future Function(i1.Migrator m, Schema14 schema) from13To14, }) => i0.VersionedSchema.stepByStepHelper( step: migrationSteps( from1To2: from1To2, @@ -5594,5 +6057,6 @@ i1.OnUpgrade stepByStep({ from10To11: from10To11, from11To12: from11To12, from12To13: from12To13, + from13To14: from13To14, ), ); diff --git a/mobile/lib/infrastructure/repositories/local_album.repository.dart b/mobile/lib/infrastructure/repositories/local_album.repository.dart index 59546a4539..9d4c9bc496 100644 --- a/mobile/lib/infrastructure/repositories/local_album.repository.dart +++ b/mobile/lib/infrastructure/repositories/local_album.repository.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/models/album/local_album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; @@ -244,7 +246,56 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { return query.map((row) => row.readTable(_db.localAssetEntity).toDto()).get(); } - Future _upsertAssets(Iterable localAssets) { + Future Function(Iterable) get _upsertAssets => + CurrentPlatform.isIOS ? _upsertAssetsDarwin : _upsertAssetsAndroid; + + Future _upsertAssetsDarwin(Iterable localAssets) async { + if (localAssets.isEmpty) { + return Future.value(); + } + + // Reset checksum if asset changed + await _db.batch((batch) async { + for (final asset in localAssets) { + final companion = LocalAssetEntityCompanion( + checksum: const Value(null), + adjustmentTime: Value(asset.adjustmentTime), + ); + batch.update( + _db.localAssetEntity, + companion, + where: (row) => row.id.equals(asset.id) & row.adjustmentTime.isNotExp(Variable(asset.adjustmentTime)), + ); + } + }); + + return _db.batch((batch) async { + for (final asset in localAssets) { + final companion = LocalAssetEntityCompanion.insert( + name: asset.name, + type: asset.type, + createdAt: Value(asset.createdAt), + updatedAt: Value(asset.updatedAt), + width: Value(asset.width), + height: Value(asset.height), + durationInSeconds: Value(asset.durationInSeconds), + id: asset.id, + orientation: Value(asset.orientation), + isFavorite: Value(asset.isFavorite), + latitude: Value(asset.latitude), + longitude: Value(asset.longitude), + adjustmentTime: Value(asset.adjustmentTime), + ); + batch.insert<$LocalAssetEntityTable, LocalAssetEntityData>( + _db.localAssetEntity, + companion.copyWith(checksum: const Value(null)), + onConflict: DoUpdate((old) => companion), + ); + } + }); + } + + Future _upsertAssetsAndroid(Iterable localAssets) async { if (localAssets.isEmpty) { return Future.value(); } @@ -260,6 +311,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository { height: Value(asset.height), durationInSeconds: Value(asset.durationInSeconds), id: asset.id, + checksum: const Value(null), orientation: Value(asset.orientation), isFavorite: Value(asset.isFavorite), ); diff --git a/mobile/lib/infrastructure/utils/exif.converter.dart b/mobile/lib/infrastructure/utils/exif.converter.dart index eb9945f454..50639e8e42 100644 --- a/mobile/lib/infrastructure/utils/exif.converter.dart +++ b/mobile/lib/infrastructure/utils/exif.converter.dart @@ -22,7 +22,7 @@ abstract final class ExifDtoConverter { f: dto.fNumber?.toDouble(), mm: dto.focalLength?.toDouble(), iso: dto.iso?.toInt(), - exposureSeconds: _exposureTimeToSeconds(dto.exposureTime), + exposureSeconds: exposureTimeToSeconds(dto.exposureTime), ); } @@ -36,15 +36,15 @@ abstract final class ExifDtoConverter { return isRotated90CW || isRotated270CW; } - static double? _exposureTimeToSeconds(String? s) { - if (s == null) { + static double? exposureTimeToSeconds(String? second) { + if (second == null) { return null; } - double? value = double.tryParse(s); + double? value = double.tryParse(second); if (value != null) { return value; } - final parts = s.split("/"); + final parts = second.split("/"); if (parts.length == 2) { final numerator = double.tryParse(parts.firstOrNull ?? "-"); final denominator = double.tryParse(parts.lastOrNull ?? "-"); diff --git a/mobile/lib/pages/backup/drift_upload_detail.page.dart b/mobile/lib/pages/backup/drift_upload_detail.page.dart index 1b8aa57eaa..612b6a8111 100644 --- a/mobile/lib/pages/backup/drift_upload_detail.page.dart +++ b/mobile/lib/pages/backup/drift_upload_detail.page.dart @@ -98,7 +98,7 @@ class DriftUploadDetailPage extends ConsumerWidget { ), ), Text( - 'Tap for more details', + "backup_upload_details_page_more_details".t(context: context), style: context.textTheme.bodySmall?.copyWith( color: context.colorScheme.onSurface.withValues(alpha: 0.6), ), @@ -239,14 +239,20 @@ class FileDetailDialog extends ConsumerWidget { const SizedBox(height: 24), if (asset != null) ...[ _buildInfoSection(context, [ - _buildInfoRow(context, "Filename", path.basename(uploadStatus.filename)), - _buildInfoRow(context, "Local ID", asset.id), - _buildInfoRow(context, "File Size", formatHumanReadableBytes(uploadStatus.fileSize, 2)), - if (asset.width != null) _buildInfoRow(context, "Width", "${asset.width}px"), - if (asset.height != null) _buildInfoRow(context, "Height", "${asset.height}px"), - _buildInfoRow(context, "Created At", asset.createdAt.toString()), - _buildInfoRow(context, "Updated At", asset.updatedAt.toString()), - if (asset.checksum != null) _buildInfoRow(context, "Checksum", asset.checksum!), + _buildInfoRow(context, "filename".t(context: context), path.basename(uploadStatus.filename)), + _buildInfoRow(context, "local_id".t(context: context), asset.id), + _buildInfoRow( + context, + "file_size".t(context: context), + formatHumanReadableBytes(uploadStatus.fileSize, 2), + ), + if (asset.width != null) _buildInfoRow(context, "width".t(context: context), "${asset.width}px"), + if (asset.height != null) + _buildInfoRow(context, "height".t(context: context), "${asset.height}px"), + _buildInfoRow(context, "created_at".t(context: context), asset.createdAt.toString()), + _buildInfoRow(context, "updated_at".t(context: context), asset.updatedAt.toString()), + if (asset.checksum != null) + _buildInfoRow(context, "checksum".t(context: context), asset.checksum!), ]), ], ], diff --git a/mobile/lib/pages/search/map/map_location_picker.page.dart b/mobile/lib/pages/search/map/map_location_picker.page.dart index 94e6627c98..a2c927c6bd 100644 --- a/mobile/lib/pages/search/map/map_location_picker.page.dart +++ b/mobile/lib/pages/search/map/map_location_picker.page.dart @@ -49,7 +49,7 @@ class MapLocationPickerPage extends HookConsumerWidget { var currentLatLng = LatLng(currentLocation.latitude, currentLocation.longitude); selectedLatLng.value = currentLatLng; - await controller.value?.animateCamera(CameraUpdate.newLatLng(currentLatLng)); + await controller.value?.animateCamera(CameraUpdate.newLatLngZoom(currentLatLng, 12)); } return MapThemeOverride( @@ -66,7 +66,10 @@ class MapLocationPickerPage extends HookConsumerWidget { borderRadius: BorderRadius.only(bottomLeft: Radius.circular(40), bottomRight: Radius.circular(40)), ), child: MapLibreMap( - initialCameraPosition: CameraPosition(target: initialLatLng, zoom: 12), + initialCameraPosition: CameraPosition( + target: initialLatLng, + zoom: (initialLatLng.latitude == 0 && initialLatLng.longitude == 0) ? 1 : 12, + ), styleString: style, onMapCreated: (mapController) => controller.value = mapController, onStyleLoadedCallback: onStyleLoaded, diff --git a/mobile/lib/platform/native_sync_api.g.dart b/mobile/lib/platform/native_sync_api.g.dart index 34ed7a5e2b..1c3b4b083e 100644 --- a/mobile/lib/platform/native_sync_api.g.dart +++ b/mobile/lib/platform/native_sync_api.g.dart @@ -41,6 +41,9 @@ class PlatformAsset { required this.durationInSeconds, required this.orientation, required this.isFavorite, + this.adjustmentTime, + this.latitude, + this.longitude, }); String id; @@ -63,8 +66,28 @@ class PlatformAsset { bool isFavorite; + int? adjustmentTime; + + double? latitude; + + double? longitude; + List _toList() { - return [id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite]; + return [ + id, + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + orientation, + isFavorite, + adjustmentTime, + latitude, + longitude, + ]; } Object encode() { @@ -84,6 +107,9 @@ class PlatformAsset { durationInSeconds: result[7]! as int, orientation: result[8]! as int, isFavorite: result[9]! as bool, + adjustmentTime: result[10] as int?, + latitude: result[11] as double?, + longitude: result[12] as double?, ); } diff --git a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart deleted file mode 100644 index 491c38e7a8..0000000000 --- a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart +++ /dev/null @@ -1,173 +0,0 @@ -import 'dart:async'; - -import 'package:auto_route/auto_route.dart'; -import 'package:drift/drift.dart' hide Column; -import 'package:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; -import 'package:immich_mobile/providers/background_sync.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/platform.provider.dart'; -import 'package:immich_mobile/providers/user.provider.dart'; -import 'package:immich_mobile/routing/router.dart'; -import 'package:logging/logging.dart'; - -final _features = [ - _Feature( - name: 'Main Timeline', - icon: Icons.timeline_rounded, - onTap: (ctx, _) => ctx.pushRoute(const TabShellRoute()), - ), - _Feature( - name: 'Selection Mode Timeline', - icon: Icons.developer_mode_rounded, - onTap: (ctx, ref) async { - final user = ref.watch(currentUserProvider); - if (user == null) { - return Future.value(); - } - - final assets = await ref.read(remoteAssetRepositoryProvider).getSome(user.id); - - final selectedAssets = await ctx.pushRoute>( - DriftAssetSelectionTimelineRoute(lockedSelectionAssets: assets.toSet()), - ); - - Logger("FeaturesInDevelopment").fine("Selected ${selectedAssets?.length ?? 0} assets"); - - return Future.value(); - }, - ), - _Feature(name: '', icon: Icons.vertical_align_center_sharp, onTap: (_, __) => Future.value()), - _Feature( - name: 'Sync Local', - icon: Icons.photo_album_rounded, - onTap: (_, ref) => ref.read(backgroundSyncProvider).syncLocal(), - ), - _Feature( - name: 'Sync Local Full (1)', - icon: Icons.photo_library_rounded, - onTap: (_, ref) => ref.read(backgroundSyncProvider).syncLocal(full: true), - ), - _Feature( - name: 'Hash Local Assets (2)', - icon: Icons.numbers_outlined, - onTap: (_, ref) => ref.read(backgroundSyncProvider).hashAssets(), - ), - _Feature( - name: 'Sync Remote (3)', - icon: Icons.refresh_rounded, - onTap: (_, ref) => ref.read(backgroundSyncProvider).syncRemote(), - ), - _Feature( - name: 'WAL Checkpoint', - icon: Icons.save_rounded, - onTap: (_, ref) => ref.read(driftProvider).customStatement("pragma wal_checkpoint(truncate)"), - ), - _Feature(name: '', icon: Icons.vertical_align_center_sharp, onTap: (_, __) => Future.value()), - _Feature( - name: 'Clear Delta Checkpoint', - icon: Icons.delete_rounded, - onTap: (_, ref) => ref.read(nativeSyncApiProvider).clearSyncCheckpoint(), - ), - _Feature( - name: 'Clear Local Data', - style: const TextStyle(color: Colors.orange, fontWeight: FontWeight.bold), - icon: Icons.delete_forever_rounded, - onTap: (_, ref) async { - final db = ref.read(driftProvider); - await db.localAssetEntity.deleteAll(); - await db.localAlbumEntity.deleteAll(); - await db.localAlbumAssetEntity.deleteAll(); - }, - ), - _Feature( - name: 'Clear Remote Data', - style: const TextStyle(color: Colors.orange, fontWeight: FontWeight.bold), - icon: Icons.delete_sweep_rounded, - onTap: (_, ref) async { - final db = ref.read(driftProvider); - await db.remoteAssetEntity.deleteAll(); - await db.remoteExifEntity.deleteAll(); - await db.remoteAlbumEntity.deleteAll(); - await db.remoteAlbumUserEntity.deleteAll(); - await db.remoteAlbumAssetEntity.deleteAll(); - await db.memoryEntity.deleteAll(); - await db.memoryAssetEntity.deleteAll(); - await db.stackEntity.deleteAll(); - await db.personEntity.deleteAll(); - await db.assetFaceEntity.deleteAll(); - }, - ), - _Feature( - name: 'Local Media Summary', - style: const TextStyle(color: Colors.indigo, fontWeight: FontWeight.bold), - icon: Icons.table_chart_rounded, - onTap: (ctx, _) => ctx.pushRoute(const LocalMediaSummaryRoute()), - ), - _Feature( - name: 'Remote Media Summary', - style: const TextStyle(color: Colors.indigo, fontWeight: FontWeight.bold), - icon: Icons.summarize_rounded, - onTap: (ctx, _) => ctx.pushRoute(const RemoteMediaSummaryRoute()), - ), - _Feature( - name: 'Reset Sqlite', - icon: Icons.table_view_rounded, - style: const TextStyle(color: Colors.red, fontWeight: FontWeight.bold), - onTap: (_, ref) async { - final drift = ref.read(driftProvider); - // ignore: invalid_use_of_protected_member, invalid_use_of_visible_for_testing_member - final migrator = drift.createMigrator(); - for (final entity in drift.allSchemaEntities) { - await migrator.drop(entity); - await migrator.create(entity); - } - }, - ), -]; - -@RoutePage() -class FeatInDevPage extends StatelessWidget { - const FeatInDevPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text('features_in_development'.tr()), centerTitle: true), - body: Column( - children: [ - Flexible( - flex: 1, - child: ListView.builder( - itemBuilder: (_, index) { - final feat = _features[index]; - return Consumer( - builder: (ctx, ref, _) => ListTile( - title: Text(feat.name, style: feat.style), - trailing: Icon(feat.icon), - visualDensity: VisualDensity.compact, - onTap: () => unawaited(feat.onTap(ctx, ref)), - ), - ); - }, - itemCount: _features.length, - ), - ), - const Divider(height: 0), - ], - ), - ); - } -} - -class _Feature { - const _Feature({required this.name, required this.icon, required this.onTap, this.style}); - - final String name; - final IconData icon; - final TextStyle? style; - final Future Function(BuildContext, WidgetRef _) onTap; -} diff --git a/mobile/lib/presentation/pages/dev/ui_showcase.page.dart b/mobile/lib/presentation/pages/dev/ui_showcase.page.dart new file mode 100644 index 0000000000..01fe928478 --- /dev/null +++ b/mobile/lib/presentation/pages/dev/ui_showcase.page.dart @@ -0,0 +1,51 @@ +import 'package:auto_route/auto_route.dart'; +import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_ui/immich_ui.dart'; + +List _showcaseBuilder(Function(ImmichVariant variant, ImmichColor color) builder) { + final children = []; + + final items = [ + (variant: ImmichVariant.filled, title: "Filled Variant"), + (variant: ImmichVariant.ghost, title: "Ghost Variant"), + ]; + + for (final (:variant, :title) in items) { + children.add(Text(title)); + children.add(Row(spacing: 10, children: [for (var color in ImmichColor.values) builder(variant, color)])); + } + + return children; +} + +@RoutePage() +class ImmichUIShowcasePage extends StatelessWidget { + const ImmichUIShowcasePage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Immich UI Showcase')), + body: Padding( + padding: const EdgeInsets.all(20), + child: SingleChildScrollView( + child: Column( + spacing: 10, + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text("IconButton", style: context.textTheme.titleLarge), + ..._showcaseBuilder( + (variant, color) => + ImmichIconButton(icon: Icons.favorite, color: color, variant: variant, onTap: () {}), + ), + Text("CloseButton", style: context.textTheme.titleLarge), + ..._showcaseBuilder((variant, color) => ImmichCloseButton(color: color, variant: variant, onTap: () {})), + ], + ), + ), + ), + ); + } +} diff --git a/mobile/lib/presentation/pages/drift_activities.page.dart b/mobile/lib/presentation/pages/drift_activities.page.dart index b92d429aa1..ac0cd7f309 100644 --- a/mobile/lib/presentation/pages/drift_activities.page.dart +++ b/mobile/lib/presentation/pages/drift_activities.page.dart @@ -37,7 +37,7 @@ class DriftActivitiesPage extends HookConsumerWidget { child: Scaffold( appBar: AppBar( title: Text(album.name), - actions: [const LikeActivityActionButton(menuItem: true)], + actions: [const LikeActivityActionButton(iconOnly: true)], actionsPadding: const EdgeInsets.only(right: 8), ), body: activities.widgetWhen( diff --git a/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart b/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart index 752ab5ba37..2b7034770b 100644 --- a/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart +++ b/mobile/lib/presentation/pages/drift_asset_troubleshoot.page.dart @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/providers/infrastructure/asset.provider.dart'; @RoutePage() @@ -129,6 +130,15 @@ class _AssetPropertiesSectionState extends ConsumerState<_AssetPropertiesSection properties.insert(4, _PropertyItem(label: 'Orientation', value: asset.orientation.toString())); final albums = await ref.read(assetServiceProvider).getSourceAlbums(asset.id); properties.add(_PropertyItem(label: 'Album', value: albums.map((a) => a.name).join(', '))); + if (CurrentPlatform.isIOS) { + properties.add(_PropertyItem(label: 'Adjustment Time', value: asset.adjustmentTime?.toString())); + } + properties.add( + _PropertyItem( + label: 'GPS Coordinates', + value: asset.hasCoordinates ? '${asset.latitude}, ${asset.longitude}' : null, + ), + ); } Future _addRemoteAssetProperties(RemoteAsset asset) async { diff --git a/mobile/lib/presentation/pages/drift_create_album.page.dart b/mobile/lib/presentation/pages/drift_create_album.page.dart index 57e5cb09a9..f1cbdb13ff 100644 --- a/mobile/lib/presentation/pages/drift_create_album.page.dart +++ b/mobile/lib/presentation/pages/drift_create_album.page.dart @@ -27,8 +27,19 @@ class _DriftCreateAlbumPageState extends ConsumerState { bool isAlbumTitleTextFieldFocus = false; Set selectedAssets = {}; + @override + void initState() { + super.initState(); + albumTitleController.addListener(_onTitleChanged); + } + + void _onTitleChanged() { + setState(() {}); + } + @override void dispose() { + albumTitleController.removeListener(_onTitleChanged); albumTitleController.dispose(); albumDescriptionController.dispose(); albumTitleTextFieldFocusNode.dispose(); diff --git a/mobile/lib/presentation/pages/editing/drift_crop.page.dart b/mobile/lib/presentation/pages/editing/drift_crop.page.dart index d8219e3b3c..1692140cd2 100644 --- a/mobile/lib/presentation/pages/editing/drift_crop.page.dart +++ b/mobile/lib/presentation/pages/editing/drift_crop.page.dart @@ -9,6 +9,7 @@ import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/routing/router.dart'; import 'package:immich_mobile/utils/hooks/crop_controller_hook.dart'; +import 'package:immich_ui/immich_ui.dart'; /// A widget for cropping an image. /// This widget uses [HookWidget] to manage its lifecycle and state. It allows @@ -30,11 +31,13 @@ class DriftCropImagePage extends HookWidget { appBar: AppBar( backgroundColor: context.scaffoldBackgroundColor, title: Text("crop".tr()), - leading: CloseButton(color: context.primaryColor), + leading: const ImmichCloseButton(), actions: [ - IconButton( - icon: Icon(Icons.done_rounded, color: context.primaryColor, size: 24), - onPressed: () async { + ImmichIconButton( + icon: Icons.done_rounded, + color: ImmichColor.primary, + variant: ImmichVariant.ghost, + onTap: () async { final croppedImage = await cropController.croppedImage(); unawaited(context.pushRoute(DriftEditImageRoute(asset: asset, image: croppedImage, isEdited: true))); }, @@ -72,17 +75,17 @@ class DriftCropImagePage extends HookWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - IconButton( - icon: Icon(Icons.rotate_left, color: context.themeData.iconTheme.color), - onPressed: () { - cropController.rotateLeft(); - }, + ImmichIconButton( + icon: Icons.rotate_left, + variant: ImmichVariant.ghost, + color: ImmichColor.secondary, + onTap: () => cropController.rotateLeft(), ), - IconButton( - icon: Icon(Icons.rotate_right, color: context.themeData.iconTheme.color), - onPressed: () { - cropController.rotateRight(); - }, + ImmichIconButton( + icon: Icons.rotate_right, + variant: ImmichVariant.ghost, + color: ImmichColor.secondary, + onTap: () => cropController.rotateRight(), ), ], ), diff --git a/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart index 71fedf1258..23cd19f363 100644 --- a/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/add_action_button.widget.dart @@ -21,12 +21,36 @@ import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_shee enum AddToMenuItem { album, archive, unarchive, lockedFolder } -class AddActionButton extends ConsumerWidget { - const AddActionButton({super.key}); +class AddActionButton extends ConsumerStatefulWidget { + const AddActionButton({super.key, this.originalTheme}); - Future _showAddOptions(BuildContext context, WidgetRef ref) async { + final ThemeData? originalTheme; + + @override + ConsumerState createState() => _AddActionButtonState(); +} + +class _AddActionButtonState extends ConsumerState { + void _handleMenuSelection(AddToMenuItem selected) { + switch (selected) { + case AddToMenuItem.album: + _openAlbumSelector(); + break; + case AddToMenuItem.archive: + performArchiveAction(context, ref, source: ActionSource.viewer); + break; + case AddToMenuItem.unarchive: + performUnArchiveAction(context, ref, source: ActionSource.viewer); + break; + case AddToMenuItem.lockedFolder: + performMoveToLockFolderAction(context, ref, source: ActionSource.viewer); + break; + } + } + + List _buildMenuChildren() { final asset = ref.read(currentAssetNotifier); - if (asset == null) return; + if (asset == null) return []; final user = ref.read(currentUserProvider); final isOwner = asset is RemoteAsset && asset.ownerId == user?.id; @@ -35,84 +59,50 @@ class AddActionButton extends ConsumerWidget { final hasRemote = asset is RemoteAsset; final showArchive = isOwner && !isInLockedView && hasRemote && !isArchived; final showUnarchive = isOwner && !isInLockedView && hasRemote && isArchived; - final menuItemHeight = 30.0; - final List> items = [ - PopupMenuItem( - enabled: false, - textStyle: context.textTheme.labelMedium, - height: 40, - child: Text("add_to_bottom_bar".tr()), + return [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text("add_to_bottom_bar".tr(), style: context.textTheme.labelMedium), ), - PopupMenuItem( - height: menuItemHeight, - value: AddToMenuItem.album, - child: ListTile(leading: const Icon(Icons.photo_album_outlined), title: Text("album".tr())), + BaseActionButton( + iconData: Icons.photo_album_outlined, + label: "album".tr(), + menuItem: true, + onPressed: () => _handleMenuSelection(AddToMenuItem.album), ), - const PopupMenuDivider(), - PopupMenuItem(enabled: false, textStyle: context.textTheme.labelMedium, height: 40, child: Text("move_to".tr())), + if (isOwner) ...[ + const Divider(), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + child: Text("move_to".tr(), style: context.textTheme.labelMedium), + ), if (showArchive) - PopupMenuItem( - height: menuItemHeight, - value: AddToMenuItem.archive, - child: ListTile(leading: const Icon(Icons.archive_outlined), title: Text("archive".tr())), + BaseActionButton( + iconData: Icons.archive_outlined, + label: "archive".tr(), + menuItem: true, + onPressed: () => _handleMenuSelection(AddToMenuItem.archive), ), if (showUnarchive) - PopupMenuItem( - height: menuItemHeight, - value: AddToMenuItem.unarchive, - child: ListTile(leading: const Icon(Icons.unarchive_outlined), title: Text("unarchive".tr())), + BaseActionButton( + iconData: Icons.unarchive_outlined, + label: "unarchive".tr(), + menuItem: true, + onPressed: () => _handleMenuSelection(AddToMenuItem.unarchive), ), - PopupMenuItem( - height: menuItemHeight, - value: AddToMenuItem.lockedFolder, - child: ListTile(leading: const Icon(Icons.lock_outline), title: Text("locked_folder".tr())), + BaseActionButton( + iconData: Icons.lock_outline, + label: "locked_folder".tr(), + menuItem: true, + onPressed: () => _handleMenuSelection(AddToMenuItem.lockedFolder), ), ], ]; - - final AddToMenuItem? selected = await showMenu( - context: context, - color: context.themeData.scaffoldBackgroundColor, - position: _menuPosition(context), - items: items, - popUpAnimationStyle: AnimationStyle.noAnimation, - ); - - if (selected == null) { - return; - } - - switch (selected) { - case AddToMenuItem.album: - _openAlbumSelector(context, ref); - break; - case AddToMenuItem.archive: - await performArchiveAction(context, ref, source: ActionSource.viewer); - break; - case AddToMenuItem.unarchive: - await performUnArchiveAction(context, ref, source: ActionSource.viewer); - break; - case AddToMenuItem.lockedFolder: - await performMoveToLockFolderAction(context, ref, source: ActionSource.viewer); - break; - } } - RelativeRect _menuPosition(BuildContext context) { - final renderObject = context.findRenderObject(); - if (renderObject is! RenderBox) { - return RelativeRect.fill; - } - - final size = renderObject.size; - final position = renderObject.localToGlobal(Offset.zero); - - return RelativeRect.fromLTRB(position.dx, position.dy - size.height - 200, position.dx + size.width, position.dy); - } - - void _openAlbumSelector(BuildContext context, WidgetRef ref) { + void _openAlbumSelector() { final currentAsset = ref.read(currentAssetNotifier); if (currentAsset == null) { ImmichToast.show(context: context, msg: "Cannot load asset information.", toastType: ToastType.error); @@ -120,7 +110,8 @@ class AddActionButton extends ConsumerWidget { } final List slivers = [ - AlbumSelector(onAlbumSelected: (album) => _addCurrentAssetToAlbum(context, ref, album)), + const CreateAlbumButton(), + AlbumSelector(onAlbumSelected: (album) => _addCurrentAssetToAlbum(album)), ]; showModalBottomSheet( @@ -141,7 +132,7 @@ class AddActionButton extends ConsumerWidget { ); } - Future _addCurrentAssetToAlbum(BuildContext context, WidgetRef ref, RemoteAlbum album) async { + Future _addCurrentAssetToAlbum(RemoteAlbum album) async { final latest = ref.read(currentAssetNotifier); if (latest == null) { @@ -165,6 +156,9 @@ class AddActionButton extends ConsumerWidget { context: context, msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}), ); + + // Invalidate using the asset's remote ID to refresh the "Appears in" list + ref.invalidate(albumsContainingAssetProvider(latest.remoteId!)); } if (!context.mounted) { @@ -174,17 +168,38 @@ class AddActionButton extends ConsumerWidget { } @override - Widget build(BuildContext context, WidgetRef ref) { + Widget build(BuildContext context) { final asset = ref.watch(currentAssetNotifier); if (asset == null) { return const SizedBox.shrink(); } - return Builder( - builder: (buttonContext) { + + final themeData = widget.originalTheme ?? context.themeData; + + return MenuAnchor( + consumeOutsideTap: true, + style: MenuStyle( + backgroundColor: WidgetStatePropertyAll(themeData.scaffoldBackgroundColor), + surfaceTintColor: const WidgetStatePropertyAll(Colors.grey), + elevation: const WidgetStatePropertyAll(4), + shape: const WidgetStatePropertyAll( + RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))), + ), + padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(vertical: 6)), + ), + menuChildren: widget.originalTheme != null + ? [ + Theme( + data: widget.originalTheme!, + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: _buildMenuChildren()), + ), + ] + : _buildMenuChildren(), + builder: (context, controller, child) { return BaseActionButton( iconData: Icons.add, label: "add_to_bottom_bar".tr(), - onPressed: () => _showAddOptions(buttonContext, ref), + onPressed: () => controller.isOpen ? controller.close() : controller.open(), ); }, ); diff --git a/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart index cb2581bc6d..b68ab69b26 100644 --- a/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart @@ -9,8 +9,10 @@ import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; class AdvancedInfoActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const AdvancedInfoActionButton({super.key, required this.source}); + const AdvancedInfoActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -26,6 +28,8 @@ class AdvancedInfoActionButton extends ConsumerWidget { maxWidth: 115.0, iconData: Icons.help_outline_rounded, label: "troubleshoot".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart index 4ba877bcba..7c7e96c1c5 100644 --- a/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/archive_action_button.widget.dart @@ -35,8 +35,10 @@ Future performArchiveAction(BuildContext context, WidgetRef ref, {required class ArchiveActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const ArchiveActionButton({super.key, required this.source}); + const ArchiveActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); Future _onTap(BuildContext context, WidgetRef ref) async { await performArchiveAction(context, ref, source: source); @@ -47,6 +49,8 @@ class ArchiveActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.archive_outlined, label: "to_archive".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart index 5ec6c8bc54..675b5bf219 100644 --- a/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/base_action_button.widget.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -class BaseActionButton extends StatelessWidget { +class BaseActionButton extends ConsumerWidget { const BaseActionButton({ super.key, required this.label, @@ -11,6 +12,7 @@ class BaseActionButton extends StatelessWidget { this.onLongPressed, this.maxWidth = 90.0, this.minWidth, + this.iconOnly = false, this.menuItem = false, }); @@ -19,25 +21,42 @@ class BaseActionButton extends StatelessWidget { final Color? iconColor; final double maxWidth; final double? minWidth; + + /// When true, renders only an IconButton without text label + final bool iconOnly; + + /// When true, renders as a MenuItemButton for use in MenuAnchor menus final bool menuItem; final void Function()? onPressed; final void Function()? onLongPressed; @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final miniWidth = minWidth ?? (context.isMobile ? context.width / 4.5 : 75.0); final iconTheme = IconTheme.of(context); final iconSize = iconTheme.size ?? 24.0; final iconColor = this.iconColor ?? iconTheme.color ?? context.themeData.iconTheme.color; final textColor = context.themeData.textTheme.labelLarge?.color; - if (menuItem) { + if (iconOnly) { return IconButton( onPressed: onPressed, icon: Icon(iconData, size: iconSize, color: iconColor), ); } + if (menuItem) { + final theme = context.themeData; + final effectiveIconColor = iconColor ?? theme.iconTheme.color ?? theme.colorScheme.onSurfaceVariant; + + return MenuItemButton( + style: MenuItemButton.styleFrom(alignment: Alignment.centerLeft, padding: const EdgeInsets.all(16)), + leadingIcon: Icon(iconData, color: effectiveIconColor), + onPressed: onPressed, + child: Text(label, style: theme.textTheme.labelLarge?.copyWith(fontSize: 16)), + ); + } + return ConstrainedBox( constraints: BoxConstraints(maxWidth: maxWidth), child: MaterialButton( diff --git a/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart index 26b8ba6f47..7a4f84fb4f 100644 --- a/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/cast_action_button.widget.dart @@ -7,8 +7,9 @@ import 'package:immich_mobile/providers/cast.provider.dart'; import 'package:immich_mobile/widgets/asset_viewer/cast_dialog.dart'; class CastActionButton extends ConsumerWidget { - const CastActionButton({super.key, this.menuItem = true}); + const CastActionButton({super.key, this.iconOnly = false, this.menuItem = false}); + final bool iconOnly; final bool menuItem; @override @@ -22,6 +23,7 @@ class CastActionButton extends ConsumerWidget { onPressed: () { showDialog(context: context, builder: (context) => const CastDialog()); }, + iconOnly: iconOnly, menuItem: menuItem, ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart index 8b82e5c839..94ee1b2343 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_action_button.widget.dart @@ -18,7 +18,15 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class DeleteActionButton extends ConsumerWidget { final ActionSource source; final bool showConfirmation; - const DeleteActionButton({super.key, required this.source, this.showConfirmation = false}); + final bool iconOnly; + final bool menuItem; + const DeleteActionButton({ + super.key, + required this.source, + this.showConfirmation = false, + this.iconOnly = false, + this.menuItem = false, + }); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -74,6 +82,8 @@ class DeleteActionButton extends ConsumerWidget { maxWidth: 110.0, iconData: Icons.delete_sweep_outlined, label: "delete".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart index 5d8ea8671c..2e15de49df 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_local_action_button.widget.dart @@ -14,8 +14,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; /// - Prompt to delete the asset locally class DeleteLocalActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const DeleteLocalActionButton({super.key, required this.source}); + const DeleteLocalActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -55,6 +57,8 @@ class DeleteLocalActionButton extends ConsumerWidget { maxWidth: 95.0, iconData: Icons.no_cell_outlined, label: "control_bottom_app_bar_delete_from_local".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart index a0191e2407..2dd9a265ed 100644 --- a/mobile/lib/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart @@ -15,8 +15,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; /// - Prompt to delete the asset locally class DeletePermanentActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const DeletePermanentActionButton({super.key, required this.source}); + const DeletePermanentActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -51,6 +53,8 @@ class DeletePermanentActionButton extends ConsumerWidget { maxWidth: 110.0, iconData: Icons.delete_forever, label: "delete_permanently".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart index cb898f069a..a5129b643a 100644 --- a/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/download_action_button.widget.dart @@ -10,8 +10,9 @@ import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; class DownloadActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; final bool menuItem; - const DownloadActionButton({super.key, required this.source, this.menuItem = false}); + const DownloadActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref, BackgroundSyncManager backgroundSyncManager) async { if (!context.mounted) { @@ -38,6 +39,7 @@ class DownloadActionButton extends ConsumerWidget { iconData: Icons.download, maxWidth: 95, label: "download".t(context: context), + iconOnly: iconOnly, menuItem: menuItem, onPressed: () => _onTap(context, ref, backgroundManager), ); diff --git a/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart index 0aca5158ef..ba2491365d 100644 --- a/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/favorite_action_button.widget.dart @@ -10,9 +10,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class FavoriteActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; final bool menuItem; - const FavoriteActionButton({super.key, required this.source, this.menuItem = false}); + const FavoriteActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -44,6 +45,7 @@ class FavoriteActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.favorite_border_rounded, label: "favorite".t(context: context), + iconOnly: iconOnly, menuItem: menuItem, onPressed: () => _onTap(context, ref), ); diff --git a/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart index 33794eae11..8c326974a7 100644 --- a/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/like_activity_action_button.widget.dart @@ -12,8 +12,9 @@ import 'package:immich_mobile/providers/infrastructure/current_album.provider.da import 'package:immich_mobile/providers/user.provider.dart'; class LikeActivityActionButton extends ConsumerWidget { - const LikeActivityActionButton({super.key, this.menuItem = false}); + const LikeActivityActionButton({super.key, this.iconOnly = false, this.menuItem = false}); + final bool iconOnly; final bool menuItem; @override @@ -46,17 +47,19 @@ class LikeActivityActionButton extends ConsumerWidget { return BaseActionButton( maxWidth: 60, - iconData: liked != null ? Icons.favorite : Icons.favorite_border, + iconData: liked != null ? Icons.thumb_up : Icons.thumb_up_off_alt, label: "like".t(context: context), onPressed: () => onTap(liked), + iconOnly: iconOnly, menuItem: menuItem, ); }, // default to empty heart during loading loading: () => BaseActionButton( - iconData: Icons.favorite_border, + iconData: Icons.thumb_up_off_alt, label: "like".t(context: context), + iconOnly: iconOnly, menuItem: menuItem, ), error: (error, stack) => Text('error_saving_image'.tr(args: [error.toString()])), diff --git a/mobile/lib/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart index 696b9ff367..3bd67978e2 100644 --- a/mobile/lib/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart @@ -5,8 +5,9 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_bu import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart'; class MotionPhotoActionButton extends ConsumerWidget { - const MotionPhotoActionButton({super.key, this.menuItem = true}); + const MotionPhotoActionButton({super.key, this.iconOnly = false, this.menuItem = false}); + final bool iconOnly; final bool menuItem; @override @@ -17,6 +18,7 @@ class MotionPhotoActionButton extends ConsumerWidget { iconData: isPlaying ? Icons.motion_photos_pause_outlined : Icons.play_circle_outline_rounded, label: "play_motion_photo".t(context: context), onPressed: ref.read(isPlayingMotionVideoProvider.notifier).toggle, + iconOnly: iconOnly, menuItem: menuItem, ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart index 20d391c4a6..341791c1af 100644 --- a/mobile/lib/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/move_to_lock_folder_action_button.widget.dart @@ -38,8 +38,10 @@ Future performMoveToLockFolderAction(BuildContext context, WidgetRef ref, class MoveToLockFolderActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const MoveToLockFolderActionButton({super.key, required this.source}); + const MoveToLockFolderActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); Future _onTap(BuildContext context, WidgetRef ref) async { await performMoveToLockFolderAction(context, ref, source: source); @@ -51,6 +53,8 @@ class MoveToLockFolderActionButton extends ConsumerWidget { maxWidth: 115.0, iconData: Icons.lock_outline_rounded, label: "move_to_locked_folder".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart index 2ce8b345a1..fd88e94cf7 100644 --- a/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/remove_from_album_action_button.widget.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; +import 'package:immich_mobile/domain/models/events.model.dart'; +import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; @@ -11,8 +13,16 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class RemoveFromAlbumActionButton extends ConsumerWidget { final String albumId; final ActionSource source; + final bool iconOnly; + final bool menuItem; - const RemoveFromAlbumActionButton({super.key, required this.albumId, required this.source}); + const RemoveFromAlbumActionButton({ + super.key, + required this.albumId, + required this.source, + this.iconOnly = false, + this.menuItem = false, + }); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -22,6 +32,10 @@ class RemoveFromAlbumActionButton extends ConsumerWidget { final result = await ref.read(actionProvider.notifier).removeFromAlbum(source, albumId); ref.read(multiSelectProvider.notifier).reset(); + if (source == ActionSource.viewer) { + EventStream.shared.emit(const ViewerReloadAssetEvent()); + } + final successMessage = 'remove_from_album_action_prompt'.t( context: context, args: {'count': result.count.toString()}, @@ -42,6 +56,8 @@ class RemoveFromAlbumActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.remove_circle_outline, label: "remove_from_album".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), maxWidth: 100, ); diff --git a/mobile/lib/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart index 028abf5596..17d2a76af7 100644 --- a/mobile/lib/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/remove_from_lock_folder_action_button.widget.dart @@ -10,8 +10,15 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class RemoveFromLockFolderActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const RemoveFromLockFolderActionButton({super.key, required this.source}); + const RemoveFromLockFolderActionButton({ + super.key, + required this.source, + this.iconOnly = false, + this.menuItem = false, + }); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -42,6 +49,8 @@ class RemoveFromLockFolderActionButton extends ConsumerWidget { maxWidth: 100.0, iconData: Icons.lock_open_rounded, label: "remove_from_locked_folder".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart index 6bcf099487..4f272cb990 100644 --- a/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/share_action_button.widget.dart @@ -31,8 +31,10 @@ class _SharePreparingDialog extends StatelessWidget { class ShareActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const ShareActionButton({super.key, required this.source}); + const ShareActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -74,6 +76,8 @@ class ShareActionButton extends ConsumerWidget { return BaseActionButton( iconData: Platform.isAndroid ? Icons.share_rounded : Icons.ios_share_rounded, label: 'share'.t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/share_link_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/share_link_action_button.widget.dart index 4a9f6d9bd6..b8dc69f515 100644 --- a/mobile/lib/presentation/widgets/action_buttons/share_link_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/share_link_action_button.widget.dart @@ -7,8 +7,10 @@ import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; class ShareLinkActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const ShareLinkActionButton({super.key, required this.source}); + const ShareLinkActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -23,6 +25,8 @@ class ShareLinkActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.link_rounded, label: "share_link".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } 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 4cbc0f0bb8..65ba744ec3 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 @@ -13,8 +13,10 @@ import 'package:immich_mobile/routing/router.dart'; class SimilarPhotosActionButton extends ConsumerWidget { final String assetId; + final bool iconOnly; + final bool menuItem; - const SimilarPhotosActionButton({super.key, required this.assetId}); + const SimilarPhotosActionButton({super.key, required this.assetId, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -44,6 +46,8 @@ class SimilarPhotosActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.compare, label: "view_similar_photos".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), maxWidth: 100, ); diff --git a/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart index a78ff2ccd8..5f1e385769 100644 --- a/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/trash_action_button.widget.dart @@ -15,8 +15,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; /// which will be permanently deleted after the number of days configure by the admin class TrashActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const TrashActionButton({super.key, required this.source}); + const TrashActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -48,6 +50,8 @@ class TrashActionButton extends ConsumerWidget { maxWidth: 85.0, iconData: Icons.delete_outline_rounded, label: "control_bottom_app_bar_trash_from_immich".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart index 32147a194f..8cf0bcba92 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unarchive_action_button.widget.dart @@ -37,8 +37,10 @@ Future performUnArchiveAction(BuildContext context, WidgetRef ref, {requir class UnArchiveActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const UnArchiveActionButton({super.key, required this.source}); + const UnArchiveActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); Future _onTap(BuildContext context, WidgetRef ref) async { await performUnArchiveAction(context, ref, source: source); @@ -49,6 +51,8 @@ class UnArchiveActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.unarchive_outlined, label: "unarchive".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart index 7fdc5e81e8..ec5513e0a8 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart @@ -10,9 +10,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class UnFavoriteActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; final bool menuItem; - const UnFavoriteActionButton({super.key, required this.source, this.menuItem = false}); + const UnFavoriteActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -45,6 +46,7 @@ class UnFavoriteActionButton extends ConsumerWidget { iconData: Icons.favorite_rounded, label: "unfavorite".t(context: context), onPressed: () => _onTap(context, ref), + iconOnly: iconOnly, menuItem: menuItem, ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart index a07803ace5..e7badf129f 100644 --- a/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/unstack_action_button.widget.dart @@ -10,8 +10,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class UnStackActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const UnStackActionButton({super.key, required this.source}); + const UnStackActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -38,6 +40,8 @@ class UnStackActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.layers_clear_outlined, label: "unstack".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart b/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart index f037d365d8..98ef831f9c 100644 --- a/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart +++ b/mobile/lib/presentation/widgets/action_buttons/upload_action_button.widget.dart @@ -10,8 +10,10 @@ import 'package:immich_mobile/widgets/common/immich_toast.dart'; class UploadActionButton extends ConsumerWidget { final ActionSource source; + final bool iconOnly; + final bool menuItem; - const UploadActionButton({super.key, required this.source}); + const UploadActionButton({super.key, required this.source, this.iconOnly = false, this.menuItem = false}); void _onTap(BuildContext context, WidgetRef ref) async { if (!context.mounted) { @@ -39,6 +41,8 @@ class UploadActionButton extends ConsumerWidget { return BaseActionButton( iconData: Icons.backup_outlined, label: "upload".t(context: context), + iconOnly: iconOnly, + menuItem: menuItem, onPressed: () => _onTap(context, ref), ); } diff --git a/mobile/lib/presentation/widgets/album/album_selector.widget.dart b/mobile/lib/presentation/widgets/album/album_selector.widget.dart index 4110966e57..c42f49091f 100644 --- a/mobile/lib/presentation/widgets/album/album_selector.widget.dart +++ b/mobile/lib/presentation/widgets/album/album_selector.widget.dart @@ -12,8 +12,10 @@ import 'package:immich_mobile/extensions/theme_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; import 'package:immich_mobile/models/albums/album_search.model.dart'; import 'package:immich_mobile/presentation/widgets/album/album_tile.dart'; +import 'package:immich_mobile/presentation/widgets/album/new_album_name_modal.widget.dart'; import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart'; @@ -766,3 +768,68 @@ class AddToAlbumHeader extends ConsumerWidget { ); } } + +class CreateAlbumButton extends ConsumerWidget { + const CreateAlbumButton({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + Future onCreateAlbum() async { + var albumName = await showDialog(context: context, builder: (context) => const NewAlbumNameModal()); + if (albumName == null) { + return; + } + + final asset = ref.read(currentAssetNotifier); + + if (asset == null) { + ImmichToast.show(context: context, msg: "Cannot load asset information.", toastType: ToastType.error); + return; + } + + final album = await ref + .read(remoteAlbumProvider.notifier) + .createAlbum(title: albumName, assetIds: [asset.remoteId!]); + + if (album == null) { + ImmichToast.show(context: context, toastType: ToastType.error, msg: 'errors.failed_to_create_album'.tr()); + return; + } + + ImmichToast.show( + context: context, + msg: 'add_to_album_bottom_sheet_added'.tr(namedArgs: {'album': album.name}), + ); + + // Invalidate using the asset's remote ID to refresh the "Appears in" list + ref.invalidate(albumsContainingAssetProvider(asset.remoteId!)); + + context.pop(); + } + + return SliverPadding( + padding: const EdgeInsets.symmetric(horizontal: 16), + sliver: SliverToBoxAdapter( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("add_to_album", style: context.textTheme.titleSmall).tr(), + TextButton.icon( + style: TextButton.styleFrom( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + minimumSize: const Size(0, 0), + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + onPressed: onCreateAlbum, + icon: Icon(Icons.add, color: context.primaryColor), + label: Text( + "common_create_new_album", + style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 14), + ).tr(), + ), + ], + ), + ), + ); + } +} diff --git a/mobile/lib/presentation/widgets/album/new_album_name_modal.widget.dart b/mobile/lib/presentation/widgets/album/new_album_name_modal.widget.dart new file mode 100644 index 0000000000..a5e21af489 --- /dev/null +++ b/mobile/lib/presentation/widgets/album/new_album_name_modal.widget.dart @@ -0,0 +1,53 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; + +class NewAlbumNameModal extends StatefulWidget { + const NewAlbumNameModal({super.key}); + + @override + State createState() => _NewAlbumNameModalState(); +} + +class _NewAlbumNameModalState extends State { + TextEditingController nameController = TextEditingController(); + + @override + void dispose() { + nameController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text("album_name", style: TextStyle(fontWeight: FontWeight.bold)).tr(), + content: SingleChildScrollView( + child: TextFormField( + controller: nameController, + textCapitalization: TextCapitalization.words, + autofocus: true, + decoration: InputDecoration(hintText: 'name'.tr(), border: const OutlineInputBorder()), + ), + ), + actions: [ + TextButton( + onPressed: () => context.pop(null), + child: Text( + "cancel", + style: TextStyle(color: Colors.red[300], fontWeight: FontWeight.bold), + ).tr(), + ), + TextButton( + onPressed: () { + context.pop(nameController.text.trim()); + }, + child: Text( + "create_album", + style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold), + ).tr(), + ), + ], + ); + } +} diff --git a/mobile/lib/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart index 63669495b9..3b46b69958 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/activities_bottom_sheet.widget.dart @@ -79,7 +79,7 @@ class ActivitiesBottomSheet extends HookConsumerWidget { expand: false, shouldCloseOnMinExtent: false, resizeOnScroll: false, - backgroundColor: context.isDarkTheme ? Colors.black : Colors.white, + backgroundColor: context.isDarkTheme ? context.colorScheme.surface : Colors.white, ); } } diff --git a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart index 70eb6699aa..d992d243ee 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/asset_viewer.page.dart @@ -97,7 +97,7 @@ class AssetViewer extends ConsumerStatefulWidget { } const double _kBottomSheetMinimumExtent = 0.4; -const double _kBottomSheetSnapExtent = 0.7; +const double _kBottomSheetSnapExtent = 0.67; class _AssetViewerState extends ConsumerState { static final _dummyListener = ImageStreamListener((image, _) => image.dispose()); @@ -399,10 +399,14 @@ class _AssetViewerState extends ConsumerState { final isDraggingDown = currentExtent < previousExtent; previousExtent = currentExtent; // Closes the bottom sheet if the user is dragging down - if (isDraggingDown && delta.extent < 0.55) { + if (isDraggingDown && delta.extent < 0.67) { if (dragInProgress) { blockGestures = true; } + // Jump to a lower position before starting close animation to prevent glitch + if (bottomSheetController.isAttached) { + bottomSheetController.jumpTo(0.67); + } sheetCloseController?.close(); } @@ -480,7 +484,7 @@ class _AssetViewerState extends ConsumerState { previousExtent = _kBottomSheetMinimumExtent; sheetCloseController = showBottomSheet( context: ctx, - sheetAnimationStyle: const AnimationStyle(duration: Durations.short4, reverseDuration: Durations.short2), + sheetAnimationStyle: const AnimationStyle(duration: Durations.medium2, reverseDuration: Durations.medium2), constraints: const BoxConstraints(maxWidth: double.infinity), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(20.0))), backgroundColor: ctx.colorScheme.surfaceContainerLowest, @@ -688,16 +692,20 @@ class _AssetViewerState extends ConsumerState { backgroundDecoration: BoxDecoration(color: backgroundColor), enablePanAlways: true, ), + if (!showingBottomSheet) + const Positioned( + bottom: 0, + left: 0, + right: 0, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [AssetStackRow(), ViewerBottomBar()], + ), + ), ], ), - bottomNavigationBar: showingBottomSheet - ? const SizedBox.shrink() - : const Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.end, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [AssetStackRow(), ViewerBottomBar()], - ), ), ); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart index 14c03ad637..537f2fc31d 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_bar.widget.dart @@ -38,16 +38,21 @@ class ViewerBottomBar extends ConsumerWidget { opacity = 0; } + final originalTheme = context.themeData; + final actions = [ const ShareActionButton(source: ActionSource.viewer), - if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer), - if (asset.type == AssetType.image) const EditImageActionButton(), - if (asset.hasRemote) const AddActionButton(), - if (isOwner) ...[ - asset.isLocalOnly - ? const DeleteLocalActionButton(source: ActionSource.viewer) - : const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true), + if (!isInLockedView) ...[ + if (asset.isLocalOnly) const UploadActionButton(source: ActionSource.viewer), + if (asset.type == AssetType.image) const EditImageActionButton(), + if (asset.hasRemote) AddActionButton(originalTheme: originalTheme), + + if (isOwner) ...[ + asset.isLocalOnly + ? const DeleteLocalActionButton(source: ActionSource.viewer) + : const DeleteActionButton(source: ActionSource.viewer, showConfirmation: true), + ], ], ]; @@ -74,7 +79,7 @@ class ViewerBottomBar extends ConsumerWidget { mainAxisAlignment: MainAxisAlignment.end, children: [ if (asset.isVideo) const VideoControls(), - if (!isInLockedView && !isReadonlyModeEnabled) + if (!isReadonlyModeEnabled) Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: actions), ], ), diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart index 276034d3d6..ed3873b510 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet.widget.dart @@ -8,7 +8,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/exif.model.dart'; -import 'package:immich_mobile/domain/models/setting.model.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/duration_extensions.dart'; import 'package:immich_mobile/extensions/translate_extensions.dart'; @@ -21,14 +20,9 @@ import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_shee import 'package:immich_mobile/providers/infrastructure/action.provider.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/setting.provider.dart'; -import 'package:immich_mobile/providers/routes.provider.dart'; -import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/repositories/asset_media.repository.dart'; import 'package:immich_mobile/routing/router.dart'; -import 'package:immich_mobile/utils/action_button.utils.dart'; import 'package:immich_mobile/utils/bytes_units.dart'; import 'package:immich_mobile/utils/timezone.dart'; import 'package:immich_mobile/widgets/common/immich_toast.dart'; @@ -48,29 +42,8 @@ class AssetDetailBottomSheet extends ConsumerWidget { return const SizedBox.shrink(); } - final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); - final isOwner = asset is RemoteAsset && asset.ownerId == ref.watch(currentUserProvider)?.id; - final isInLockedView = ref.watch(inLockedViewProvider); - final currentAlbum = ref.watch(currentRemoteAlbumProvider); - final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive; - final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(Setting.advancedTroubleshooting); - - final buttonContext = ActionButtonContext( - asset: asset, - isOwner: isOwner, - isArchived: isArchived, - isTrashEnabled: isTrashEnable, - isInLockedView: isInLockedView, - isStacked: asset is RemoteAsset && asset.stackId != null, - currentAlbum: currentAlbum, - advancedTroubleshooting: advancedTroubleshooting, - source: ActionSource.viewer, - ); - - final actions = ActionButtonBuilder.build(buttonContext); - return BaseBottomSheet( - actions: actions, + actions: [], slivers: const [_AssetDetailBottomSheet()], controller: controller, initialChildSize: initialChildSize, @@ -79,7 +52,7 @@ class AssetDetailBottomSheet extends ConsumerWidget { expand: false, shouldCloseOnMinExtent: false, resizeOnScroll: false, - backgroundColor: context.isDarkTheme ? Colors.black : Colors.white, + backgroundColor: context.isDarkTheme ? context.colorScheme.surface : Colors.white, ); } } @@ -251,8 +224,8 @@ class _AssetDetailBottomSheet extends ConsumerWidget { color: context.textTheme.labelLarge?.color, ), subtitle: _getFileInfo(asset, exifInfo), - subtitleStyle: context.textTheme.bodyMedium?.copyWith( - color: context.textTheme.bodyMedium?.color?.withAlpha(155), + subtitleStyle: context.textTheme.labelMedium?.copyWith( + color: context.textTheme.labelMedium?.color?.withAlpha(200), ), ); }, @@ -268,8 +241,8 @@ class _AssetDetailBottomSheet extends ConsumerWidget { color: context.textTheme.labelLarge?.color, ), subtitle: _getFileInfo(asset, exifInfo), - subtitleStyle: context.textTheme.bodyMedium?.copyWith( - color: context.textTheme.bodyMedium?.color?.withAlpha(155), + subtitleStyle: context.textTheme.labelMedium?.copyWith( + color: context.textTheme.labelMedium?.color?.withAlpha(200), ), ); } @@ -280,7 +253,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget { // Asset Date and Time SheetTile( title: _getDateTime(context, asset, exifInfo), - titleStyle: context.textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600), + titleStyle: context.textTheme.labelLarge, trailing: asset.hasRemote && isOwner ? const Icon(Icons.edit, size: 18) : null, onTap: asset.hasRemote && isOwner ? () async => await _editDateTime(context, ref) : null, ), @@ -289,7 +262,7 @@ class _AssetDetailBottomSheet extends ConsumerWidget { const SheetLocationDetails(), // Details header SheetTile( - title: 'exif_bottom_sheet_details'.t(context: context), + title: 'details'.t(context: context).toUpperCase(), titleStyle: context.textTheme.labelMedium?.copyWith( color: context.textTheme.labelMedium?.color?.withAlpha(200), fontWeight: FontWeight.w600, @@ -298,31 +271,35 @@ class _AssetDetailBottomSheet extends ConsumerWidget { // File info buildFileInfoTile(), // Camera info - if (cameraTitle != null) + if (cameraTitle != null) ...[ + const SizedBox(height: 16), SheetTile( title: cameraTitle, titleStyle: context.textTheme.labelLarge, leading: Icon(Icons.camera_alt_outlined, size: 24, color: context.textTheme.labelLarge?.color), subtitle: _getCameraInfoSubtitle(exifInfo), - subtitleStyle: context.textTheme.bodyMedium?.copyWith( - color: context.textTheme.bodyMedium?.color?.withAlpha(155), + subtitleStyle: context.textTheme.labelMedium?.copyWith( + color: context.textTheme.labelMedium?.color?.withAlpha(200), ), ), + ], // Lens info - if (lensTitle != null) + if (lensTitle != null) ...[ + const SizedBox(height: 16), SheetTile( title: lensTitle, titleStyle: context.textTheme.labelLarge, leading: Icon(Icons.camera_outlined, size: 24, color: context.textTheme.labelLarge?.color), subtitle: _getLensInfoSubtitle(exifInfo), - subtitleStyle: context.textTheme.bodyMedium?.copyWith( - color: context.textTheme.bodyMedium?.color?.withAlpha(155), + subtitleStyle: context.textTheme.labelMedium?.copyWith( + color: context.textTheme.labelMedium?.color?.withAlpha(200), ), ), + ], // Appears in (Albums) - _buildAppearsInList(ref, context), + Padding(padding: const EdgeInsets.only(top: 16.0), child: _buildAppearsInList(ref, context)), // padding at the bottom to avoid cut-off - const SizedBox(height: 100), + const SizedBox(height: 30), ], ); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart index 05d19476c6..4edd6855a8 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/bottom_sheet/sheet_location_details.widget.dart @@ -78,7 +78,7 @@ class _SheetLocationDetailsState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ SheetTile( - title: 'exif_bottom_sheet_location'.t(context: context), + title: 'location'.t(context: context).toUpperCase(), titleStyle: context.textTheme.labelMedium?.copyWith( color: context.textTheme.labelMedium?.color?.withAlpha(200), fontWeight: FontWeight.w600, @@ -102,7 +102,7 @@ class _SheetLocationDetailsState extends ConsumerState { Text( coordinates, style: context.textTheme.labelMedium?.copyWith( - color: context.textTheme.labelMedium?.color?.withAlpha(150), + color: context.textTheme.labelMedium?.color?.withAlpha(200), ), ), ], diff --git a/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart index e78aa926aa..2af68e1ff0 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/sheet_tile.widget.dart @@ -46,7 +46,7 @@ class SheetTile extends ConsumerWidget { } else { titleWidget = Container( width: double.infinity, - padding: const EdgeInsets.only(left: 15), + padding: const EdgeInsets.only(left: 15, right: 15), child: Text(title, style: titleStyle), ); } diff --git a/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart index 5114ef6fd2..193cf60220 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/top_app_bar.widget.dart @@ -4,25 +4,19 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; import 'package:immich_mobile/domain/models/events.model.dart'; -import 'package:immich_mobile/domain/services/timeline.service.dart'; import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; -import 'package:immich_mobile/extensions/translate_extensions.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/cast_action_button.widget.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/download_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/favorite_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/motion_photo_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; +import 'package:immich_mobile/presentation/widgets/asset_viewer/viewer_kebab_menu.widget.dart'; import 'package:immich_mobile/providers/activity.provider.dart'; -import 'package:immich_mobile/providers/cast.provider.dart'; import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; import 'package:immich_mobile/providers/infrastructure/readonly_mode.provider.dart'; -import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; import 'package:immich_mobile/providers/routes.provider.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -import 'package:immich_mobile/routing/router.dart'; class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { const ViewerTopAppBar({super.key}); @@ -41,15 +35,6 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { final isInLockedView = ref.watch(inLockedViewProvider); final isReadonlyModeEnabled = ref.watch(readonlyModeProvider); - final timelineOrigin = ref.read(timelineServiceProvider).origin; - final showViewInTimelineButton = - timelineOrigin != TimelineOrigin.main && - timelineOrigin != TimelineOrigin.deepLink && - timelineOrigin != TimelineOrigin.trash && - timelineOrigin != TimelineOrigin.archive && - timelineOrigin != TimelineOrigin.localAlbum && - isOwner; - final isShowingSheet = ref.watch(assetViewerProvider.select((state) => state.showingBottomSheet)); int opacity = ref.watch(assetViewerProvider.select((state) => state.backgroundOpacity)); final showControls = ref.watch(assetViewerProvider.select((s) => s.showingControls)); @@ -62,11 +47,10 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { opacity = 0; } - final isCasting = ref.watch(castProvider.select((c) => c.isCasting)); + final originalTheme = context.themeData; final actions = [ - if (asset.isRemoteOnly) const DownloadActionButton(source: ActionSource.viewer, menuItem: true), - if (isCasting || (asset.hasRemote)) const CastActionButton(menuItem: true), + if (asset.isMotionPhoto) const MotionPhotoActionButton(iconOnly: true), if (album != null && album.isActivityEnabled && album.isShared) IconButton( icon: const Icon(Icons.chat_outlined), @@ -74,28 +58,16 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { EventStream.shared.emit(const ViewerOpenBottomSheetEvent(activitiesMode: true)); }, ), - if (showViewInTimelineButton) - IconButton( - onPressed: () async { - await context.maybePop(); - await context.navigateTo(const TabShellRoute(children: [MainTimelineRoute()])); - EventStream.shared.emit(ScrollToDateEvent(asset.createdAt)); - }, - icon: const Icon(Icons.image_search), - tooltip: 'view_in_timeline'.t(context: context), - ), + if (asset.hasRemote && isOwner && !asset.isFavorite) - const FavoriteActionButton(source: ActionSource.viewer, menuItem: true), + const FavoriteActionButton(source: ActionSource.viewer, iconOnly: true), if (asset.hasRemote && isOwner && asset.isFavorite) - const UnFavoriteActionButton(source: ActionSource.viewer, menuItem: true), - if (asset.isMotionPhoto) const MotionPhotoActionButton(menuItem: true), - const _KebabMenu(), + const UnFavoriteActionButton(source: ActionSource.viewer, iconOnly: true), + + ViewerKebabMenu(originalTheme: originalTheme), ]; - final lockedViewActions = [ - if (isCasting || (asset.hasRemote)) const CastActionButton(menuItem: true), - const _KebabMenu(), - ]; + final lockedViewActions = [ViewerKebabMenu(originalTheme: originalTheme)]; return IgnorePointer( ignoring: opacity < 255, @@ -122,20 +94,6 @@ class ViewerTopAppBar extends ConsumerWidget implements PreferredSizeWidget { Size get preferredSize => const Size.fromHeight(60.0); } -class _KebabMenu extends ConsumerWidget { - const _KebabMenu(); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return IconButton( - onPressed: () { - EventStream.shared.emit(const ViewerOpenBottomSheetEvent()); - }, - icon: const Icon(Icons.more_vert_rounded), - ); - } -} - class _AppBarBackButton extends ConsumerWidget { const _AppBarBackButton(); diff --git a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart index 08b5b25343..8727f40a1a 100644 --- a/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart +++ b/mobile/lib/presentation/widgets/asset_viewer/video_viewer.widget.dart @@ -9,6 +9,7 @@ import 'package:immich_mobile/domain/models/setting.model.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/setting.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_viewer.state.dart'; import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer_controls.widget.dart'; @@ -104,7 +105,12 @@ class NativeVideoViewer extends HookConsumerWidget { throw Exception('No file found for the video'); } - final source = await VideoSource.init(path: file.path, type: VideoSourceType.file); + // Pass a file:// URI so Android's Uri.parse doesn't + // interpret characters like '#' as fragment identifiers. + final source = await VideoSource.init( + path: CurrentPlatform.isAndroid ? file.uri.toString() : file.path, + type: VideoSourceType.file, + ); return source; } diff --git a/mobile/lib/presentation/widgets/asset_viewer/viewer_kebab_menu.widget.dart b/mobile/lib/presentation/widgets/asset_viewer/viewer_kebab_menu.widget.dart new file mode 100644 index 0000000000..10f3595d01 --- /dev/null +++ b/mobile/lib/presentation/widgets/asset_viewer/viewer_kebab_menu.widget.dart @@ -0,0 +1,85 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/constants/enums.dart'; +import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/setting.model.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; +import 'package:immich_mobile/providers/cast.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/asset_viewer/current_asset.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/setting.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart'; +import 'package:immich_mobile/providers/routes.provider.dart'; +import 'package:immich_mobile/providers/server_info.provider.dart'; +import 'package:immich_mobile/providers/user.provider.dart'; +import 'package:immich_mobile/utils/action_button.utils.dart'; + +class ViewerKebabMenu extends ConsumerWidget { + const ViewerKebabMenu({super.key, this.originalTheme}); + + final ThemeData? originalTheme; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final asset = ref.watch(currentAssetNotifier); + if (asset == null) { + return const SizedBox.shrink(); + } + + final user = ref.watch(currentUserProvider); + final isOwner = asset is RemoteAsset && asset.ownerId == user?.id; + final isCasting = ref.watch(castProvider.select((c) => c.isCasting)); + final timelineOrigin = ref.read(timelineServiceProvider).origin; + final isTrashEnable = ref.watch(serverInfoProvider.select((state) => state.serverFeatures.trash)); + final isInLockedView = ref.watch(inLockedViewProvider); + final currentAlbum = ref.watch(currentRemoteAlbumProvider); + final isArchived = asset is RemoteAsset && asset.visibility == AssetVisibility.archive; + final advancedTroubleshooting = ref.watch(settingsProvider.notifier).get(Setting.advancedTroubleshooting); + + final actionContext = ActionButtonContext( + asset: asset, + isOwner: isOwner, + isArchived: isArchived, + isTrashEnabled: isTrashEnable, + isStacked: asset is RemoteAsset && asset.stackId != null, + isInLockedView: isInLockedView, + currentAlbum: currentAlbum, + advancedTroubleshooting: advancedTroubleshooting, + source: ActionSource.viewer, + isCasting: isCasting, + timelineOrigin: timelineOrigin, + originalTheme: originalTheme, + ); + + final menuChildren = ActionButtonBuilder.buildViewerKebabMenu(actionContext, context, ref); + + return MenuAnchor( + consumeOutsideTap: true, + style: MenuStyle( + backgroundColor: WidgetStatePropertyAll(context.themeData.scaffoldBackgroundColor), + surfaceTintColor: const WidgetStatePropertyAll(Colors.grey), + elevation: const WidgetStatePropertyAll(4), + shape: const WidgetStatePropertyAll( + RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12))), + ), + padding: const WidgetStatePropertyAll(EdgeInsets.symmetric(vertical: 6)), + ), + menuChildren: [ + ConstrainedBox( + constraints: const BoxConstraints(minWidth: 150), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: menuChildren, + ), + ), + ], + builder: (context, controller, child) { + return IconButton( + icon: const Icon(Icons.more_vert_rounded), + onPressed: () => controller.isOpen ? controller.close() : controller.open(), + ); + }, + ); + } +} diff --git a/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart index f40e189e18..9481ec12f5 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/archive_bottom_sheet.widget.dart @@ -14,7 +14,6 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_b import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/providers/server_info.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; @@ -47,10 +46,7 @@ class ArchiveBottomSheet extends ConsumerWidget { if (multiselect.selectedAssets.length > 1) const StackActionButton(source: ActionSource.timeline), if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), ], - if (multiselect.hasLocal) ...[ - const DeleteLocalActionButton(source: ActionSource.timeline), - const UploadActionButton(source: ActionSource.timeline), - ], + if (multiselect.hasMerged) const DeleteLocalActionButton(source: ActionSource.timeline), ], ); } diff --git a/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart index 2f2847543f..0d0e0259fd 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart @@ -81,7 +81,7 @@ class _BaseDraggableScrollableSheetState extends ConsumerState child: CustomScrollView( controller: scrollController, slivers: [ - const SliverPersistentHeader(delegate: _DragHandleDelegate(), pinned: true), + const SliverToBoxAdapter(child: _DragHandle()), if (widget.actions.isNotEmpty) SliverToBoxAdapter( child: Column( @@ -108,31 +108,13 @@ class _BaseDraggableScrollableSheetState extends ConsumerState } } -class _DragHandleDelegate extends SliverPersistentHeaderDelegate { - const _DragHandleDelegate(); - - @override - Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { - return const _DragHandle(); - } - - @override - bool shouldRebuild(_DragHandleDelegate oldDelegate) => false; - - @override - double get minExtent => 50.0; - - @override - double get maxExtent => 50.0; -} - class _DragHandle extends StatelessWidget { const _DragHandle(); @override Widget build(BuildContext context) { return SizedBox( - height: 50, + height: 38, child: Center( child: SizedBox( width: 32, diff --git a/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart index b2502127d4..fb6034b869 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/favorite_bottom_sheet.widget.dart @@ -17,7 +17,6 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_b import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unfavorite_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; @@ -86,10 +85,7 @@ class FavoriteBottomSheet extends ConsumerWidget { if (multiselect.selectedAssets.length > 1) const StackActionButton(source: ActionSource.timeline), if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), ], - if (multiselect.hasLocal) ...[ - const DeleteLocalActionButton(source: ActionSource.timeline), - const UploadActionButton(source: ActionSource.timeline), - ], + if (multiselect.hasMerged) const DeleteLocalActionButton(source: ActionSource.timeline), ], slivers: multiselect.hasRemote ? [const AddToAlbumHeader(), AlbumSelector(onAlbumSelected: addAssetsToAlbum)] diff --git a/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart b/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart index 7db8a80af2..2f2a2e0a4e 100644 --- a/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart +++ b/mobile/lib/presentation/widgets/bottom_sheet/remote_album_bottom_sheet.widget.dart @@ -18,7 +18,6 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/share_link_act import 'package:immich_mobile/presentation/widgets/action_buttons/stack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; -import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/album/album_selector.widget.dart'; import 'package:immich_mobile/presentation/widgets/bottom_sheet/base_bottom_sheet.widget.dart'; import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; @@ -112,10 +111,7 @@ class _RemoteAlbumBottomSheetState extends ConsumerState if (multiselect.hasStacked) const UnStackActionButton(source: ActionSource.timeline), ], ], - if (multiselect.hasLocal) ...[ - const DeleteLocalActionButton(source: ActionSource.timeline), - const UploadActionButton(source: ActionSource.timeline), - ], + if (multiselect.hasMerged) const DeleteLocalActionButton(source: ActionSource.timeline), if (ownsAlbum) RemoveFromAlbumActionButton(source: ActionSource.timeline, albumId: widget.album.id), ], slivers: ownsAlbum diff --git a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart index 5868de92aa..a04e26d653 100644 --- a/mobile/lib/presentation/widgets/timeline/timeline.widget.dart +++ b/mobile/lib/presentation/widgets/timeline/timeline.widget.dart @@ -324,7 +324,11 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { final topPadding = context.padding.top + (widget.appBar == null ? 0 : kToolbarHeight) + 10; const scrubberBottomPadding = 100.0; - final bottomPadding = context.padding.bottom + (widget.appBar == null ? 0 : scrubberBottomPadding); + const bottomSheetOpenModifier = 120.0; + final bottomPadding = + context.padding.bottom + + (widget.appBar == null ? 0 : scrubberBottomPadding) + + (isMultiSelectEnabled ? bottomSheetOpenModifier : 0); final grid = CustomScrollView( primary: true, @@ -347,7 +351,7 @@ class _SliverTimelineState extends ConsumerState<_SliverTimeline> { addRepaintBoundaries: false, ), ), - const SliverPadding(padding: EdgeInsets.only(bottom: scrubberBottomPadding)), + SliverPadding(padding: EdgeInsets.only(bottom: bottomPadding)), ], ); diff --git a/mobile/lib/providers/app_life_cycle.provider.dart b/mobile/lib/providers/app_life_cycle.provider.dart index 6d0c0acb0d..4b1bf3e809 100644 --- a/mobile/lib/providers/app_life_cycle.provider.dart +++ b/mobile/lib/providers/app_life_cycle.provider.dart @@ -4,6 +4,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/models/store.model.dart'; import 'package:immich_mobile/domain/services/log.service.dart'; import 'package:immich_mobile/entities/store.entity.dart'; +import 'package:immich_mobile/extensions/platform_extensions.dart'; import 'package:immich_mobile/models/backup/backup_state.model.dart'; import 'package:immich_mobile/providers/album/album.provider.dart'; import 'package:immich_mobile/providers/app_settings.provider.dart'; @@ -150,7 +151,7 @@ class AppLifeCycleNotifier extends StateNotifier { try { bool syncSuccess = false; await Future.wait([ - _safeRun(backgroundManager.syncLocal(), "syncLocal"), + _safeRun(backgroundManager.syncLocal(full: CurrentPlatform.isAndroid ? true : false), "syncLocal"), _safeRun(backgroundManager.syncRemote().then((success) => syncSuccess = success), "syncRemote"), ]); if (syncSuccess) { diff --git a/mobile/lib/repositories/person_api.repository.dart b/mobile/lib/repositories/person_api.repository.dart index 04e4bd2a2c..bbf55e674a 100644 --- a/mobile/lib/repositories/person_api.repository.dart +++ b/mobile/lib/repositories/person_api.repository.dart @@ -17,8 +17,10 @@ class PersonApiRepository extends ApiRepository { } Future update(String id, {String? name, DateTime? birthday}) async { - final dto = await checkNull(_api.updatePerson(id, PersonUpdateDto(name: name, birthDate: birthday))); - return _toPerson(dto); + final birthdayUtc = birthday == null ? null : DateTime.utc(birthday.year, birthday.month, birthday.day); + final dto = PersonUpdateDto(name: name, birthDate: birthdayUtc); + final response = await checkNull(_api.updatePerson(id, dto)); + return _toPerson(response); } static PersonDto _toPerson(PersonResponseDto dto) => PersonDto( diff --git a/mobile/lib/routing/router.dart b/mobile/lib/routing/router.dart index 30f43cf3b2..9c4a193381 100644 --- a/mobile/lib/routing/router.dart +++ b/mobile/lib/routing/router.dart @@ -78,9 +78,9 @@ import 'package:immich_mobile/pages/search/recently_taken.page.dart'; import 'package:immich_mobile/pages/search/search.page.dart'; import 'package:immich_mobile/pages/settings/sync_status.page.dart'; import 'package:immich_mobile/pages/share_intent/share_intent.page.dart'; -import 'package:immich_mobile/presentation/pages/dev/feat_in_development.page.dart'; import 'package:immich_mobile/presentation/pages/dev/main_timeline.page.dart'; import 'package:immich_mobile/presentation/pages/dev/media_stat.page.dart'; +import 'package:immich_mobile/presentation/pages/dev/ui_showcase.page.dart'; import 'package:immich_mobile/presentation/pages/download_info.page.dart'; import 'package:immich_mobile/presentation/pages/drift_activities.page.dart'; import 'package:immich_mobile/presentation/pages/drift_album.page.dart'; @@ -167,7 +167,7 @@ class AppRouter extends RootStackRouter { AutoRoute(page: LoginRoute.page, guards: [_duplicateGuard]), AutoRoute(page: ChangePasswordRoute.page), AutoRoute(page: SearchRoute.page, guards: [_authGuard, _duplicateGuard], maintainState: false), - CustomRoute( + AutoRoute( page: TabControllerRoute.page, guards: [_authGuard, _duplicateGuard], children: [ @@ -176,9 +176,8 @@ class AppRouter extends RootStackRouter { AutoRoute(page: LibraryRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: AlbumsRoute.page, guards: [_authGuard, _duplicateGuard]), ], - transitionsBuilder: TransitionsBuilders.fadeIn, ), - CustomRoute( + AutoRoute( page: TabShellRoute.page, guards: [_authGuard, _duplicateGuard], children: [ @@ -187,7 +186,6 @@ class AppRouter extends RootStackRouter { AutoRoute(page: DriftLibraryRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DriftAlbumsRoute.page, guards: [_authGuard, _duplicateGuard]), ], - transitionsBuilder: TransitionsBuilders.fadeIn, ), CustomRoute( page: GalleryViewerRoute.page, @@ -288,7 +286,6 @@ class AppRouter extends RootStackRouter { AutoRoute(page: ShareIntentRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: LockedRoute.page, guards: [_authGuard, _lockedGuard, _duplicateGuard]), AutoRoute(page: PinAuthRoute.page, guards: [_authGuard, _duplicateGuard]), - AutoRoute(page: FeatInDevRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: LocalMediaSummaryRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: RemoteMediaSummaryRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DriftBackupRoute.page, guards: [_authGuard, _duplicateGuard]), @@ -340,6 +337,7 @@ class AppRouter extends RootStackRouter { AutoRoute(page: DriftBackupAssetDetailRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: AssetTroubleshootRoute.page, guards: [_authGuard, _duplicateGuard]), AutoRoute(page: DownloadInfoRoute.page, guards: [_authGuard, _duplicateGuard]), + AutoRoute(page: ImmichUIShowcaseRoute.page, guards: [_authGuard, _duplicateGuard]), // required to handle all deeplinks in deep_link.service.dart // auto_route_library#1722 RedirectRoute(path: '*', redirectTo: '/'), diff --git a/mobile/lib/routing/router.gr.dart b/mobile/lib/routing/router.gr.dart index 146b313c2d..939bf73369 100644 --- a/mobile/lib/routing/router.gr.dart +++ b/mobile/lib/routing/router.gr.dart @@ -1648,22 +1648,6 @@ class FavoritesRoute extends PageRouteInfo { ); } -/// generated route for -/// [FeatInDevPage] -class FeatInDevRoute extends PageRouteInfo { - const FeatInDevRoute({List? children}) - : super(FeatInDevRoute.name, initialChildren: children); - - static const String name = 'FeatInDevRoute'; - - static PageInfo page = PageInfo( - name, - builder: (data) { - return const FeatInDevPage(); - }, - ); -} - /// generated route for /// [FilterImagePage] class FilterImageRoute extends PageRouteInfo { @@ -1831,6 +1815,22 @@ class HeaderSettingsRoute extends PageRouteInfo { ); } +/// generated route for +/// [ImmichUIShowcasePage] +class ImmichUIShowcaseRoute extends PageRouteInfo { + const ImmichUIShowcaseRoute({List? children}) + : super(ImmichUIShowcaseRoute.name, initialChildren: children); + + static const String name = 'ImmichUIShowcaseRoute'; + + static PageInfo page = PageInfo( + name, + builder: (data) { + return const ImmichUIShowcasePage(); + }, + ); +} + /// generated route for /// [LibraryPage] class LibraryRoute extends PageRouteInfo { diff --git a/mobile/lib/services/app_settings.service.dart b/mobile/lib/services/app_settings.service.dart index fc08193d11..aa247682a7 100644 --- a/mobile/lib/services/app_settings.service.dart +++ b/mobile/lib/services/app_settings.service.dart @@ -27,7 +27,7 @@ enum AppSettingsEnum { thumbnailCacheSize(StoreKey.thumbnailCacheSize, "thumbnailCacheSize", 10000), imageCacheSize(StoreKey.imageCacheSize, "imageCacheSize", 350), albumThumbnailCacheSize(StoreKey.albumThumbnailCacheSize, "albumThumbnailCacheSize", 200), - selectedAlbumSortOrder(StoreKey.selectedAlbumSortOrder, "selectedAlbumSortOrder", 0), + selectedAlbumSortOrder(StoreKey.selectedAlbumSortOrder, "selectedAlbumSortOrder", 2), advancedTroubleshooting(StoreKey.advancedTroubleshooting, null, false), manageLocalMediaAndroid(StoreKey.manageLocalMediaAndroid, null, false), logLevel(StoreKey.logLevel, null, 5), // Level.INFO = 5 @@ -42,7 +42,7 @@ enum AppSettingsEnum { mapRelativeDate(StoreKey.mapRelativeDate, null, 0), allowSelfSignedSSLCert(StoreKey.selfSignedCert, null, false), ignoreIcloudAssets(StoreKey.ignoreIcloudAssets, null, false), - selectedAlbumSortReverse(StoreKey.selectedAlbumSortReverse, null, false), + selectedAlbumSortReverse(StoreKey.selectedAlbumSortReverse, null, true), enableHapticFeedback(StoreKey.enableHapticFeedback, null, true), syncAlbums(StoreKey.syncAlbums, null, false), autoEndpointSwitching(StoreKey.autoEndpointSwitching, null, false), diff --git a/mobile/lib/utils/action_button.utils.dart b/mobile/lib/utils/action_button.utils.dart index 42729becc9..1a2883bee7 100644 --- a/mobile/lib/utils/action_button.utils.dart +++ b/mobile/lib/utils/action_button.utils.dart @@ -1,9 +1,17 @@ -import 'package:flutter/widgets.dart'; +import 'package:auto_route/auto_route.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/constants/enums.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/events.model.dart'; +import 'package:immich_mobile/domain/services/timeline.service.dart'; +import 'package:immich_mobile/domain/utils/event_stream.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/advanced_info_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/archive_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/base_action_button.widget.dart'; +import 'package:immich_mobile/presentation/widgets/action_buttons/cast_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_local_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/delete_permanent_action_button.widget.dart'; @@ -19,6 +27,7 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/trash_action_b import 'package:immich_mobile/presentation/widgets/action_buttons/unarchive_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/unstack_action_button.widget.dart'; import 'package:immich_mobile/presentation/widgets/action_buttons/upload_action_button.widget.dart'; +import 'package:immich_mobile/routing/router.dart'; class ActionButtonContext { final BaseAsset asset; @@ -30,6 +39,9 @@ class ActionButtonContext { final RemoteAlbum? currentAlbum; final bool advancedTroubleshooting; final ActionSource source; + final bool isCasting; + final TimelineOrigin timelineOrigin; + final ThemeData? originalTheme; const ActionButtonContext({ required this.asset, @@ -41,27 +53,33 @@ class ActionButtonContext { required this.currentAlbum, required this.advancedTroubleshooting, required this.source, + this.isCasting = false, + this.timelineOrigin = TimelineOrigin.main, + this.originalTheme, }); } enum ActionButtonType { - advancedInfo, + openInfo, + likeActivity, share, shareLink, + cast, similarPhotos, + viewInTimeline, + download, + upload, + unstack, archive, unarchive, - download, - trash, - deletePermanent, - delete, moveToLockFolder, removeFromLockFolder, - deleteLocal, - upload, removeFromAlbum, - unstack, - likeActivity; + trash, + deleteLocal, + deletePermanent, + delete, + advancedInfo; bool shouldShow(ActionButtonContext context) { return switch (this) { @@ -128,39 +146,165 @@ enum ActionButtonType { ActionButtonType.similarPhotos => !context.isInLockedView && // context.asset is RemoteAsset, + ActionButtonType.openInfo => true, + ActionButtonType.viewInTimeline => + context.timelineOrigin != TimelineOrigin.main && + context.timelineOrigin != TimelineOrigin.deepLink && + context.timelineOrigin != TimelineOrigin.trash && + context.timelineOrigin != TimelineOrigin.lockedFolder && + context.timelineOrigin != TimelineOrigin.archive && + context.timelineOrigin != TimelineOrigin.localAlbum && + context.isOwner, + ActionButtonType.cast => context.isCasting || context.asset.hasRemote, }; } - Widget buildButton(ActionButtonContext context) { + ConsumerWidget buildButton( + ActionButtonContext context, [ + BuildContext? buildContext, + bool iconOnly = false, + bool menuItem = false, + ]) { return switch (this) { - ActionButtonType.advancedInfo => AdvancedInfoActionButton(source: context.source), - ActionButtonType.share => ShareActionButton(source: context.source), - ActionButtonType.shareLink => ShareLinkActionButton(source: context.source), - ActionButtonType.archive => ArchiveActionButton(source: context.source), - ActionButtonType.unarchive => UnArchiveActionButton(source: context.source), - ActionButtonType.download => DownloadActionButton(source: context.source), - ActionButtonType.trash => TrashActionButton(source: context.source), - ActionButtonType.deletePermanent => DeletePermanentActionButton(source: context.source), - ActionButtonType.delete => DeleteActionButton(source: context.source), - ActionButtonType.moveToLockFolder => MoveToLockFolderActionButton(source: context.source), - ActionButtonType.removeFromLockFolder => RemoveFromLockFolderActionButton(source: context.source), - ActionButtonType.deleteLocal => DeleteLocalActionButton(source: context.source), - ActionButtonType.upload => UploadActionButton(source: context.source), + ActionButtonType.advancedInfo => AdvancedInfoActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.share => ShareActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.shareLink => ShareLinkActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.archive => ArchiveActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.unarchive => UnArchiveActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.download => DownloadActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.trash => TrashActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.deletePermanent => DeletePermanentActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.delete => DeleteActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.moveToLockFolder => MoveToLockFolderActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.removeFromLockFolder => RemoveFromLockFolderActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.deleteLocal => DeleteLocalActionButton( + source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.upload => UploadActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), ActionButtonType.removeFromAlbum => RemoveFromAlbumActionButton( albumId: context.currentAlbum!.id, source: context.source, + iconOnly: iconOnly, + menuItem: menuItem, ), - ActionButtonType.likeActivity => const LikeActivityActionButton(), - ActionButtonType.unstack => UnStackActionButton(source: context.source), - ActionButtonType.similarPhotos => SimilarPhotosActionButton(assetId: (context.asset as RemoteAsset).id), + ActionButtonType.likeActivity => LikeActivityActionButton(iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.unstack => UnStackActionButton(source: context.source, iconOnly: iconOnly, menuItem: menuItem), + ActionButtonType.similarPhotos => SimilarPhotosActionButton( + assetId: (context.asset as RemoteAsset).id, + iconOnly: iconOnly, + menuItem: menuItem, + ), + ActionButtonType.openInfo => BaseActionButton( + label: 'info'.tr(), + iconData: Icons.info_outline, + iconColor: context.originalTheme?.iconTheme.color, + menuItem: true, + onPressed: () => EventStream.shared.emit(const ViewerOpenBottomSheetEvent()), + ), + ActionButtonType.viewInTimeline => BaseActionButton( + label: 'view_in_timeline'.tr(), + iconData: Icons.image_search, + iconColor: context.originalTheme?.iconTheme.color, + iconOnly: iconOnly, + menuItem: menuItem, + onPressed: buildContext == null + ? null + : () async { + await buildContext.maybePop(); + await buildContext.navigateTo(const TabShellRoute(children: [MainTimelineRoute()])); + EventStream.shared.emit(ScrollToDateEvent(context.asset.createdAt)); + }, + ), + ActionButtonType.cast => CastActionButton(iconOnly: iconOnly, menuItem: menuItem), }; } + + /// Defines which group each button belongs to for kebab menu. + /// Buttons in the same group will be displayed together, + /// with dividers separating different groups. + int get kebabMenuGroup => switch (this) { + // 0: info + ActionButtonType.openInfo => 0, + // 10: move,remove, and delete + ActionButtonType.trash => 10, + ActionButtonType.deletePermanent => 10, + ActionButtonType.removeFromLockFolder => 10, + ActionButtonType.removeFromAlbum => 10, + ActionButtonType.unstack => 10, + ActionButtonType.archive => 10, + ActionButtonType.unarchive => 10, + ActionButtonType.moveToLockFolder => 10, + ActionButtonType.deleteLocal => 10, + ActionButtonType.delete => 10, + // 90: advancedInfo + ActionButtonType.advancedInfo => 90, + // 1: others + _ => 1, + }; } class ActionButtonBuilder { static const List _actionTypes = ActionButtonType.values; + static const List defaultViewerKebabMenuOrder = _actionTypes; + static const Set defaultViewerBottomBarButtons = { + ActionButtonType.share, + ActionButtonType.moveToLockFolder, + ActionButtonType.upload, + ActionButtonType.delete, + ActionButtonType.archive, + ActionButtonType.unarchive, + }; static List build(ActionButtonContext context) { return _actionTypes.where((type) => type.shouldShow(context)).map((type) => type.buildButton(context)).toList(); } + + static List buildViewerKebabMenu(ActionButtonContext context, BuildContext buildContext, WidgetRef ref) { + final visibleButtons = defaultViewerKebabMenuOrder + .where((type) => !defaultViewerBottomBarButtons.contains(type) && type.shouldShow(context)) + .toList(); + + if (visibleButtons.isEmpty) { + return []; + } + + final List result = []; + int? lastGroup; + + for (final type in visibleButtons) { + if (lastGroup != null && type.kebabMenuGroup != lastGroup) { + result.add(const Divider(height: 1)); + } + result.add(type.buildButton(context, buildContext, false, true).build(buildContext, ref)); + lastGroup = type.kebabMenuGroup; + } + + return result; + } } diff --git a/mobile/lib/utils/migration.dart b/mobile/lib/utils/migration.dart index 552c9e356a..35cdc7addf 100644 --- a/mobile/lib/utils/migration.dart +++ b/mobile/lib/utils/migration.dart @@ -81,7 +81,7 @@ Future migrateDatabaseIfNeeded(Isar db, Drift drift) async { } if (version < 19 && Store.isBetaTimelineEnabled) { - if (!await _populateUpdatedAtTime(drift)) { + if (!await _populateLocalAssetTime(drift)) { return; } } @@ -229,7 +229,7 @@ Future _migrateDeviceAsset(Isar db) async { }); } -Future _populateUpdatedAtTime(Drift db) async { +Future _populateLocalAssetTime(Drift db) async { try { final nativeApi = NativeSyncApi(); final albums = await nativeApi.getAlbums(); @@ -240,6 +240,9 @@ Future _populateUpdatedAtTime(Drift db) async { batch.update( db.localAssetEntity, LocalAssetEntityCompanion( + longitude: Value(asset.longitude), + latitude: Value(asset.latitude), + adjustmentTime: Value(tryFromSecondsSinceEpoch(asset.adjustmentTime, isUtc: true)), updatedAt: Value(tryFromSecondsSinceEpoch(asset.updatedAt, isUtc: true) ?? DateTime.timestamp()), ), where: (t) => t.id.equals(asset.id), @@ -250,7 +253,7 @@ Future _populateUpdatedAtTime(Drift db) async { return true; } catch (error) { - dPrint(() => "[MIGRATION] Error while populating updatedAt time: $error"); + dPrint(() => "[MIGRATION] Error while populating asset time: $error"); return false; } } diff --git a/mobile/lib/widgets/activities/activity_text_field.dart b/mobile/lib/widgets/activities/activity_text_field.dart index e3958b6287..a61a284844 100644 --- a/mobile/lib/widgets/activities/activity_text_field.dart +++ b/mobile/lib/widgets/activities/activity_text_field.dart @@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/activity.provider.dart'; import 'package:immich_mobile/providers/album/current_album.provider.dart'; import 'package:immich_mobile/providers/asset_viewer/current_asset.provider.dart'; @@ -68,11 +69,11 @@ class ActivityTextField extends HookConsumerWidget { suffixIcon: Padding( padding: const EdgeInsets.only(right: 10), child: IconButton( - icon: Icon(liked ? Icons.favorite_rounded : Icons.favorite_border_rounded), + icon: Icon(liked ? Icons.thumb_up : Icons.thumb_up_off_alt), onPressed: liked ? removeLike : addLike, ), ), - suffixIconColor: liked ? Colors.red[700] : null, + suffixIconColor: liked ? context.primaryColor : null, hintText: !isEnabled ? 'shared_album_activities_input_disable'.tr() : 'say_something'.tr(), hintStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 14, color: Colors.grey[600]), ), diff --git a/mobile/lib/widgets/activities/activity_tile.dart b/mobile/lib/widgets/activities/activity_tile.dart index 6812d1b90c..76c0b7bf2a 100644 --- a/mobile/lib/widgets/activities/activity_tile.dart +++ b/mobile/lib/widgets/activities/activity_tile.dart @@ -37,7 +37,7 @@ class ActivityTile extends HookConsumerWidget { ? Container( width: isBottomSheet ? 30 : 44, alignment: Alignment.center, - child: Icon(Icons.favorite_rounded, color: Colors.red[700]), + child: Icon(Icons.thumb_up, color: context.primaryColor), ) : isBottomSheet ? UserCircleAvatar(user: activity.user, size: 30, radius: 15) diff --git a/mobile/lib/widgets/activities/comment_bubble.dart b/mobile/lib/widgets/activities/comment_bubble.dart index 11d5c21cec..3dd46cd92a 100644 --- a/mobile/lib/widgets/activities/comment_bubble.dart +++ b/mobile/lib/widgets/activities/comment_bubble.dart @@ -67,8 +67,8 @@ class CommentBubble extends ConsumerWidget { bottom: 6, child: Container( padding: const EdgeInsets.all(4), - decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle), - child: Icon(Icons.favorite, color: Colors.red[600], size: 18), + decoration: BoxDecoration(color: context.colorScheme.surfaceContainer, shape: BoxShape.circle), + child: Icon(Icons.thumb_up, color: context.primaryColor, size: 18), ), ), ], @@ -81,8 +81,8 @@ class CommentBubble extends ConsumerWidget { if (isLike && !showThumbnail) { likes = Container( padding: const EdgeInsets.all(8), - decoration: BoxDecoration(color: Colors.white.withValues(alpha: 0.7), shape: BoxShape.circle), - child: Icon(Icons.favorite, color: Colors.red[600], size: 18), + decoration: BoxDecoration(color: context.colorScheme.surfaceContainer, shape: BoxShape.circle), + child: Icon(Icons.thumb_up, color: context.primaryColor, size: 18), ); } diff --git a/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart b/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart index 6068ee022e..179eab8e7d 100644 --- a/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart +++ b/mobile/lib/widgets/common/app_bar_dialog/server_update_notification.dart @@ -53,16 +53,18 @@ class ServerUpdateNotification extends HookConsumerWidget { child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - serverInfoState.versionStatus.message, - textAlign: TextAlign.start, - maxLines: 3, - overflow: TextOverflow.ellipsis, - style: context.textTheme.labelLarge, + Expanded( + child: Text( + serverInfoState.versionStatus.message, + textAlign: TextAlign.start, + maxLines: 3, + overflow: TextOverflow.ellipsis, + style: context.textTheme.labelLarge, + ), ), if (serverInfoState.versionStatus == VersionStatus.serverOutOfDate || serverInfoState.versionStatus == VersionStatus.clientOutOfDate) ...[ - const Spacer(), + const SizedBox(width: 8), TextButton( onPressed: openUpdateLink, style: TextButton.styleFrom( diff --git a/mobile/lib/widgets/common/immich_app_bar.dart b/mobile/lib/widgets/common/immich_app_bar.dart index 2bac100807..b3dc04236c 100644 --- a/mobile/lib/widgets/common/immich_app_bar.dart +++ b/mobile/lib/widgets/common/immich_app_bar.dart @@ -155,8 +155,8 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { ...actions!.map((action) => Padding(padding: const EdgeInsets.only(right: 16), child: action)), if (kDebugMode || kProfileMode) IconButton( - icon: const Icon(Icons.science_rounded), - onPressed: () => context.pushRoute(const FeatInDevRoute()), + icon: const Icon(Icons.palette_rounded), + onPressed: () => context.pushRoute(const ImmichUIShowcaseRoute()), ), if (isCasting) Padding( diff --git a/mobile/lib/widgets/common/immich_sliver_app_bar.dart b/mobile/lib/widgets/common/immich_sliver_app_bar.dart index f68d5c9fda..dd985ebfe2 100644 --- a/mobile/lib/widgets/common/immich_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/immich_sliver_app_bar.dart @@ -74,8 +74,8 @@ class ImmichSliverAppBar extends ConsumerWidget { ...actions!.map((action) => Padding(padding: const EdgeInsets.only(right: 16), child: action)), if ((kDebugMode || kProfileMode) && !isReadonlyModeEnabled) IconButton( - icon: const Icon(Icons.science_rounded), - onPressed: () => context.pushRoute(const FeatInDevRoute()), + icon: const Icon(Icons.palette_rounded), + onPressed: () => context.pushRoute(const ImmichUIShowcaseRoute()), ), if (showUploadButton && !isReadonlyModeEnabled) const Padding(padding: EdgeInsets.only(right: 20), child: _BackupIndicator()), diff --git a/mobile/lib/widgets/settings/beta_sync_settings/entity_count_tile.dart b/mobile/lib/widgets/settings/beta_sync_settings/entity_count_tile.dart index ac357c2dee..d9a0bae606 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/entity_count_tile.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/entity_count_tile.dart @@ -2,26 +2,27 @@ import 'package:flutter/material.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/extensions/theme_extensions.dart'; -class EntitiyCountTile extends StatelessWidget { +class EntityCountTile extends StatelessWidget { final int count; final String label; final IconData icon; - const EntitiyCountTile({super.key, required this.count, required this.label, required this.icon}); + const EntityCountTile({super.key, required this.count, required this.label, required this.icon}); String zeroPadding(int number, int targetWidth) { final numStr = number.toString(); return numStr.length < targetWidth ? "0" * (targetWidth - numStr.length) : ""; } - int calculateMaxDigits(double availableWidth) { - const double charWidth = 11.0; - return (availableWidth / charWidth).floor().clamp(1, 8); - } - @override Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + final availableWidth = (screenWidth - 32 - 8) / 2; + const double charWidth = 11.0; + final maxDigits = ((availableWidth - 32) / charWidth).floor().clamp(1, 8); + return Container( + height: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: context.colorScheme.surfaceContainerLow, @@ -29,7 +30,6 @@ class EntitiyCountTile extends StatelessWidget { border: Border.all(width: 0.5, color: context.colorScheme.outline.withAlpha(25)), ), child: Column( - mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ // Icon and Label @@ -38,33 +38,30 @@ class EntitiyCountTile extends StatelessWidget { children: [ Icon(icon, color: context.primaryColor), const SizedBox(width: 8), - Text( - label, - style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16), + Flexible( + child: Text( + label, + style: TextStyle(color: context.primaryColor, fontWeight: FontWeight.bold, fontSize: 16), + ), ), ], ), - const SizedBox(height: 12), // Number - LayoutBuilder( - builder: (context, constraints) { - final maxDigits = calculateMaxDigits(constraints.maxWidth); - return RichText( - text: TextSpan( - style: const TextStyle(fontSize: 18, fontFamily: 'OverpassMono', fontWeight: FontWeight.w600), - children: [ - TextSpan( - text: zeroPadding(count, maxDigits), - style: TextStyle(color: context.colorScheme.onSurfaceSecondary.withAlpha(75)), - ), - TextSpan( - text: count.toString(), - style: TextStyle(color: context.primaryColor), - ), - ], + const Spacer(), + RichText( + text: TextSpan( + style: const TextStyle(fontSize: 18, fontFamily: 'OverpassMono', fontWeight: FontWeight.w600), + children: [ + TextSpan( + text: zeroPadding(count, maxDigits), + style: TextStyle(color: context.colorScheme.onSurfaceSecondary.withAlpha(75)), ), - ); - }, + TextSpan( + text: count.toString(), + style: TextStyle(color: context.primaryColor), + ), + ], + ), ), ], ), diff --git a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart index 64c3d9b832..d4730951c0 100644 --- a/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart +++ b/mobile/lib/widgets/settings/beta_sync_settings/sync_status_and_actions.dart @@ -282,76 +282,87 @@ class _SyncStatsCounts extends ConsumerWidget { _SectionHeaderText(text: "assets".t(context: context)), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "local".t(context: context), - count: localAssetCount, - icon: Icons.smartphone, + // 1. Wrap in IntrinsicHeight + child: IntrinsicHeight( + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + // 2. Stretch children vertically to fill the IntrinsicHeight + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 8.0, + children: [ + Expanded( + child: EntityCountTile( + label: "local".t(context: context), + count: localAssetCount, + icon: Icons.smartphone, + ), ), - ), - Expanded( - child: EntitiyCountTile( - label: "remote".t(context: context), - count: remoteAssetCount, - icon: Icons.cloud, + Expanded( + child: EntityCountTile( + label: "remote".t(context: context), + count: remoteAssetCount, + icon: Icons.cloud, + ), ), - ), - ], + ], + ), ), ), _SectionHeaderText(text: "albums".t(context: context)), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "local".t(context: context), - count: localAlbumCount, - icon: Icons.smartphone, + child: IntrinsicHeight( + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.stretch, // Added + spacing: 8.0, + children: [ + Expanded( + child: EntityCountTile( + label: "local".t(context: context), + count: localAlbumCount, + icon: Icons.smartphone, + ), ), - ), - Expanded( - child: EntitiyCountTile( - label: "remote".t(context: context), - count: remoteAlbumCount, - icon: Icons.cloud, + Expanded( + child: EntityCountTile( + label: "remote".t(context: context), + count: remoteAlbumCount, + icon: Icons.cloud, + ), ), - ), - ], + ], + ), ), ), _SectionHeaderText(text: "other".t(context: context)), Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "memories".t(context: context), - count: memoryCount, - icon: Icons.calendar_today, + child: IntrinsicHeight( + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.stretch, // Added + spacing: 8.0, + children: [ + Expanded( + child: EntityCountTile( + label: "memories".t(context: context), + count: memoryCount, + icon: Icons.calendar_today, + ), ), - ), - Expanded( - child: EntitiyCountTile( - label: "hashed_assets".t(context: context), - count: localHashedCount, - icon: Icons.tag, + Expanded( + child: EntityCountTile( + label: "hashed_assets".t(context: context), + count: localHashedCount, + icon: Icons.tag, + ), ), - ), - ], + ], + ), ), ), // To be removed once the experimental feature is stable @@ -364,26 +375,29 @@ class _SyncStatsCounts extends ConsumerWidget { return counts.when( data: (c) => Padding( padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), - child: Flex( - direction: Axis.horizontal, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - spacing: 8.0, - children: [ - Expanded( - child: EntitiyCountTile( - label: "local".t(context: context), - count: c.total, - icon: Icons.delete_outline, + child: IntrinsicHeight( + child: Flex( + direction: Axis.horizontal, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.stretch, // Added + spacing: 8.0, + children: [ + Expanded( + child: EntityCountTile( + label: "local".t(context: context), + count: c.total, + icon: Icons.delete_outline, + ), ), - ), - Expanded( - child: EntitiyCountTile( - label: "hashed_assets".t(context: context), - count: c.hashed, - icon: Icons.tag, + Expanded( + child: EntityCountTile( + label: "hashed_assets".t(context: context), + count: c.hashed, + icon: Icons.tag, + ), ), - ), - ], + ], + ), ), ), loading: () => const CircularProgressIndicator(), diff --git a/mobile/packages/ui/lib/immich_ui.dart b/mobile/packages/ui/lib/immich_ui.dart new file mode 100644 index 0000000000..2417149f76 --- /dev/null +++ b/mobile/packages/ui/lib/immich_ui.dart @@ -0,0 +1,3 @@ +export 'src/buttons/close_button.dart'; +export 'src/buttons/icon_button.dart'; +export 'src/types.dart'; diff --git a/mobile/packages/ui/lib/src/buttons/close_button.dart b/mobile/packages/ui/lib/src/buttons/close_button.dart new file mode 100644 index 0000000000..c8c5d62a12 --- /dev/null +++ b/mobile/packages/ui/lib/src/buttons/close_button.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:immich_ui/src/buttons/icon_button.dart'; +import 'package:immich_ui/src/types.dart'; + +class ImmichCloseButton extends StatelessWidget { + final VoidCallback? onTap; + final ImmichVariant variant; + final ImmichColor color; + + const ImmichCloseButton({ + super.key, + this.onTap, + this.color = ImmichColor.primary, + this.variant = ImmichVariant.ghost, + }); + + @override + Widget build(BuildContext context) => ImmichIconButton( + key: key, + icon: Icons.close, + color: color, + variant: variant, + onTap: onTap ?? () => Navigator.of(context).pop(), + ); +} diff --git a/mobile/packages/ui/lib/src/buttons/icon_button.dart b/mobile/packages/ui/lib/src/buttons/icon_button.dart new file mode 100644 index 0000000000..5c62ee8eda --- /dev/null +++ b/mobile/packages/ui/lib/src/buttons/icon_button.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:immich_ui/src/types.dart'; + +class ImmichIconButton extends StatelessWidget { + final IconData icon; + final VoidCallback onTap; + final ImmichVariant variant; + final ImmichColor color; + + const ImmichIconButton({ + super.key, + required this.icon, + required this.onTap, + this.color = ImmichColor.primary, + this.variant = ImmichVariant.filled, + }); + + @override + Widget build(BuildContext context) { + final background = switch (variant) { + ImmichVariant.filled => switch (color) { + ImmichColor.primary => Theme.of(context).colorScheme.primary, + ImmichColor.secondary => Theme.of(context).colorScheme.secondary, + }, + ImmichVariant.ghost => Colors.transparent, + }; + + final foreground = switch (variant) { + ImmichVariant.filled => switch (color) { + ImmichColor.primary => Theme.of(context).colorScheme.onPrimary, + ImmichColor.secondary => Theme.of(context).colorScheme.onSecondary, + }, + ImmichVariant.ghost => switch (color) { + ImmichColor.primary => Theme.of(context).colorScheme.primary, + ImmichColor.secondary => Theme.of(context).colorScheme.secondary, + }, + }; + + return IconButton( + icon: Icon(icon), + onPressed: onTap, + style: IconButton.styleFrom( + backgroundColor: background, + foregroundColor: foreground, + ), + ); + } +} diff --git a/mobile/packages/ui/lib/src/types.dart b/mobile/packages/ui/lib/src/types.dart new file mode 100644 index 0000000000..2c0c7b7760 --- /dev/null +++ b/mobile/packages/ui/lib/src/types.dart @@ -0,0 +1,9 @@ +enum ImmichVariant { + filled, + ghost, +} + +enum ImmichColor { + primary, + secondary, +} diff --git a/mobile/packages/ui/pubspec.lock b/mobile/packages/ui/pubspec.lock new file mode 100644 index 0000000000..b9d150f174 --- /dev/null +++ b/mobile/packages/ui/pubspec.lock @@ -0,0 +1,55 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" + source: hosted + version: "1.16.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" +sdks: + dart: ">=3.8.0-0 <4.0.0" diff --git a/mobile/packages/ui/pubspec.yaml b/mobile/packages/ui/pubspec.yaml new file mode 100644 index 0000000000..47b9a9dd8a --- /dev/null +++ b/mobile/packages/ui/pubspec.yaml @@ -0,0 +1,12 @@ +name: immich_ui +publish_to: none + +environment: + sdk: '>=3.0.0 <4.0.0' + +dependencies: + flutter: + sdk: flutter + +flutter: + uses-material-design: true \ No newline at end of file diff --git a/mobile/pigeon/native_sync_api.dart b/mobile/pigeon/native_sync_api.dart index 822e2eddb3..ec28afb008 100644 --- a/mobile/pigeon/native_sync_api.dart +++ b/mobile/pigeon/native_sync_api.dart @@ -27,6 +27,10 @@ class PlatformAsset { final int orientation; final bool isFavorite; + final int? adjustmentTime; + final double? latitude; + final double? longitude; + const PlatformAsset({ required this.id, required this.name, @@ -38,6 +42,9 @@ class PlatformAsset { this.durationInSeconds = 0, this.orientation = 0, this.isFavorite = false, + this.adjustmentTime, + this.latitude, + this.longitude, }); } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 6a067f509f..3179d71bd1 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1015,6 +1015,13 @@ packages: relative: true source: path version: "0.0.0" + immich_ui: + dependency: "direct main" + description: + path: "packages/ui" + relative: true + source: path + version: "0.0.0" integration_test: dependency: "direct dev" description: flutter diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index a49a012031..1633a54cb6 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -43,6 +43,8 @@ dependencies: hooks_riverpod: ^2.6.1 http: ^1.5.0 image_picker: ^1.2.0 + immich_ui: + path: './packages/ui' intl: ^0.20.2 isar: git: diff --git a/mobile/test/drift/main/generated/schema.dart b/mobile/test/drift/main/generated/schema.dart index 69dff89fb1..5e19610574 100644 --- a/mobile/test/drift/main/generated/schema.dart +++ b/mobile/test/drift/main/generated/schema.dart @@ -16,6 +16,7 @@ import 'schema_v10.dart' as v10; import 'schema_v11.dart' as v11; import 'schema_v12.dart' as v12; import 'schema_v13.dart' as v13; +import 'schema_v14.dart' as v14; class GeneratedHelper implements SchemaInstantiationHelper { @override @@ -47,10 +48,12 @@ class GeneratedHelper implements SchemaInstantiationHelper { return v12.DatabaseAtV12(db); case 13: return v13.DatabaseAtV13(db); + case 14: + return v14.DatabaseAtV14(db); default: throw MissingSchemaException(version, versions); } } - static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; + static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]; } diff --git a/mobile/test/drift/main/generated/schema_v14.dart b/mobile/test/drift/main/generated/schema_v14.dart new file mode 100644 index 0000000000..242aa581f3 --- /dev/null +++ b/mobile/test/drift/main/generated/schema_v14.dart @@ -0,0 +1,7878 @@ +// dart format width=80 +// GENERATED CODE, DO NOT EDIT BY HAND. +// ignore_for_file: type=lint +import 'package:drift/drift.dart'; + +class UserEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_entity'; + @override + Set get $primaryKey => {id}; + @override + UserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + ); + } + + @override + UserEntity createAlias(String alias) { + return UserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserEntityData extends DataClass implements Insertable { + final String id; + final String name; + final String email; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + const UserEntityData({ + required this.id, + required this.name, + required this.email, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + return map; + } + + factory UserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + }; + } + + UserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + }) => UserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + UserEntityData copyWithCompanion(UserEntityCompanion data) { + return UserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + ); + } + + @override + String toString() { + return (StringBuffer('UserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + hasProfileImage, + profileChangedAt, + avatarColor, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor); +} + +class UserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + const UserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }); + UserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + }); + } + + UserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + }) { + return UserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor') + ..write(')')) + .toString(); + } +} + +class RemoteAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn localDateTime = + GeneratedColumn( + 'local_date_time', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn thumbHash = GeneratedColumn( + 'thumb_hash', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn livePhotoVideoId = GeneratedColumn( + 'live_photo_video_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn visibility = GeneratedColumn( + 'visibility', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stackId = GeneratedColumn( + 'stack_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn libraryId = GeneratedColumn( + 'library_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + )!, + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + localDateTime: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}local_date_time'], + ), + thumbHash: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumb_hash'], + ), + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + livePhotoVideoId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}live_photo_video_id'], + ), + visibility: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}visibility'], + )!, + stackId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}stack_id'], + ), + libraryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}library_id'], + ), + ); + } + + @override + RemoteAssetEntity createAlias(String alias) { + return RemoteAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String checksum; + final bool isFavorite; + final String ownerId; + final DateTime? localDateTime; + final String? thumbHash; + final DateTime? deletedAt; + final String? livePhotoVideoId; + final int visibility; + final String? stackId; + final String? libraryId; + const RemoteAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + required this.checksum, + required this.isFavorite, + required this.ownerId, + this.localDateTime, + this.thumbHash, + this.deletedAt, + this.livePhotoVideoId, + required this.visibility, + this.stackId, + this.libraryId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + map['checksum'] = Variable(checksum); + map['is_favorite'] = Variable(isFavorite); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || localDateTime != null) { + map['local_date_time'] = Variable(localDateTime); + } + if (!nullToAbsent || thumbHash != null) { + map['thumb_hash'] = Variable(thumbHash); + } + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + if (!nullToAbsent || livePhotoVideoId != null) { + map['live_photo_video_id'] = Variable(livePhotoVideoId); + } + map['visibility'] = Variable(visibility); + if (!nullToAbsent || stackId != null) { + map['stack_id'] = Variable(stackId); + } + if (!nullToAbsent || libraryId != null) { + map['library_id'] = Variable(libraryId); + } + return map; + } + + factory RemoteAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + ownerId: serializer.fromJson(json['ownerId']), + localDateTime: serializer.fromJson(json['localDateTime']), + thumbHash: serializer.fromJson(json['thumbHash']), + deletedAt: serializer.fromJson(json['deletedAt']), + livePhotoVideoId: serializer.fromJson(json['livePhotoVideoId']), + visibility: serializer.fromJson(json['visibility']), + stackId: serializer.fromJson(json['stackId']), + libraryId: serializer.fromJson(json['libraryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'ownerId': serializer.toJson(ownerId), + 'localDateTime': serializer.toJson(localDateTime), + 'thumbHash': serializer.toJson(thumbHash), + 'deletedAt': serializer.toJson(deletedAt), + 'livePhotoVideoId': serializer.toJson(livePhotoVideoId), + 'visibility': serializer.toJson(visibility), + 'stackId': serializer.toJson(stackId), + 'libraryId': serializer.toJson(libraryId), + }; + } + + RemoteAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + String? checksum, + bool? isFavorite, + String? ownerId, + Value localDateTime = const Value.absent(), + Value thumbHash = const Value.absent(), + Value deletedAt = const Value.absent(), + Value livePhotoVideoId = const Value.absent(), + int? visibility, + Value stackId = const Value.absent(), + Value libraryId = const Value.absent(), + }) => RemoteAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime.present + ? localDateTime.value + : this.localDateTime, + thumbHash: thumbHash.present ? thumbHash.value : this.thumbHash, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + livePhotoVideoId: livePhotoVideoId.present + ? livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId.present ? stackId.value : this.stackId, + libraryId: libraryId.present ? libraryId.value : this.libraryId, + ); + RemoteAssetEntityData copyWithCompanion(RemoteAssetEntityCompanion data) { + return RemoteAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + localDateTime: data.localDateTime.present + ? data.localDateTime.value + : this.localDateTime, + thumbHash: data.thumbHash.present ? data.thumbHash.value : this.thumbHash, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + livePhotoVideoId: data.livePhotoVideoId.present + ? data.livePhotoVideoId.value + : this.livePhotoVideoId, + visibility: data.visibility.present + ? data.visibility.value + : this.visibility, + stackId: data.stackId.present ? data.stackId.value : this.stackId, + libraryId: data.libraryId.present ? data.libraryId.value : this.libraryId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + ownerId, + localDateTime, + thumbHash, + deletedAt, + livePhotoVideoId, + visibility, + stackId, + libraryId, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.ownerId == this.ownerId && + other.localDateTime == this.localDateTime && + other.thumbHash == this.thumbHash && + other.deletedAt == this.deletedAt && + other.livePhotoVideoId == this.livePhotoVideoId && + other.visibility == this.visibility && + other.stackId == this.stackId && + other.libraryId == this.libraryId); +} + +class RemoteAssetEntityCompanion + extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value ownerId; + final Value localDateTime; + final Value thumbHash; + final Value deletedAt; + final Value livePhotoVideoId; + final Value visibility; + final Value stackId; + final Value libraryId; + const RemoteAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.ownerId = const Value.absent(), + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + this.visibility = const Value.absent(), + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }); + RemoteAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + required String checksum, + this.isFavorite = const Value.absent(), + required String ownerId, + this.localDateTime = const Value.absent(), + this.thumbHash = const Value.absent(), + this.deletedAt = const Value.absent(), + this.livePhotoVideoId = const Value.absent(), + required int visibility, + this.stackId = const Value.absent(), + this.libraryId = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id), + checksum = Value(checksum), + ownerId = Value(ownerId), + visibility = Value(visibility); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? ownerId, + Expression? localDateTime, + Expression? thumbHash, + Expression? deletedAt, + Expression? livePhotoVideoId, + Expression? visibility, + Expression? stackId, + Expression? libraryId, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (ownerId != null) 'owner_id': ownerId, + if (localDateTime != null) 'local_date_time': localDateTime, + if (thumbHash != null) 'thumb_hash': thumbHash, + if (deletedAt != null) 'deleted_at': deletedAt, + if (livePhotoVideoId != null) 'live_photo_video_id': livePhotoVideoId, + if (visibility != null) 'visibility': visibility, + if (stackId != null) 'stack_id': stackId, + if (libraryId != null) 'library_id': libraryId, + }); + } + + RemoteAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? ownerId, + Value? localDateTime, + Value? thumbHash, + Value? deletedAt, + Value? livePhotoVideoId, + Value? visibility, + Value? stackId, + Value? libraryId, + }) { + return RemoteAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + ownerId: ownerId ?? this.ownerId, + localDateTime: localDateTime ?? this.localDateTime, + thumbHash: thumbHash ?? this.thumbHash, + deletedAt: deletedAt ?? this.deletedAt, + livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId, + visibility: visibility ?? this.visibility, + stackId: stackId ?? this.stackId, + libraryId: libraryId ?? this.libraryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (localDateTime.present) { + map['local_date_time'] = Variable(localDateTime.value); + } + if (thumbHash.present) { + map['thumb_hash'] = Variable(thumbHash.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (livePhotoVideoId.present) { + map['live_photo_video_id'] = Variable(livePhotoVideoId.value); + } + if (visibility.present) { + map['visibility'] = Variable(visibility.value); + } + if (stackId.present) { + map['stack_id'] = Variable(stackId.value); + } + if (libraryId.present) { + map['library_id'] = Variable(libraryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('ownerId: $ownerId, ') + ..write('localDateTime: $localDateTime, ') + ..write('thumbHash: $thumbHash, ') + ..write('deletedAt: $deletedAt, ') + ..write('livePhotoVideoId: $livePhotoVideoId, ') + ..write('visibility: $visibility, ') + ..write('stackId: $stackId, ') + ..write('libraryId: $libraryId') + ..write(')')) + .toString(); + } +} + +class StackEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StackEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn primaryAssetId = GeneratedColumn( + 'primary_asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + primaryAssetId, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'stack_entity'; + @override + Set get $primaryKey => {id}; + @override + StackEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StackEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + primaryAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}primary_asset_id'], + )!, + ); + } + + @override + StackEntity createAlias(String alias) { + return StackEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StackEntityData extends DataClass implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String primaryAssetId; + const StackEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.primaryAssetId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['primary_asset_id'] = Variable(primaryAssetId); + return map; + } + + factory StackEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StackEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + primaryAssetId: serializer.fromJson(json['primaryAssetId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'primaryAssetId': serializer.toJson(primaryAssetId), + }; + } + + StackEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? primaryAssetId, + }) => StackEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + StackEntityData copyWithCompanion(StackEntityCompanion data) { + return StackEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + primaryAssetId: data.primaryAssetId.present + ? data.primaryAssetId.value + : this.primaryAssetId, + ); + } + + @override + String toString() { + return (StringBuffer('StackEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(id, createdAt, updatedAt, ownerId, primaryAssetId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StackEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.primaryAssetId == this.primaryAssetId); +} + +class StackEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value primaryAssetId; + const StackEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.primaryAssetId = const Value.absent(), + }); + StackEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String primaryAssetId, + }) : id = Value(id), + ownerId = Value(ownerId), + primaryAssetId = Value(primaryAssetId); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? primaryAssetId, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (primaryAssetId != null) 'primary_asset_id': primaryAssetId, + }); + } + + StackEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? primaryAssetId, + }) { + return StackEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + primaryAssetId: primaryAssetId ?? this.primaryAssetId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (primaryAssetId.present) { + map['primary_asset_id'] = Variable(primaryAssetId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StackEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('primaryAssetId: $primaryAssetId') + ..write(')')) + .toString(); + } +} + +class LocalAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn adjustmentTime = + GeneratedColumn( + 'adjustment_time', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn latitude = GeneratedColumn( + 'latitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn longitude = GeneratedColumn( + 'longitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + adjustmentTime, + latitude, + longitude, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_asset_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}orientation'], + )!, + adjustmentTime: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}adjustment_time'], + ), + latitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}latitude'], + ), + longitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}longitude'], + ), + ); + } + + @override + LocalAssetEntity createAlias(String alias) { + return LocalAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String? checksum; + final bool isFavorite; + final int orientation; + final DateTime? adjustmentTime; + final double? latitude; + final double? longitude; + const LocalAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + this.checksum, + required this.isFavorite, + required this.orientation, + this.adjustmentTime, + this.latitude, + this.longitude, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + if (!nullToAbsent || checksum != null) { + map['checksum'] = Variable(checksum); + } + map['is_favorite'] = Variable(isFavorite); + map['orientation'] = Variable(orientation); + if (!nullToAbsent || adjustmentTime != null) { + map['adjustment_time'] = Variable(adjustmentTime); + } + if (!nullToAbsent || latitude != null) { + map['latitude'] = Variable(latitude); + } + if (!nullToAbsent || longitude != null) { + map['longitude'] = Variable(longitude); + } + return map; + } + + factory LocalAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + orientation: serializer.fromJson(json['orientation']), + adjustmentTime: serializer.fromJson(json['adjustmentTime']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'orientation': serializer.toJson(orientation), + 'adjustmentTime': serializer.toJson(adjustmentTime), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), + }; + } + + LocalAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + Value checksum = const Value.absent(), + bool? isFavorite, + int? orientation, + Value adjustmentTime = const Value.absent(), + Value latitude = const Value.absent(), + Value longitude = const Value.absent(), + }) => LocalAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + checksum: checksum.present ? checksum.value : this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + adjustmentTime: adjustmentTime.present + ? adjustmentTime.value + : this.adjustmentTime, + latitude: latitude.present ? latitude.value : this.latitude, + longitude: longitude.present ? longitude.value : this.longitude, + ); + LocalAssetEntityData copyWithCompanion(LocalAssetEntityCompanion data) { + return LocalAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + adjustmentTime: data.adjustmentTime.present + ? data.adjustmentTime.value + : this.adjustmentTime, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation, ') + ..write('adjustmentTime: $adjustmentTime, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + checksum, + isFavorite, + orientation, + adjustmentTime, + latitude, + longitude, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.orientation == this.orientation && + other.adjustmentTime == this.adjustmentTime && + other.latitude == this.latitude && + other.longitude == this.longitude); +} + +class LocalAssetEntityCompanion extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value checksum; + final Value isFavorite; + final Value orientation; + final Value adjustmentTime; + final Value latitude; + final Value longitude; + const LocalAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + this.adjustmentTime = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + }); + LocalAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + this.adjustmentTime = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? checksum, + Expression? isFavorite, + Expression? orientation, + Expression? adjustmentTime, + Expression? latitude, + Expression? longitude, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (orientation != null) 'orientation': orientation, + if (adjustmentTime != null) 'adjustment_time': adjustmentTime, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, + }); + } + + LocalAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? checksum, + Value? isFavorite, + Value? orientation, + Value? adjustmentTime, + Value? latitude, + Value? longitude, + }) { + return LocalAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + adjustmentTime: adjustmentTime ?? this.adjustmentTime, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + if (adjustmentTime.present) { + map['adjustment_time'] = Variable(adjustmentTime.value); + } + if (latitude.present) { + map['latitude'] = Variable(latitude.value); + } + if (longitude.present) { + map['longitude'] = Variable(longitude.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation, ') + ..write('adjustmentTime: $adjustmentTime, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultValue: const CustomExpression('\'\''), + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn thumbnailAssetId = GeneratedColumn( + 'thumbnail_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn isActivityEnabled = GeneratedColumn( + 'is_activity_enabled', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_activity_enabled" IN (0, 1))', + ), + defaultValue: const CustomExpression('1'), + ); + late final GeneratedColumn order = GeneratedColumn( + 'order', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_entity'; + @override + Set get $primaryKey => {id}; + @override + RemoteAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + thumbnailAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}thumbnail_asset_id'], + ), + isActivityEnabled: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_activity_enabled'], + )!, + order: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}order'], + )!, + ); + } + + @override + RemoteAlbumEntity createAlias(String alias) { + return RemoteAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String description; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String? thumbnailAssetId; + final bool isActivityEnabled; + final int order; + const RemoteAlbumEntityData({ + required this.id, + required this.name, + required this.description, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + this.thumbnailAssetId, + required this.isActivityEnabled, + required this.order, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['description'] = Variable(description); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + if (!nullToAbsent || thumbnailAssetId != null) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId); + } + map['is_activity_enabled'] = Variable(isActivityEnabled); + map['order'] = Variable(order); + return map; + } + + factory RemoteAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + thumbnailAssetId: serializer.fromJson(json['thumbnailAssetId']), + isActivityEnabled: serializer.fromJson(json['isActivityEnabled']), + order: serializer.fromJson(json['order']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'thumbnailAssetId': serializer.toJson(thumbnailAssetId), + 'isActivityEnabled': serializer.toJson(isActivityEnabled), + 'order': serializer.toJson(order), + }; + } + + RemoteAlbumEntityData copyWith({ + String? id, + String? name, + String? description, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + Value thumbnailAssetId = const Value.absent(), + bool? isActivityEnabled, + int? order, + }) => RemoteAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId.present + ? thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + RemoteAlbumEntityData copyWithCompanion(RemoteAlbumEntityCompanion data) { + return RemoteAlbumEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + description: data.description.present + ? data.description.value + : this.description, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + thumbnailAssetId: data.thumbnailAssetId.present + ? data.thumbnailAssetId.value + : this.thumbnailAssetId, + isActivityEnabled: data.isActivityEnabled.present + ? data.isActivityEnabled.value + : this.isActivityEnabled, + order: data.order.present ? data.order.value : this.order, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + description, + createdAt, + updatedAt, + ownerId, + thumbnailAssetId, + isActivityEnabled, + order, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.description == this.description && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.thumbnailAssetId == this.thumbnailAssetId && + other.isActivityEnabled == this.isActivityEnabled && + other.order == this.order); +} + +class RemoteAlbumEntityCompanion + extends UpdateCompanion { + final Value id; + final Value name; + final Value description; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value thumbnailAssetId; + final Value isActivityEnabled; + final Value order; + const RemoteAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + this.order = const Value.absent(), + }); + RemoteAlbumEntityCompanion.insert({ + required String id, + required String name, + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + this.thumbnailAssetId = const Value.absent(), + this.isActivityEnabled = const Value.absent(), + required int order, + }) : id = Value(id), + name = Value(name), + ownerId = Value(ownerId), + order = Value(order); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? description, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? thumbnailAssetId, + Expression? isActivityEnabled, + Expression? order, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (thumbnailAssetId != null) 'thumbnail_asset_id': thumbnailAssetId, + if (isActivityEnabled != null) 'is_activity_enabled': isActivityEnabled, + if (order != null) 'order': order, + }); + } + + RemoteAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? description, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? thumbnailAssetId, + Value? isActivityEnabled, + Value? order, + }) { + return RemoteAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + thumbnailAssetId: thumbnailAssetId ?? this.thumbnailAssetId, + isActivityEnabled: isActivityEnabled ?? this.isActivityEnabled, + order: order ?? this.order, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (thumbnailAssetId.present) { + map['thumbnail_asset_id'] = Variable(thumbnailAssetId.value); + } + if (isActivityEnabled.present) { + map['is_activity_enabled'] = Variable(isActivityEnabled.value); + } + if (order.present) { + map['order'] = Variable(order.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('thumbnailAssetId: $thumbnailAssetId, ') + ..write('isActivityEnabled: $isActivityEnabled, ') + ..write('order: $order') + ..write(')')) + .toString(); + } +} + +class LocalAlbumEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn backupSelection = GeneratedColumn( + 'backup_selection', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn isIosSharedAlbum = GeneratedColumn( + 'is_ios_shared_album', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_ios_shared_album" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn linkedRemoteAlbumId = + GeneratedColumn( + 'linked_remote_album_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [ + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_entity'; + @override + Set get $primaryKey => {id}; + @override + LocalAlbumEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + backupSelection: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}backup_selection'], + )!, + isIosSharedAlbum: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_ios_shared_album'], + )!, + linkedRemoteAlbumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}linked_remote_album_id'], + ), + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumEntity createAlias(String alias) { + return LocalAlbumEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final DateTime updatedAt; + final int backupSelection; + final bool isIosSharedAlbum; + final String? linkedRemoteAlbumId; + final bool? marker_; + const LocalAlbumEntityData({ + required this.id, + required this.name, + required this.updatedAt, + required this.backupSelection, + required this.isIosSharedAlbum, + this.linkedRemoteAlbumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['updated_at'] = Variable(updatedAt); + map['backup_selection'] = Variable(backupSelection); + map['is_ios_shared_album'] = Variable(isIosSharedAlbum); + if (!nullToAbsent || linkedRemoteAlbumId != null) { + map['linked_remote_album_id'] = Variable(linkedRemoteAlbumId); + } + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + updatedAt: serializer.fromJson(json['updatedAt']), + backupSelection: serializer.fromJson(json['backupSelection']), + isIosSharedAlbum: serializer.fromJson(json['isIosSharedAlbum']), + linkedRemoteAlbumId: serializer.fromJson( + json['linkedRemoteAlbumId'], + ), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'updatedAt': serializer.toJson(updatedAt), + 'backupSelection': serializer.toJson(backupSelection), + 'isIosSharedAlbum': serializer.toJson(isIosSharedAlbum), + 'linkedRemoteAlbumId': serializer.toJson(linkedRemoteAlbumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumEntityData copyWith({ + String? id, + String? name, + DateTime? updatedAt, + int? backupSelection, + bool? isIosSharedAlbum, + Value linkedRemoteAlbumId = const Value.absent(), + Value marker_ = const Value.absent(), + }) => LocalAlbumEntityData( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId.present + ? linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumEntityData copyWithCompanion(LocalAlbumEntityCompanion data) { + return LocalAlbumEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + backupSelection: data.backupSelection.present + ? data.backupSelection.value + : this.backupSelection, + isIosSharedAlbum: data.isIosSharedAlbum.present + ? data.isIosSharedAlbum.value + : this.isIosSharedAlbum, + linkedRemoteAlbumId: data.linkedRemoteAlbumId.present + ? data.linkedRemoteAlbumId.value + : this.linkedRemoteAlbumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + updatedAt, + backupSelection, + isIosSharedAlbum, + linkedRemoteAlbumId, + marker_, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumEntityData && + other.id == this.id && + other.name == this.name && + other.updatedAt == this.updatedAt && + other.backupSelection == this.backupSelection && + other.isIosSharedAlbum == this.isIosSharedAlbum && + other.linkedRemoteAlbumId == this.linkedRemoteAlbumId && + other.marker_ == this.marker_); +} + +class LocalAlbumEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value updatedAt; + final Value backupSelection; + final Value isIosSharedAlbum; + final Value linkedRemoteAlbumId; + final Value marker_; + const LocalAlbumEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.updatedAt = const Value.absent(), + this.backupSelection = const Value.absent(), + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumEntityCompanion.insert({ + required String id, + required String name, + this.updatedAt = const Value.absent(), + required int backupSelection, + this.isIosSharedAlbum = const Value.absent(), + this.linkedRemoteAlbumId = const Value.absent(), + this.marker_ = const Value.absent(), + }) : id = Value(id), + name = Value(name), + backupSelection = Value(backupSelection); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? updatedAt, + Expression? backupSelection, + Expression? isIosSharedAlbum, + Expression? linkedRemoteAlbumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (updatedAt != null) 'updated_at': updatedAt, + if (backupSelection != null) 'backup_selection': backupSelection, + if (isIosSharedAlbum != null) 'is_ios_shared_album': isIosSharedAlbum, + if (linkedRemoteAlbumId != null) + 'linked_remote_album_id': linkedRemoteAlbumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumEntityCompanion copyWith({ + Value? id, + Value? name, + Value? updatedAt, + Value? backupSelection, + Value? isIosSharedAlbum, + Value? linkedRemoteAlbumId, + Value? marker_, + }) { + return LocalAlbumEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + updatedAt: updatedAt ?? this.updatedAt, + backupSelection: backupSelection ?? this.backupSelection, + isIosSharedAlbum: isIosSharedAlbum ?? this.isIosSharedAlbum, + linkedRemoteAlbumId: linkedRemoteAlbumId ?? this.linkedRemoteAlbumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (backupSelection.present) { + map['backup_selection'] = Variable(backupSelection.value); + } + if (isIosSharedAlbum.present) { + map['is_ios_shared_album'] = Variable(isIosSharedAlbum.value); + } + if (linkedRemoteAlbumId.present) { + map['linked_remote_album_id'] = Variable( + linkedRemoteAlbumId.value, + ); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('updatedAt: $updatedAt, ') + ..write('backupSelection: $backupSelection, ') + ..write('isIosSharedAlbum: $isIosSharedAlbum, ') + ..write('linkedRemoteAlbumId: $linkedRemoteAlbumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class LocalAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + LocalAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES local_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn marker_ = GeneratedColumn( + 'marker', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("marker" IN (0, 1))', + ), + ); + @override + List get $columns => [assetId, albumId, marker_]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'local_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + LocalAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return LocalAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + marker_: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}marker'], + ), + ); + } + + @override + LocalAlbumAssetEntity createAlias(String alias) { + return LocalAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class LocalAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + final bool? marker_; + const LocalAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + this.marker_, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + if (!nullToAbsent || marker_ != null) { + map['marker'] = Variable(marker_); + } + return map; + } + + factory LocalAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return LocalAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + marker_: serializer.fromJson(json['marker_']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + 'marker_': serializer.toJson(marker_), + }; + } + + LocalAlbumAssetEntityData copyWith({ + String? assetId, + String? albumId, + Value marker_ = const Value.absent(), + }) => LocalAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_.present ? marker_.value : this.marker_, + ); + LocalAlbumAssetEntityData copyWithCompanion( + LocalAlbumAssetEntityCompanion data, + ) { + return LocalAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + marker_: data.marker_.present ? data.marker_.value : this.marker_, + ); + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId, marker_); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is LocalAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId && + other.marker_ == this.marker_); +} + +class LocalAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + final Value marker_; + const LocalAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + this.marker_ = const Value.absent(), + }); + LocalAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + this.marker_ = const Value.absent(), + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + Expression? marker_, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + if (marker_ != null) 'marker': marker_, + }); + } + + LocalAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + Value? marker_, + }) { + return LocalAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + marker_: marker_ ?? this.marker_, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (marker_.present) { + map['marker'] = Variable(marker_.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('LocalAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId, ') + ..write('marker_: $marker_') + ..write(')')) + .toString(); + } +} + +class AuthUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AuthUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn email = GeneratedColumn( + 'email', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isAdmin = GeneratedColumn( + 'is_admin', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_admin" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn hasProfileImage = GeneratedColumn( + 'has_profile_image', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("has_profile_image" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn profileChangedAt = + GeneratedColumn( + 'profile_changed_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn avatarColor = GeneratedColumn( + 'avatar_color', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn quotaSizeInBytes = GeneratedColumn( + 'quota_size_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn quotaUsageInBytes = GeneratedColumn( + 'quota_usage_in_bytes', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn pinCode = GeneratedColumn( + 'pin_code', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'auth_user_entity'; + @override + Set get $primaryKey => {id}; + @override + AuthUserEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AuthUserEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + email: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}email'], + )!, + isAdmin: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_admin'], + )!, + hasProfileImage: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}has_profile_image'], + )!, + profileChangedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}profile_changed_at'], + )!, + avatarColor: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}avatar_color'], + )!, + quotaSizeInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_size_in_bytes'], + )!, + quotaUsageInBytes: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}quota_usage_in_bytes'], + )!, + pinCode: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}pin_code'], + ), + ); + } + + @override + AuthUserEntity createAlias(String alias) { + return AuthUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AuthUserEntityData extends DataClass + implements Insertable { + final String id; + final String name; + final String email; + final bool isAdmin; + final bool hasProfileImage; + final DateTime profileChangedAt; + final int avatarColor; + final int quotaSizeInBytes; + final int quotaUsageInBytes; + final String? pinCode; + const AuthUserEntityData({ + required this.id, + required this.name, + required this.email, + required this.isAdmin, + required this.hasProfileImage, + required this.profileChangedAt, + required this.avatarColor, + required this.quotaSizeInBytes, + required this.quotaUsageInBytes, + this.pinCode, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['email'] = Variable(email); + map['is_admin'] = Variable(isAdmin); + map['has_profile_image'] = Variable(hasProfileImage); + map['profile_changed_at'] = Variable(profileChangedAt); + map['avatar_color'] = Variable(avatarColor); + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes); + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes); + if (!nullToAbsent || pinCode != null) { + map['pin_code'] = Variable(pinCode); + } + return map; + } + + factory AuthUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AuthUserEntityData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + email: serializer.fromJson(json['email']), + isAdmin: serializer.fromJson(json['isAdmin']), + hasProfileImage: serializer.fromJson(json['hasProfileImage']), + profileChangedAt: serializer.fromJson(json['profileChangedAt']), + avatarColor: serializer.fromJson(json['avatarColor']), + quotaSizeInBytes: serializer.fromJson(json['quotaSizeInBytes']), + quotaUsageInBytes: serializer.fromJson(json['quotaUsageInBytes']), + pinCode: serializer.fromJson(json['pinCode']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'email': serializer.toJson(email), + 'isAdmin': serializer.toJson(isAdmin), + 'hasProfileImage': serializer.toJson(hasProfileImage), + 'profileChangedAt': serializer.toJson(profileChangedAt), + 'avatarColor': serializer.toJson(avatarColor), + 'quotaSizeInBytes': serializer.toJson(quotaSizeInBytes), + 'quotaUsageInBytes': serializer.toJson(quotaUsageInBytes), + 'pinCode': serializer.toJson(pinCode), + }; + } + + AuthUserEntityData copyWith({ + String? id, + String? name, + String? email, + bool? isAdmin, + bool? hasProfileImage, + DateTime? profileChangedAt, + int? avatarColor, + int? quotaSizeInBytes, + int? quotaUsageInBytes, + Value pinCode = const Value.absent(), + }) => AuthUserEntityData( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode.present ? pinCode.value : this.pinCode, + ); + AuthUserEntityData copyWithCompanion(AuthUserEntityCompanion data) { + return AuthUserEntityData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + email: data.email.present ? data.email.value : this.email, + isAdmin: data.isAdmin.present ? data.isAdmin.value : this.isAdmin, + hasProfileImage: data.hasProfileImage.present + ? data.hasProfileImage.value + : this.hasProfileImage, + profileChangedAt: data.profileChangedAt.present + ? data.profileChangedAt.value + : this.profileChangedAt, + avatarColor: data.avatarColor.present + ? data.avatarColor.value + : this.avatarColor, + quotaSizeInBytes: data.quotaSizeInBytes.present + ? data.quotaSizeInBytes.value + : this.quotaSizeInBytes, + quotaUsageInBytes: data.quotaUsageInBytes.present + ? data.quotaUsageInBytes.value + : this.quotaUsageInBytes, + pinCode: data.pinCode.present ? data.pinCode.value : this.pinCode, + ); + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + name, + email, + isAdmin, + hasProfileImage, + profileChangedAt, + avatarColor, + quotaSizeInBytes, + quotaUsageInBytes, + pinCode, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AuthUserEntityData && + other.id == this.id && + other.name == this.name && + other.email == this.email && + other.isAdmin == this.isAdmin && + other.hasProfileImage == this.hasProfileImage && + other.profileChangedAt == this.profileChangedAt && + other.avatarColor == this.avatarColor && + other.quotaSizeInBytes == this.quotaSizeInBytes && + other.quotaUsageInBytes == this.quotaUsageInBytes && + other.pinCode == this.pinCode); +} + +class AuthUserEntityCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value email; + final Value isAdmin; + final Value hasProfileImage; + final Value profileChangedAt; + final Value avatarColor; + final Value quotaSizeInBytes; + final Value quotaUsageInBytes; + final Value pinCode; + const AuthUserEntityCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.email = const Value.absent(), + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + this.avatarColor = const Value.absent(), + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }); + AuthUserEntityCompanion.insert({ + required String id, + required String name, + required String email, + this.isAdmin = const Value.absent(), + this.hasProfileImage = const Value.absent(), + this.profileChangedAt = const Value.absent(), + required int avatarColor, + this.quotaSizeInBytes = const Value.absent(), + this.quotaUsageInBytes = const Value.absent(), + this.pinCode = const Value.absent(), + }) : id = Value(id), + name = Value(name), + email = Value(email), + avatarColor = Value(avatarColor); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? email, + Expression? isAdmin, + Expression? hasProfileImage, + Expression? profileChangedAt, + Expression? avatarColor, + Expression? quotaSizeInBytes, + Expression? quotaUsageInBytes, + Expression? pinCode, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (email != null) 'email': email, + if (isAdmin != null) 'is_admin': isAdmin, + if (hasProfileImage != null) 'has_profile_image': hasProfileImage, + if (profileChangedAt != null) 'profile_changed_at': profileChangedAt, + if (avatarColor != null) 'avatar_color': avatarColor, + if (quotaSizeInBytes != null) 'quota_size_in_bytes': quotaSizeInBytes, + if (quotaUsageInBytes != null) 'quota_usage_in_bytes': quotaUsageInBytes, + if (pinCode != null) 'pin_code': pinCode, + }); + } + + AuthUserEntityCompanion copyWith({ + Value? id, + Value? name, + Value? email, + Value? isAdmin, + Value? hasProfileImage, + Value? profileChangedAt, + Value? avatarColor, + Value? quotaSizeInBytes, + Value? quotaUsageInBytes, + Value? pinCode, + }) { + return AuthUserEntityCompanion( + id: id ?? this.id, + name: name ?? this.name, + email: email ?? this.email, + isAdmin: isAdmin ?? this.isAdmin, + hasProfileImage: hasProfileImage ?? this.hasProfileImage, + profileChangedAt: profileChangedAt ?? this.profileChangedAt, + avatarColor: avatarColor ?? this.avatarColor, + quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes, + quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes, + pinCode: pinCode ?? this.pinCode, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (email.present) { + map['email'] = Variable(email.value); + } + if (isAdmin.present) { + map['is_admin'] = Variable(isAdmin.value); + } + if (hasProfileImage.present) { + map['has_profile_image'] = Variable(hasProfileImage.value); + } + if (profileChangedAt.present) { + map['profile_changed_at'] = Variable(profileChangedAt.value); + } + if (avatarColor.present) { + map['avatar_color'] = Variable(avatarColor.value); + } + if (quotaSizeInBytes.present) { + map['quota_size_in_bytes'] = Variable(quotaSizeInBytes.value); + } + if (quotaUsageInBytes.present) { + map['quota_usage_in_bytes'] = Variable(quotaUsageInBytes.value); + } + if (pinCode.present) { + map['pin_code'] = Variable(pinCode.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AuthUserEntityCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('email: $email, ') + ..write('isAdmin: $isAdmin, ') + ..write('hasProfileImage: $hasProfileImage, ') + ..write('profileChangedAt: $profileChangedAt, ') + ..write('avatarColor: $avatarColor, ') + ..write('quotaSizeInBytes: $quotaSizeInBytes, ') + ..write('quotaUsageInBytes: $quotaUsageInBytes, ') + ..write('pinCode: $pinCode') + ..write(')')) + .toString(); + } +} + +class UserMetadataEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + UserMetadataEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn key = GeneratedColumn( + 'key', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn value = GeneratedColumn( + 'value', + aliasedName, + false, + type: DriftSqlType.blob, + requiredDuringInsert: true, + ); + @override + List get $columns => [userId, key, value]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'user_metadata_entity'; + @override + Set get $primaryKey => {userId, key}; + @override + UserMetadataEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return UserMetadataEntityData( + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + key: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}key'], + )!, + value: attachedDatabase.typeMapping.read( + DriftSqlType.blob, + data['${effectivePrefix}value'], + )!, + ); + } + + @override + UserMetadataEntity createAlias(String alias) { + return UserMetadataEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class UserMetadataEntityData extends DataClass + implements Insertable { + final String userId; + final int key; + final Uint8List value; + const UserMetadataEntityData({ + required this.userId, + required this.key, + required this.value, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['user_id'] = Variable(userId); + map['key'] = Variable(key); + map['value'] = Variable(value); + return map; + } + + factory UserMetadataEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return UserMetadataEntityData( + userId: serializer.fromJson(json['userId']), + key: serializer.fromJson(json['key']), + value: serializer.fromJson(json['value']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'userId': serializer.toJson(userId), + 'key': serializer.toJson(key), + 'value': serializer.toJson(value), + }; + } + + UserMetadataEntityData copyWith({ + String? userId, + int? key, + Uint8List? value, + }) => UserMetadataEntityData( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + UserMetadataEntityData copyWithCompanion(UserMetadataEntityCompanion data) { + return UserMetadataEntityData( + userId: data.userId.present ? data.userId.value : this.userId, + key: data.key.present ? data.key.value : this.key, + value: data.value.present ? data.value.value : this.value, + ); + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityData(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(userId, key, $driftBlobEquality.hash(value)); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is UserMetadataEntityData && + other.userId == this.userId && + other.key == this.key && + $driftBlobEquality.equals(other.value, this.value)); +} + +class UserMetadataEntityCompanion + extends UpdateCompanion { + final Value userId; + final Value key; + final Value value; + const UserMetadataEntityCompanion({ + this.userId = const Value.absent(), + this.key = const Value.absent(), + this.value = const Value.absent(), + }); + UserMetadataEntityCompanion.insert({ + required String userId, + required int key, + required Uint8List value, + }) : userId = Value(userId), + key = Value(key), + value = Value(value); + static Insertable custom({ + Expression? userId, + Expression? key, + Expression? value, + }) { + return RawValuesInsertable({ + if (userId != null) 'user_id': userId, + if (key != null) 'key': key, + if (value != null) 'value': value, + }); + } + + UserMetadataEntityCompanion copyWith({ + Value? userId, + Value? key, + Value? value, + }) { + return UserMetadataEntityCompanion( + userId: userId ?? this.userId, + key: key ?? this.key, + value: value ?? this.value, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (key.present) { + map['key'] = Variable(key.value); + } + if (value.present) { + map['value'] = Variable(value.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('UserMetadataEntityCompanion(') + ..write('userId: $userId, ') + ..write('key: $key, ') + ..write('value: $value') + ..write(')')) + .toString(); + } +} + +class PartnerEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PartnerEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn sharedById = GeneratedColumn( + 'shared_by_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn sharedWithId = GeneratedColumn( + 'shared_with_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn inTimeline = GeneratedColumn( + 'in_timeline', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("in_timeline" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [sharedById, sharedWithId, inTimeline]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'partner_entity'; + @override + Set get $primaryKey => {sharedById, sharedWithId}; + @override + PartnerEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PartnerEntityData( + sharedById: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_by_id'], + )!, + sharedWithId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}shared_with_id'], + )!, + inTimeline: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}in_timeline'], + )!, + ); + } + + @override + PartnerEntity createAlias(String alias) { + return PartnerEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PartnerEntityData extends DataClass + implements Insertable { + final String sharedById; + final String sharedWithId; + final bool inTimeline; + const PartnerEntityData({ + required this.sharedById, + required this.sharedWithId, + required this.inTimeline, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['shared_by_id'] = Variable(sharedById); + map['shared_with_id'] = Variable(sharedWithId); + map['in_timeline'] = Variable(inTimeline); + return map; + } + + factory PartnerEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PartnerEntityData( + sharedById: serializer.fromJson(json['sharedById']), + sharedWithId: serializer.fromJson(json['sharedWithId']), + inTimeline: serializer.fromJson(json['inTimeline']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'sharedById': serializer.toJson(sharedById), + 'sharedWithId': serializer.toJson(sharedWithId), + 'inTimeline': serializer.toJson(inTimeline), + }; + } + + PartnerEntityData copyWith({ + String? sharedById, + String? sharedWithId, + bool? inTimeline, + }) => PartnerEntityData( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + PartnerEntityData copyWithCompanion(PartnerEntityCompanion data) { + return PartnerEntityData( + sharedById: data.sharedById.present + ? data.sharedById.value + : this.sharedById, + sharedWithId: data.sharedWithId.present + ? data.sharedWithId.value + : this.sharedWithId, + inTimeline: data.inTimeline.present + ? data.inTimeline.value + : this.inTimeline, + ); + } + + @override + String toString() { + return (StringBuffer('PartnerEntityData(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(sharedById, sharedWithId, inTimeline); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PartnerEntityData && + other.sharedById == this.sharedById && + other.sharedWithId == this.sharedWithId && + other.inTimeline == this.inTimeline); +} + +class PartnerEntityCompanion extends UpdateCompanion { + final Value sharedById; + final Value sharedWithId; + final Value inTimeline; + const PartnerEntityCompanion({ + this.sharedById = const Value.absent(), + this.sharedWithId = const Value.absent(), + this.inTimeline = const Value.absent(), + }); + PartnerEntityCompanion.insert({ + required String sharedById, + required String sharedWithId, + this.inTimeline = const Value.absent(), + }) : sharedById = Value(sharedById), + sharedWithId = Value(sharedWithId); + static Insertable custom({ + Expression? sharedById, + Expression? sharedWithId, + Expression? inTimeline, + }) { + return RawValuesInsertable({ + if (sharedById != null) 'shared_by_id': sharedById, + if (sharedWithId != null) 'shared_with_id': sharedWithId, + if (inTimeline != null) 'in_timeline': inTimeline, + }); + } + + PartnerEntityCompanion copyWith({ + Value? sharedById, + Value? sharedWithId, + Value? inTimeline, + }) { + return PartnerEntityCompanion( + sharedById: sharedById ?? this.sharedById, + sharedWithId: sharedWithId ?? this.sharedWithId, + inTimeline: inTimeline ?? this.inTimeline, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (sharedById.present) { + map['shared_by_id'] = Variable(sharedById.value); + } + if (sharedWithId.present) { + map['shared_with_id'] = Variable(sharedWithId.value); + } + if (inTimeline.present) { + map['in_timeline'] = Variable(inTimeline.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PartnerEntityCompanion(') + ..write('sharedById: $sharedById, ') + ..write('sharedWithId: $sharedWithId, ') + ..write('inTimeline: $inTimeline') + ..write(')')) + .toString(); + } +} + +class RemoteExifEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteExifEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn city = GeneratedColumn( + 'city', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn state = GeneratedColumn( + 'state', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn country = GeneratedColumn( + 'country', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn dateTimeOriginal = + GeneratedColumn( + 'date_time_original', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn exposureTime = GeneratedColumn( + 'exposure_time', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn fNumber = GeneratedColumn( + 'f_number', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn fileSize = GeneratedColumn( + 'file_size', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn focalLength = GeneratedColumn( + 'focal_length', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn latitude = GeneratedColumn( + 'latitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn longitude = GeneratedColumn( + 'longitude', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + late final GeneratedColumn iso = GeneratedColumn( + 'iso', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn make = GeneratedColumn( + 'make', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn model = GeneratedColumn( + 'model', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn lens = GeneratedColumn( + 'lens', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn timeZone = GeneratedColumn( + 'time_zone', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn rating = GeneratedColumn( + 'rating', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn projectionType = GeneratedColumn( + 'projection_type', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_exif_entity'; + @override + Set get $primaryKey => {assetId}; + @override + RemoteExifEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteExifEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + city: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}city'], + ), + state: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}state'], + ), + country: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}country'], + ), + dateTimeOriginal: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}date_time_original'], + ), + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + exposureTime: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}exposure_time'], + ), + fNumber: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}f_number'], + ), + fileSize: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}file_size'], + ), + focalLength: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}focal_length'], + ), + latitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}latitude'], + ), + longitude: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}longitude'], + ), + iso: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}iso'], + ), + make: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}make'], + ), + model: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}model'], + ), + lens: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}lens'], + ), + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}orientation'], + ), + timeZone: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}time_zone'], + ), + rating: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}rating'], + ), + projectionType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}projection_type'], + ), + ); + } + + @override + RemoteExifEntity createAlias(String alias) { + return RemoteExifEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteExifEntityData extends DataClass + implements Insertable { + final String assetId; + final String? city; + final String? state; + final String? country; + final DateTime? dateTimeOriginal; + final String? description; + final int? height; + final int? width; + final String? exposureTime; + final double? fNumber; + final int? fileSize; + final double? focalLength; + final double? latitude; + final double? longitude; + final int? iso; + final String? make; + final String? model; + final String? lens; + final String? orientation; + final String? timeZone; + final int? rating; + final String? projectionType; + const RemoteExifEntityData({ + required this.assetId, + this.city, + this.state, + this.country, + this.dateTimeOriginal, + this.description, + this.height, + this.width, + this.exposureTime, + this.fNumber, + this.fileSize, + this.focalLength, + this.latitude, + this.longitude, + this.iso, + this.make, + this.model, + this.lens, + this.orientation, + this.timeZone, + this.rating, + this.projectionType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || city != null) { + map['city'] = Variable(city); + } + if (!nullToAbsent || state != null) { + map['state'] = Variable(state); + } + if (!nullToAbsent || country != null) { + map['country'] = Variable(country); + } + if (!nullToAbsent || dateTimeOriginal != null) { + map['date_time_original'] = Variable(dateTimeOriginal); + } + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || exposureTime != null) { + map['exposure_time'] = Variable(exposureTime); + } + if (!nullToAbsent || fNumber != null) { + map['f_number'] = Variable(fNumber); + } + if (!nullToAbsent || fileSize != null) { + map['file_size'] = Variable(fileSize); + } + if (!nullToAbsent || focalLength != null) { + map['focal_length'] = Variable(focalLength); + } + if (!nullToAbsent || latitude != null) { + map['latitude'] = Variable(latitude); + } + if (!nullToAbsent || longitude != null) { + map['longitude'] = Variable(longitude); + } + if (!nullToAbsent || iso != null) { + map['iso'] = Variable(iso); + } + if (!nullToAbsent || make != null) { + map['make'] = Variable(make); + } + if (!nullToAbsent || model != null) { + map['model'] = Variable(model); + } + if (!nullToAbsent || lens != null) { + map['lens'] = Variable(lens); + } + if (!nullToAbsent || orientation != null) { + map['orientation'] = Variable(orientation); + } + if (!nullToAbsent || timeZone != null) { + map['time_zone'] = Variable(timeZone); + } + if (!nullToAbsent || rating != null) { + map['rating'] = Variable(rating); + } + if (!nullToAbsent || projectionType != null) { + map['projection_type'] = Variable(projectionType); + } + return map; + } + + factory RemoteExifEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteExifEntityData( + assetId: serializer.fromJson(json['assetId']), + city: serializer.fromJson(json['city']), + state: serializer.fromJson(json['state']), + country: serializer.fromJson(json['country']), + dateTimeOriginal: serializer.fromJson( + json['dateTimeOriginal'], + ), + description: serializer.fromJson(json['description']), + height: serializer.fromJson(json['height']), + width: serializer.fromJson(json['width']), + exposureTime: serializer.fromJson(json['exposureTime']), + fNumber: serializer.fromJson(json['fNumber']), + fileSize: serializer.fromJson(json['fileSize']), + focalLength: serializer.fromJson(json['focalLength']), + latitude: serializer.fromJson(json['latitude']), + longitude: serializer.fromJson(json['longitude']), + iso: serializer.fromJson(json['iso']), + make: serializer.fromJson(json['make']), + model: serializer.fromJson(json['model']), + lens: serializer.fromJson(json['lens']), + orientation: serializer.fromJson(json['orientation']), + timeZone: serializer.fromJson(json['timeZone']), + rating: serializer.fromJson(json['rating']), + projectionType: serializer.fromJson(json['projectionType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'city': serializer.toJson(city), + 'state': serializer.toJson(state), + 'country': serializer.toJson(country), + 'dateTimeOriginal': serializer.toJson(dateTimeOriginal), + 'description': serializer.toJson(description), + 'height': serializer.toJson(height), + 'width': serializer.toJson(width), + 'exposureTime': serializer.toJson(exposureTime), + 'fNumber': serializer.toJson(fNumber), + 'fileSize': serializer.toJson(fileSize), + 'focalLength': serializer.toJson(focalLength), + 'latitude': serializer.toJson(latitude), + 'longitude': serializer.toJson(longitude), + 'iso': serializer.toJson(iso), + 'make': serializer.toJson(make), + 'model': serializer.toJson(model), + 'lens': serializer.toJson(lens), + 'orientation': serializer.toJson(orientation), + 'timeZone': serializer.toJson(timeZone), + 'rating': serializer.toJson(rating), + 'projectionType': serializer.toJson(projectionType), + }; + } + + RemoteExifEntityData copyWith({ + String? assetId, + Value city = const Value.absent(), + Value state = const Value.absent(), + Value country = const Value.absent(), + Value dateTimeOriginal = const Value.absent(), + Value description = const Value.absent(), + Value height = const Value.absent(), + Value width = const Value.absent(), + Value exposureTime = const Value.absent(), + Value fNumber = const Value.absent(), + Value fileSize = const Value.absent(), + Value focalLength = const Value.absent(), + Value latitude = const Value.absent(), + Value longitude = const Value.absent(), + Value iso = const Value.absent(), + Value make = const Value.absent(), + Value model = const Value.absent(), + Value lens = const Value.absent(), + Value orientation = const Value.absent(), + Value timeZone = const Value.absent(), + Value rating = const Value.absent(), + Value projectionType = const Value.absent(), + }) => RemoteExifEntityData( + assetId: assetId ?? this.assetId, + city: city.present ? city.value : this.city, + state: state.present ? state.value : this.state, + country: country.present ? country.value : this.country, + dateTimeOriginal: dateTimeOriginal.present + ? dateTimeOriginal.value + : this.dateTimeOriginal, + description: description.present ? description.value : this.description, + height: height.present ? height.value : this.height, + width: width.present ? width.value : this.width, + exposureTime: exposureTime.present ? exposureTime.value : this.exposureTime, + fNumber: fNumber.present ? fNumber.value : this.fNumber, + fileSize: fileSize.present ? fileSize.value : this.fileSize, + focalLength: focalLength.present ? focalLength.value : this.focalLength, + latitude: latitude.present ? latitude.value : this.latitude, + longitude: longitude.present ? longitude.value : this.longitude, + iso: iso.present ? iso.value : this.iso, + make: make.present ? make.value : this.make, + model: model.present ? model.value : this.model, + lens: lens.present ? lens.value : this.lens, + orientation: orientation.present ? orientation.value : this.orientation, + timeZone: timeZone.present ? timeZone.value : this.timeZone, + rating: rating.present ? rating.value : this.rating, + projectionType: projectionType.present + ? projectionType.value + : this.projectionType, + ); + RemoteExifEntityData copyWithCompanion(RemoteExifEntityCompanion data) { + return RemoteExifEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + city: data.city.present ? data.city.value : this.city, + state: data.state.present ? data.state.value : this.state, + country: data.country.present ? data.country.value : this.country, + dateTimeOriginal: data.dateTimeOriginal.present + ? data.dateTimeOriginal.value + : this.dateTimeOriginal, + description: data.description.present + ? data.description.value + : this.description, + height: data.height.present ? data.height.value : this.height, + width: data.width.present ? data.width.value : this.width, + exposureTime: data.exposureTime.present + ? data.exposureTime.value + : this.exposureTime, + fNumber: data.fNumber.present ? data.fNumber.value : this.fNumber, + fileSize: data.fileSize.present ? data.fileSize.value : this.fileSize, + focalLength: data.focalLength.present + ? data.focalLength.value + : this.focalLength, + latitude: data.latitude.present ? data.latitude.value : this.latitude, + longitude: data.longitude.present ? data.longitude.value : this.longitude, + iso: data.iso.present ? data.iso.value : this.iso, + make: data.make.present ? data.make.value : this.make, + model: data.model.present ? data.model.value : this.model, + lens: data.lens.present ? data.lens.value : this.lens, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + timeZone: data.timeZone.present ? data.timeZone.value : this.timeZone, + rating: data.rating.present ? data.rating.value : this.rating, + projectionType: data.projectionType.present + ? data.projectionType.value + : this.projectionType, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityData(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hashAll([ + assetId, + city, + state, + country, + dateTimeOriginal, + description, + height, + width, + exposureTime, + fNumber, + fileSize, + focalLength, + latitude, + longitude, + iso, + make, + model, + lens, + orientation, + timeZone, + rating, + projectionType, + ]); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteExifEntityData && + other.assetId == this.assetId && + other.city == this.city && + other.state == this.state && + other.country == this.country && + other.dateTimeOriginal == this.dateTimeOriginal && + other.description == this.description && + other.height == this.height && + other.width == this.width && + other.exposureTime == this.exposureTime && + other.fNumber == this.fNumber && + other.fileSize == this.fileSize && + other.focalLength == this.focalLength && + other.latitude == this.latitude && + other.longitude == this.longitude && + other.iso == this.iso && + other.make == this.make && + other.model == this.model && + other.lens == this.lens && + other.orientation == this.orientation && + other.timeZone == this.timeZone && + other.rating == this.rating && + other.projectionType == this.projectionType); +} + +class RemoteExifEntityCompanion extends UpdateCompanion { + final Value assetId; + final Value city; + final Value state; + final Value country; + final Value dateTimeOriginal; + final Value description; + final Value height; + final Value width; + final Value exposureTime; + final Value fNumber; + final Value fileSize; + final Value focalLength; + final Value latitude; + final Value longitude; + final Value iso; + final Value make; + final Value model; + final Value lens; + final Value orientation; + final Value timeZone; + final Value rating; + final Value projectionType; + const RemoteExifEntityCompanion({ + this.assetId = const Value.absent(), + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }); + RemoteExifEntityCompanion.insert({ + required String assetId, + this.city = const Value.absent(), + this.state = const Value.absent(), + this.country = const Value.absent(), + this.dateTimeOriginal = const Value.absent(), + this.description = const Value.absent(), + this.height = const Value.absent(), + this.width = const Value.absent(), + this.exposureTime = const Value.absent(), + this.fNumber = const Value.absent(), + this.fileSize = const Value.absent(), + this.focalLength = const Value.absent(), + this.latitude = const Value.absent(), + this.longitude = const Value.absent(), + this.iso = const Value.absent(), + this.make = const Value.absent(), + this.model = const Value.absent(), + this.lens = const Value.absent(), + this.orientation = const Value.absent(), + this.timeZone = const Value.absent(), + this.rating = const Value.absent(), + this.projectionType = const Value.absent(), + }) : assetId = Value(assetId); + static Insertable custom({ + Expression? assetId, + Expression? city, + Expression? state, + Expression? country, + Expression? dateTimeOriginal, + Expression? description, + Expression? height, + Expression? width, + Expression? exposureTime, + Expression? fNumber, + Expression? fileSize, + Expression? focalLength, + Expression? latitude, + Expression? longitude, + Expression? iso, + Expression? make, + Expression? model, + Expression? lens, + Expression? orientation, + Expression? timeZone, + Expression? rating, + Expression? projectionType, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (city != null) 'city': city, + if (state != null) 'state': state, + if (country != null) 'country': country, + if (dateTimeOriginal != null) 'date_time_original': dateTimeOriginal, + if (description != null) 'description': description, + if (height != null) 'height': height, + if (width != null) 'width': width, + if (exposureTime != null) 'exposure_time': exposureTime, + if (fNumber != null) 'f_number': fNumber, + if (fileSize != null) 'file_size': fileSize, + if (focalLength != null) 'focal_length': focalLength, + if (latitude != null) 'latitude': latitude, + if (longitude != null) 'longitude': longitude, + if (iso != null) 'iso': iso, + if (make != null) 'make': make, + if (model != null) 'model': model, + if (lens != null) 'lens': lens, + if (orientation != null) 'orientation': orientation, + if (timeZone != null) 'time_zone': timeZone, + if (rating != null) 'rating': rating, + if (projectionType != null) 'projection_type': projectionType, + }); + } + + RemoteExifEntityCompanion copyWith({ + Value? assetId, + Value? city, + Value? state, + Value? country, + Value? dateTimeOriginal, + Value? description, + Value? height, + Value? width, + Value? exposureTime, + Value? fNumber, + Value? fileSize, + Value? focalLength, + Value? latitude, + Value? longitude, + Value? iso, + Value? make, + Value? model, + Value? lens, + Value? orientation, + Value? timeZone, + Value? rating, + Value? projectionType, + }) { + return RemoteExifEntityCompanion( + assetId: assetId ?? this.assetId, + city: city ?? this.city, + state: state ?? this.state, + country: country ?? this.country, + dateTimeOriginal: dateTimeOriginal ?? this.dateTimeOriginal, + description: description ?? this.description, + height: height ?? this.height, + width: width ?? this.width, + exposureTime: exposureTime ?? this.exposureTime, + fNumber: fNumber ?? this.fNumber, + fileSize: fileSize ?? this.fileSize, + focalLength: focalLength ?? this.focalLength, + latitude: latitude ?? this.latitude, + longitude: longitude ?? this.longitude, + iso: iso ?? this.iso, + make: make ?? this.make, + model: model ?? this.model, + lens: lens ?? this.lens, + orientation: orientation ?? this.orientation, + timeZone: timeZone ?? this.timeZone, + rating: rating ?? this.rating, + projectionType: projectionType ?? this.projectionType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (city.present) { + map['city'] = Variable(city.value); + } + if (state.present) { + map['state'] = Variable(state.value); + } + if (country.present) { + map['country'] = Variable(country.value); + } + if (dateTimeOriginal.present) { + map['date_time_original'] = Variable(dateTimeOriginal.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (exposureTime.present) { + map['exposure_time'] = Variable(exposureTime.value); + } + if (fNumber.present) { + map['f_number'] = Variable(fNumber.value); + } + if (fileSize.present) { + map['file_size'] = Variable(fileSize.value); + } + if (focalLength.present) { + map['focal_length'] = Variable(focalLength.value); + } + if (latitude.present) { + map['latitude'] = Variable(latitude.value); + } + if (longitude.present) { + map['longitude'] = Variable(longitude.value); + } + if (iso.present) { + map['iso'] = Variable(iso.value); + } + if (make.present) { + map['make'] = Variable(make.value); + } + if (model.present) { + map['model'] = Variable(model.value); + } + if (lens.present) { + map['lens'] = Variable(lens.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + if (timeZone.present) { + map['time_zone'] = Variable(timeZone.value); + } + if (rating.present) { + map['rating'] = Variable(rating.value); + } + if (projectionType.present) { + map['projection_type'] = Variable(projectionType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteExifEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('city: $city, ') + ..write('state: $state, ') + ..write('country: $country, ') + ..write('dateTimeOriginal: $dateTimeOriginal, ') + ..write('description: $description, ') + ..write('height: $height, ') + ..write('width: $width, ') + ..write('exposureTime: $exposureTime, ') + ..write('fNumber: $fNumber, ') + ..write('fileSize: $fileSize, ') + ..write('focalLength: $focalLength, ') + ..write('latitude: $latitude, ') + ..write('longitude: $longitude, ') + ..write('iso: $iso, ') + ..write('make: $make, ') + ..write('model: $model, ') + ..write('lens: $lens, ') + ..write('orientation: $orientation, ') + ..write('timeZone: $timeZone, ') + ..write('rating: $rating, ') + ..write('projectionType: $projectionType') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, albumId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_asset_entity'; + @override + Set get $primaryKey => {assetId, albumId}; + @override + RemoteAlbumAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + ); + } + + @override + RemoteAlbumAssetEntity createAlias(String alias) { + return RemoteAlbumAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String albumId; + const RemoteAlbumAssetEntityData({ + required this.assetId, + required this.albumId, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['album_id'] = Variable(albumId); + return map; + } + + factory RemoteAlbumAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + albumId: serializer.fromJson(json['albumId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'albumId': serializer.toJson(albumId), + }; + } + + RemoteAlbumAssetEntityData copyWith({String? assetId, String? albumId}) => + RemoteAlbumAssetEntityData( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + RemoteAlbumAssetEntityData copyWithCompanion( + RemoteAlbumAssetEntityCompanion data, + ) { + return RemoteAlbumAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, albumId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumAssetEntityData && + other.assetId == this.assetId && + other.albumId == this.albumId); +} + +class RemoteAlbumAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value albumId; + const RemoteAlbumAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.albumId = const Value.absent(), + }); + RemoteAlbumAssetEntityCompanion.insert({ + required String assetId, + required String albumId, + }) : assetId = Value(assetId), + albumId = Value(albumId); + static Insertable custom({ + Expression? assetId, + Expression? albumId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (albumId != null) 'album_id': albumId, + }); + } + + RemoteAlbumAssetEntityCompanion copyWith({ + Value? assetId, + Value? albumId, + }) { + return RemoteAlbumAssetEntityCompanion( + assetId: assetId ?? this.assetId, + albumId: albumId ?? this.albumId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('albumId: $albumId') + ..write(')')) + .toString(); + } +} + +class RemoteAlbumUserEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + RemoteAlbumUserEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_album_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn userId = GeneratedColumn( + 'user_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn role = GeneratedColumn( + 'role', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [albumId, userId, role]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'remote_album_user_entity'; + @override + Set get $primaryKey => {albumId, userId}; + @override + RemoteAlbumUserEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return RemoteAlbumUserEntityData( + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + userId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}user_id'], + )!, + role: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}role'], + )!, + ); + } + + @override + RemoteAlbumUserEntity createAlias(String alias) { + return RemoteAlbumUserEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class RemoteAlbumUserEntityData extends DataClass + implements Insertable { + final String albumId; + final String userId; + final int role; + const RemoteAlbumUserEntityData({ + required this.albumId, + required this.userId, + required this.role, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['album_id'] = Variable(albumId); + map['user_id'] = Variable(userId); + map['role'] = Variable(role); + return map; + } + + factory RemoteAlbumUserEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return RemoteAlbumUserEntityData( + albumId: serializer.fromJson(json['albumId']), + userId: serializer.fromJson(json['userId']), + role: serializer.fromJson(json['role']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'albumId': serializer.toJson(albumId), + 'userId': serializer.toJson(userId), + 'role': serializer.toJson(role), + }; + } + + RemoteAlbumUserEntityData copyWith({ + String? albumId, + String? userId, + int? role, + }) => RemoteAlbumUserEntityData( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + RemoteAlbumUserEntityData copyWithCompanion( + RemoteAlbumUserEntityCompanion data, + ) { + return RemoteAlbumUserEntityData( + albumId: data.albumId.present ? data.albumId.value : this.albumId, + userId: data.userId.present ? data.userId.value : this.userId, + role: data.role.present ? data.role.value : this.role, + ); + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityData(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(albumId, userId, role); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is RemoteAlbumUserEntityData && + other.albumId == this.albumId && + other.userId == this.userId && + other.role == this.role); +} + +class RemoteAlbumUserEntityCompanion + extends UpdateCompanion { + final Value albumId; + final Value userId; + final Value role; + const RemoteAlbumUserEntityCompanion({ + this.albumId = const Value.absent(), + this.userId = const Value.absent(), + this.role = const Value.absent(), + }); + RemoteAlbumUserEntityCompanion.insert({ + required String albumId, + required String userId, + required int role, + }) : albumId = Value(albumId), + userId = Value(userId), + role = Value(role); + static Insertable custom({ + Expression? albumId, + Expression? userId, + Expression? role, + }) { + return RawValuesInsertable({ + if (albumId != null) 'album_id': albumId, + if (userId != null) 'user_id': userId, + if (role != null) 'role': role, + }); + } + + RemoteAlbumUserEntityCompanion copyWith({ + Value? albumId, + Value? userId, + Value? role, + }) { + return RemoteAlbumUserEntityCompanion( + albumId: albumId ?? this.albumId, + userId: userId ?? this.userId, + role: role ?? this.role, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (userId.present) { + map['user_id'] = Variable(userId.value); + } + if (role.present) { + map['role'] = Variable(role.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('RemoteAlbumUserEntityCompanion(') + ..write('albumId: $albumId, ') + ..write('userId: $userId, ') + ..write('role: $role') + ..write(')')) + .toString(); + } +} + +class MemoryEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn deletedAt = GeneratedColumn( + 'deleted_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn data = GeneratedColumn( + 'data', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn isSaved = GeneratedColumn( + 'is_saved', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_saved" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn memoryAt = GeneratedColumn( + 'memory_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + late final GeneratedColumn seenAt = GeneratedColumn( + 'seen_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn showAt = GeneratedColumn( + 'show_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + late final GeneratedColumn hideAt = GeneratedColumn( + 'hide_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_entity'; + @override + Set get $primaryKey => {id}; + @override + MemoryEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + deletedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}deleted_at'], + ), + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + data: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}data'], + )!, + isSaved: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_saved'], + )!, + memoryAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}memory_at'], + )!, + seenAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}seen_at'], + ), + showAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}show_at'], + ), + hideAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}hide_at'], + ), + ); + } + + @override + MemoryEntity createAlias(String alias) { + return MemoryEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final String ownerId; + final int type; + final String data; + final bool isSaved; + final DateTime memoryAt; + final DateTime? seenAt; + final DateTime? showAt; + final DateTime? hideAt; + const MemoryEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + required this.ownerId, + required this.type, + required this.data, + required this.isSaved, + required this.memoryAt, + this.seenAt, + this.showAt, + this.hideAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = Variable(deletedAt); + } + map['owner_id'] = Variable(ownerId); + map['type'] = Variable(type); + map['data'] = Variable(data); + map['is_saved'] = Variable(isSaved); + map['memory_at'] = Variable(memoryAt); + if (!nullToAbsent || seenAt != null) { + map['seen_at'] = Variable(seenAt); + } + if (!nullToAbsent || showAt != null) { + map['show_at'] = Variable(showAt); + } + if (!nullToAbsent || hideAt != null) { + map['hide_at'] = Variable(hideAt); + } + return map; + } + + factory MemoryEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + ownerId: serializer.fromJson(json['ownerId']), + type: serializer.fromJson(json['type']), + data: serializer.fromJson(json['data']), + isSaved: serializer.fromJson(json['isSaved']), + memoryAt: serializer.fromJson(json['memoryAt']), + seenAt: serializer.fromJson(json['seenAt']), + showAt: serializer.fromJson(json['showAt']), + hideAt: serializer.fromJson(json['hideAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'ownerId': serializer.toJson(ownerId), + 'type': serializer.toJson(type), + 'data': serializer.toJson(data), + 'isSaved': serializer.toJson(isSaved), + 'memoryAt': serializer.toJson(memoryAt), + 'seenAt': serializer.toJson(seenAt), + 'showAt': serializer.toJson(showAt), + 'hideAt': serializer.toJson(hideAt), + }; + } + + MemoryEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + Value deletedAt = const Value.absent(), + String? ownerId, + int? type, + String? data, + bool? isSaved, + DateTime? memoryAt, + Value seenAt = const Value.absent(), + Value showAt = const Value.absent(), + Value hideAt = const Value.absent(), + }) => MemoryEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt.present ? seenAt.value : this.seenAt, + showAt: showAt.present ? showAt.value : this.showAt, + hideAt: hideAt.present ? hideAt.value : this.hideAt, + ); + MemoryEntityData copyWithCompanion(MemoryEntityCompanion data) { + return MemoryEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + type: data.type.present ? data.type.value : this.type, + data: data.data.present ? data.data.value : this.data, + isSaved: data.isSaved.present ? data.isSaved.value : this.isSaved, + memoryAt: data.memoryAt.present ? data.memoryAt.value : this.memoryAt, + seenAt: data.seenAt.present ? data.seenAt.value : this.seenAt, + showAt: data.showAt.present ? data.showAt.value : this.showAt, + hideAt: data.hideAt.present ? data.hideAt.value : this.hideAt, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.ownerId == this.ownerId && + other.type == this.type && + other.data == this.data && + other.isSaved == this.isSaved && + other.memoryAt == this.memoryAt && + other.seenAt == this.seenAt && + other.showAt == this.showAt && + other.hideAt == this.hideAt); +} + +class MemoryEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value deletedAt; + final Value ownerId; + final Value type; + final Value data; + final Value isSaved; + final Value memoryAt; + final Value seenAt; + final Value showAt; + final Value hideAt; + const MemoryEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.type = const Value.absent(), + this.data = const Value.absent(), + this.isSaved = const Value.absent(), + this.memoryAt = const Value.absent(), + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }); + MemoryEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.deletedAt = const Value.absent(), + required String ownerId, + required int type, + required String data, + this.isSaved = const Value.absent(), + required DateTime memoryAt, + this.seenAt = const Value.absent(), + this.showAt = const Value.absent(), + this.hideAt = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + type = Value(type), + data = Value(data), + memoryAt = Value(memoryAt); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? deletedAt, + Expression? ownerId, + Expression? type, + Expression? data, + Expression? isSaved, + Expression? memoryAt, + Expression? seenAt, + Expression? showAt, + Expression? hideAt, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (ownerId != null) 'owner_id': ownerId, + if (type != null) 'type': type, + if (data != null) 'data': data, + if (isSaved != null) 'is_saved': isSaved, + if (memoryAt != null) 'memory_at': memoryAt, + if (seenAt != null) 'seen_at': seenAt, + if (showAt != null) 'show_at': showAt, + if (hideAt != null) 'hide_at': hideAt, + }); + } + + MemoryEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? deletedAt, + Value? ownerId, + Value? type, + Value? data, + Value? isSaved, + Value? memoryAt, + Value? seenAt, + Value? showAt, + Value? hideAt, + }) { + return MemoryEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt ?? this.seenAt, + showAt: showAt ?? this.showAt, + hideAt: hideAt ?? this.hideAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = Variable(deletedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (data.present) { + map['data'] = Variable(data.value); + } + if (isSaved.present) { + map['is_saved'] = Variable(isSaved.value); + } + if (memoryAt.present) { + map['memory_at'] = Variable(memoryAt.value); + } + if (seenAt.present) { + map['seen_at'] = Variable(seenAt.value); + } + if (showAt.present) { + map['show_at'] = Variable(showAt.value); + } + if (hideAt.present) { + map['hide_at'] = Variable(hideAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } +} + +class MemoryAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + MemoryAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn memoryId = GeneratedColumn( + 'memory_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES memory_entity (id) ON DELETE CASCADE', + ), + ); + @override + List get $columns => [assetId, memoryId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_asset_entity'; + @override + Set get $primaryKey => {assetId, memoryId}; + @override + MemoryAssetEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MemoryAssetEntityData( + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + memoryId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}memory_id'], + )!, + ); + } + + @override + MemoryAssetEntity createAlias(String alias) { + return MemoryAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryAssetEntityData extends DataClass + implements Insertable { + final String assetId; + final String memoryId; + const MemoryAssetEntityData({required this.assetId, required this.memoryId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = Variable(assetId); + map['memory_id'] = Variable(memoryId); + return map; + } + + factory MemoryAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return MemoryAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + memoryId: serializer.fromJson(json['memoryId']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'memoryId': serializer.toJson(memoryId), + }; + } + + MemoryAssetEntityData copyWith({String? assetId, String? memoryId}) => + MemoryAssetEntityData( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + MemoryAssetEntityData copyWithCompanion(MemoryAssetEntityCompanion data) { + return MemoryAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + memoryId: data.memoryId.present ? data.memoryId.value : this.memoryId, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, memoryId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is MemoryAssetEntityData && + other.assetId == this.assetId && + other.memoryId == this.memoryId); +} + +class MemoryAssetEntityCompanion + extends UpdateCompanion { + final Value assetId; + final Value memoryId; + const MemoryAssetEntityCompanion({ + this.assetId = const Value.absent(), + this.memoryId = const Value.absent(), + }); + MemoryAssetEntityCompanion.insert({ + required String assetId, + required String memoryId, + }) : assetId = Value(assetId), + memoryId = Value(memoryId); + static Insertable custom({ + Expression? assetId, + Expression? memoryId, + }) { + return RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (memoryId != null) 'memory_id': memoryId, + }); + } + + MemoryAssetEntityCompanion copyWith({ + Value? assetId, + Value? memoryId, + }) { + return MemoryAssetEntityCompanion( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (memoryId.present) { + map['memory_id'] = Variable(memoryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } +} + +class PersonEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + PersonEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn ownerId = GeneratedColumn( + 'owner_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn faceAssetId = GeneratedColumn( + 'face_asset_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + ); + late final GeneratedColumn isHidden = GeneratedColumn( + 'is_hidden', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_hidden" IN (0, 1))', + ), + ); + late final GeneratedColumn color = GeneratedColumn( + 'color', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn birthDate = GeneratedColumn( + 'birth_date', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'person_entity'; + @override + Set get $primaryKey => {id}; + @override + PersonEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return PersonEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + ownerId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}owner_id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + faceAssetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}face_asset_id'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + isHidden: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_hidden'], + )!, + color: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}color'], + ), + birthDate: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}birth_date'], + ), + ); + } + + @override + PersonEntity createAlias(String alias) { + return PersonEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class PersonEntityData extends DataClass + implements Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final String ownerId; + final String name; + final String? faceAssetId; + final bool isFavorite; + final bool isHidden; + final String? color; + final DateTime? birthDate; + const PersonEntityData({ + required this.id, + required this.createdAt, + required this.updatedAt, + required this.ownerId, + required this.name, + this.faceAssetId, + required this.isFavorite, + required this.isHidden, + this.color, + this.birthDate, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + map['owner_id'] = Variable(ownerId); + map['name'] = Variable(name); + if (!nullToAbsent || faceAssetId != null) { + map['face_asset_id'] = Variable(faceAssetId); + } + map['is_favorite'] = Variable(isFavorite); + map['is_hidden'] = Variable(isHidden); + if (!nullToAbsent || color != null) { + map['color'] = Variable(color); + } + if (!nullToAbsent || birthDate != null) { + map['birth_date'] = Variable(birthDate); + } + return map; + } + + factory PersonEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return PersonEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + ownerId: serializer.fromJson(json['ownerId']), + name: serializer.fromJson(json['name']), + faceAssetId: serializer.fromJson(json['faceAssetId']), + isFavorite: serializer.fromJson(json['isFavorite']), + isHidden: serializer.fromJson(json['isHidden']), + color: serializer.fromJson(json['color']), + birthDate: serializer.fromJson(json['birthDate']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'ownerId': serializer.toJson(ownerId), + 'name': serializer.toJson(name), + 'faceAssetId': serializer.toJson(faceAssetId), + 'isFavorite': serializer.toJson(isFavorite), + 'isHidden': serializer.toJson(isHidden), + 'color': serializer.toJson(color), + 'birthDate': serializer.toJson(birthDate), + }; + } + + PersonEntityData copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + String? ownerId, + String? name, + Value faceAssetId = const Value.absent(), + bool? isFavorite, + bool? isHidden, + Value color = const Value.absent(), + Value birthDate = const Value.absent(), + }) => PersonEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId.present ? faceAssetId.value : this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color.present ? color.value : this.color, + birthDate: birthDate.present ? birthDate.value : this.birthDate, + ); + PersonEntityData copyWithCompanion(PersonEntityCompanion data) { + return PersonEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + name: data.name.present ? data.name.value : this.name, + faceAssetId: data.faceAssetId.present + ? data.faceAssetId.value + : this.faceAssetId, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + isHidden: data.isHidden.present ? data.isHidden.value : this.isHidden, + color: data.color.present ? data.color.value : this.color, + birthDate: data.birthDate.present ? data.birthDate.value : this.birthDate, + ); + } + + @override + String toString() { + return (StringBuffer('PersonEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + createdAt, + updatedAt, + ownerId, + name, + faceAssetId, + isFavorite, + isHidden, + color, + birthDate, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is PersonEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.ownerId == this.ownerId && + other.name == this.name && + other.faceAssetId == this.faceAssetId && + other.isFavorite == this.isFavorite && + other.isHidden == this.isHidden && + other.color == this.color && + other.birthDate == this.birthDate); +} + +class PersonEntityCompanion extends UpdateCompanion { + final Value id; + final Value createdAt; + final Value updatedAt; + final Value ownerId; + final Value name; + final Value faceAssetId; + final Value isFavorite; + final Value isHidden; + final Value color; + final Value birthDate; + const PersonEntityCompanion({ + this.id = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.ownerId = const Value.absent(), + this.name = const Value.absent(), + this.faceAssetId = const Value.absent(), + this.isFavorite = const Value.absent(), + this.isHidden = const Value.absent(), + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }); + PersonEntityCompanion.insert({ + required String id, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + required String ownerId, + required String name, + this.faceAssetId = const Value.absent(), + required bool isFavorite, + required bool isHidden, + this.color = const Value.absent(), + this.birthDate = const Value.absent(), + }) : id = Value(id), + ownerId = Value(ownerId), + name = Value(name), + isFavorite = Value(isFavorite), + isHidden = Value(isHidden); + static Insertable custom({ + Expression? id, + Expression? createdAt, + Expression? updatedAt, + Expression? ownerId, + Expression? name, + Expression? faceAssetId, + Expression? isFavorite, + Expression? isHidden, + Expression? color, + Expression? birthDate, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (ownerId != null) 'owner_id': ownerId, + if (name != null) 'name': name, + if (faceAssetId != null) 'face_asset_id': faceAssetId, + if (isFavorite != null) 'is_favorite': isFavorite, + if (isHidden != null) 'is_hidden': isHidden, + if (color != null) 'color': color, + if (birthDate != null) 'birth_date': birthDate, + }); + } + + PersonEntityCompanion copyWith({ + Value? id, + Value? createdAt, + Value? updatedAt, + Value? ownerId, + Value? name, + Value? faceAssetId, + Value? isFavorite, + Value? isHidden, + Value? color, + Value? birthDate, + }) { + return PersonEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + faceAssetId: faceAssetId ?? this.faceAssetId, + isFavorite: isFavorite ?? this.isFavorite, + isHidden: isHidden ?? this.isHidden, + color: color ?? this.color, + birthDate: birthDate ?? this.birthDate, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (ownerId.present) { + map['owner_id'] = Variable(ownerId.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (faceAssetId.present) { + map['face_asset_id'] = Variable(faceAssetId.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (isHidden.present) { + map['is_hidden'] = Variable(isHidden.value); + } + if (color.present) { + map['color'] = Variable(color.value); + } + if (birthDate.present) { + map['birth_date'] = Variable(birthDate.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('PersonEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('ownerId: $ownerId, ') + ..write('name: $name, ') + ..write('faceAssetId: $faceAssetId, ') + ..write('isFavorite: $isFavorite, ') + ..write('isHidden: $isHidden, ') + ..write('color: $color, ') + ..write('birthDate: $birthDate') + ..write(')')) + .toString(); + } +} + +class AssetFaceEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + AssetFaceEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn assetId = GeneratedColumn( + 'asset_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE', + ), + ); + late final GeneratedColumn personId = GeneratedColumn( + 'person_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES person_entity (id) ON DELETE SET NULL', + ), + ); + late final GeneratedColumn imageWidth = GeneratedColumn( + 'image_width', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn imageHeight = GeneratedColumn( + 'image_height', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX1 = GeneratedColumn( + 'bounding_box_x1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY1 = GeneratedColumn( + 'bounding_box_y1', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxX2 = GeneratedColumn( + 'bounding_box_x2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn boundingBoxY2 = GeneratedColumn( + 'bounding_box_y2', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn sourceType = GeneratedColumn( + 'source_type', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'asset_face_entity'; + @override + Set get $primaryKey => {id}; + @override + AssetFaceEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return AssetFaceEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + assetId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}asset_id'], + )!, + personId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}person_id'], + ), + imageWidth: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_width'], + )!, + imageHeight: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}image_height'], + )!, + boundingBoxX1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x1'], + )!, + boundingBoxY1: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y1'], + )!, + boundingBoxX2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_x2'], + )!, + boundingBoxY2: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}bounding_box_y2'], + )!, + sourceType: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}source_type'], + )!, + ); + } + + @override + AssetFaceEntity createAlias(String alias) { + return AssetFaceEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class AssetFaceEntityData extends DataClass + implements Insertable { + final String id; + final String assetId; + final String? personId; + final int imageWidth; + final int imageHeight; + final int boundingBoxX1; + final int boundingBoxY1; + final int boundingBoxX2; + final int boundingBoxY2; + final String sourceType; + const AssetFaceEntityData({ + required this.id, + required this.assetId, + this.personId, + required this.imageWidth, + required this.imageHeight, + required this.boundingBoxX1, + required this.boundingBoxY1, + required this.boundingBoxX2, + required this.boundingBoxY2, + required this.sourceType, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['asset_id'] = Variable(assetId); + if (!nullToAbsent || personId != null) { + map['person_id'] = Variable(personId); + } + map['image_width'] = Variable(imageWidth); + map['image_height'] = Variable(imageHeight); + map['bounding_box_x1'] = Variable(boundingBoxX1); + map['bounding_box_y1'] = Variable(boundingBoxY1); + map['bounding_box_x2'] = Variable(boundingBoxX2); + map['bounding_box_y2'] = Variable(boundingBoxY2); + map['source_type'] = Variable(sourceType); + return map; + } + + factory AssetFaceEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return AssetFaceEntityData( + id: serializer.fromJson(json['id']), + assetId: serializer.fromJson(json['assetId']), + personId: serializer.fromJson(json['personId']), + imageWidth: serializer.fromJson(json['imageWidth']), + imageHeight: serializer.fromJson(json['imageHeight']), + boundingBoxX1: serializer.fromJson(json['boundingBoxX1']), + boundingBoxY1: serializer.fromJson(json['boundingBoxY1']), + boundingBoxX2: serializer.fromJson(json['boundingBoxX2']), + boundingBoxY2: serializer.fromJson(json['boundingBoxY2']), + sourceType: serializer.fromJson(json['sourceType']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'assetId': serializer.toJson(assetId), + 'personId': serializer.toJson(personId), + 'imageWidth': serializer.toJson(imageWidth), + 'imageHeight': serializer.toJson(imageHeight), + 'boundingBoxX1': serializer.toJson(boundingBoxX1), + 'boundingBoxY1': serializer.toJson(boundingBoxY1), + 'boundingBoxX2': serializer.toJson(boundingBoxX2), + 'boundingBoxY2': serializer.toJson(boundingBoxY2), + 'sourceType': serializer.toJson(sourceType), + }; + } + + AssetFaceEntityData copyWith({ + String? id, + String? assetId, + Value personId = const Value.absent(), + int? imageWidth, + int? imageHeight, + int? boundingBoxX1, + int? boundingBoxY1, + int? boundingBoxX2, + int? boundingBoxY2, + String? sourceType, + }) => AssetFaceEntityData( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId.present ? personId.value : this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + AssetFaceEntityData copyWithCompanion(AssetFaceEntityCompanion data) { + return AssetFaceEntityData( + id: data.id.present ? data.id.value : this.id, + assetId: data.assetId.present ? data.assetId.value : this.assetId, + personId: data.personId.present ? data.personId.value : this.personId, + imageWidth: data.imageWidth.present + ? data.imageWidth.value + : this.imageWidth, + imageHeight: data.imageHeight.present + ? data.imageHeight.value + : this.imageHeight, + boundingBoxX1: data.boundingBoxX1.present + ? data.boundingBoxX1.value + : this.boundingBoxX1, + boundingBoxY1: data.boundingBoxY1.present + ? data.boundingBoxY1.value + : this.boundingBoxY1, + boundingBoxX2: data.boundingBoxX2.present + ? data.boundingBoxX2.value + : this.boundingBoxX2, + boundingBoxY2: data.boundingBoxY2.present + ? data.boundingBoxY2.value + : this.boundingBoxY2, + sourceType: data.sourceType.present + ? data.sourceType.value + : this.sourceType, + ); + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityData(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + id, + assetId, + personId, + imageWidth, + imageHeight, + boundingBoxX1, + boundingBoxY1, + boundingBoxX2, + boundingBoxY2, + sourceType, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is AssetFaceEntityData && + other.id == this.id && + other.assetId == this.assetId && + other.personId == this.personId && + other.imageWidth == this.imageWidth && + other.imageHeight == this.imageHeight && + other.boundingBoxX1 == this.boundingBoxX1 && + other.boundingBoxY1 == this.boundingBoxY1 && + other.boundingBoxX2 == this.boundingBoxX2 && + other.boundingBoxY2 == this.boundingBoxY2 && + other.sourceType == this.sourceType); +} + +class AssetFaceEntityCompanion extends UpdateCompanion { + final Value id; + final Value assetId; + final Value personId; + final Value imageWidth; + final Value imageHeight; + final Value boundingBoxX1; + final Value boundingBoxY1; + final Value boundingBoxX2; + final Value boundingBoxY2; + final Value sourceType; + const AssetFaceEntityCompanion({ + this.id = const Value.absent(), + this.assetId = const Value.absent(), + this.personId = const Value.absent(), + this.imageWidth = const Value.absent(), + this.imageHeight = const Value.absent(), + this.boundingBoxX1 = const Value.absent(), + this.boundingBoxY1 = const Value.absent(), + this.boundingBoxX2 = const Value.absent(), + this.boundingBoxY2 = const Value.absent(), + this.sourceType = const Value.absent(), + }); + AssetFaceEntityCompanion.insert({ + required String id, + required String assetId, + this.personId = const Value.absent(), + required int imageWidth, + required int imageHeight, + required int boundingBoxX1, + required int boundingBoxY1, + required int boundingBoxX2, + required int boundingBoxY2, + required String sourceType, + }) : id = Value(id), + assetId = Value(assetId), + imageWidth = Value(imageWidth), + imageHeight = Value(imageHeight), + boundingBoxX1 = Value(boundingBoxX1), + boundingBoxY1 = Value(boundingBoxY1), + boundingBoxX2 = Value(boundingBoxX2), + boundingBoxY2 = Value(boundingBoxY2), + sourceType = Value(sourceType); + static Insertable custom({ + Expression? id, + Expression? assetId, + Expression? personId, + Expression? imageWidth, + Expression? imageHeight, + Expression? boundingBoxX1, + Expression? boundingBoxY1, + Expression? boundingBoxX2, + Expression? boundingBoxY2, + Expression? sourceType, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (assetId != null) 'asset_id': assetId, + if (personId != null) 'person_id': personId, + if (imageWidth != null) 'image_width': imageWidth, + if (imageHeight != null) 'image_height': imageHeight, + if (boundingBoxX1 != null) 'bounding_box_x1': boundingBoxX1, + if (boundingBoxY1 != null) 'bounding_box_y1': boundingBoxY1, + if (boundingBoxX2 != null) 'bounding_box_x2': boundingBoxX2, + if (boundingBoxY2 != null) 'bounding_box_y2': boundingBoxY2, + if (sourceType != null) 'source_type': sourceType, + }); + } + + AssetFaceEntityCompanion copyWith({ + Value? id, + Value? assetId, + Value? personId, + Value? imageWidth, + Value? imageHeight, + Value? boundingBoxX1, + Value? boundingBoxY1, + Value? boundingBoxX2, + Value? boundingBoxY2, + Value? sourceType, + }) { + return AssetFaceEntityCompanion( + id: id ?? this.id, + assetId: assetId ?? this.assetId, + personId: personId ?? this.personId, + imageWidth: imageWidth ?? this.imageWidth, + imageHeight: imageHeight ?? this.imageHeight, + boundingBoxX1: boundingBoxX1 ?? this.boundingBoxX1, + boundingBoxY1: boundingBoxY1 ?? this.boundingBoxY1, + boundingBoxX2: boundingBoxX2 ?? this.boundingBoxX2, + boundingBoxY2: boundingBoxY2 ?? this.boundingBoxY2, + sourceType: sourceType ?? this.sourceType, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (assetId.present) { + map['asset_id'] = Variable(assetId.value); + } + if (personId.present) { + map['person_id'] = Variable(personId.value); + } + if (imageWidth.present) { + map['image_width'] = Variable(imageWidth.value); + } + if (imageHeight.present) { + map['image_height'] = Variable(imageHeight.value); + } + if (boundingBoxX1.present) { + map['bounding_box_x1'] = Variable(boundingBoxX1.value); + } + if (boundingBoxY1.present) { + map['bounding_box_y1'] = Variable(boundingBoxY1.value); + } + if (boundingBoxX2.present) { + map['bounding_box_x2'] = Variable(boundingBoxX2.value); + } + if (boundingBoxY2.present) { + map['bounding_box_y2'] = Variable(boundingBoxY2.value); + } + if (sourceType.present) { + map['source_type'] = Variable(sourceType.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('AssetFaceEntityCompanion(') + ..write('id: $id, ') + ..write('assetId: $assetId, ') + ..write('personId: $personId, ') + ..write('imageWidth: $imageWidth, ') + ..write('imageHeight: $imageHeight, ') + ..write('boundingBoxX1: $boundingBoxX1, ') + ..write('boundingBoxY1: $boundingBoxY1, ') + ..write('boundingBoxX2: $boundingBoxX2, ') + ..write('boundingBoxY2: $boundingBoxY2, ') + ..write('sourceType: $sourceType') + ..write(')')) + .toString(); + } +} + +class StoreEntity extends Table with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + StoreEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn stringValue = GeneratedColumn( + 'string_value', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn intValue = GeneratedColumn( + 'int_value', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + @override + List get $columns => [id, stringValue, intValue]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'store_entity'; + @override + Set get $primaryKey => {id}; + @override + StoreEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return StoreEntityData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}id'], + )!, + stringValue: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}string_value'], + ), + intValue: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}int_value'], + ), + ); + } + + @override + StoreEntity createAlias(String alias) { + return StoreEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class StoreEntityData extends DataClass implements Insertable { + final int id; + final String? stringValue; + final int? intValue; + const StoreEntityData({required this.id, this.stringValue, this.intValue}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + if (!nullToAbsent || stringValue != null) { + map['string_value'] = Variable(stringValue); + } + if (!nullToAbsent || intValue != null) { + map['int_value'] = Variable(intValue); + } + return map; + } + + factory StoreEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return StoreEntityData( + id: serializer.fromJson(json['id']), + stringValue: serializer.fromJson(json['stringValue']), + intValue: serializer.fromJson(json['intValue']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'stringValue': serializer.toJson(stringValue), + 'intValue': serializer.toJson(intValue), + }; + } + + StoreEntityData copyWith({ + int? id, + Value stringValue = const Value.absent(), + Value intValue = const Value.absent(), + }) => StoreEntityData( + id: id ?? this.id, + stringValue: stringValue.present ? stringValue.value : this.stringValue, + intValue: intValue.present ? intValue.value : this.intValue, + ); + StoreEntityData copyWithCompanion(StoreEntityCompanion data) { + return StoreEntityData( + id: data.id.present ? data.id.value : this.id, + stringValue: data.stringValue.present + ? data.stringValue.value + : this.stringValue, + intValue: data.intValue.present ? data.intValue.value : this.intValue, + ); + } + + @override + String toString() { + return (StringBuffer('StoreEntityData(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, stringValue, intValue); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is StoreEntityData && + other.id == this.id && + other.stringValue == this.stringValue && + other.intValue == this.intValue); +} + +class StoreEntityCompanion extends UpdateCompanion { + final Value id; + final Value stringValue; + final Value intValue; + const StoreEntityCompanion({ + this.id = const Value.absent(), + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }); + StoreEntityCompanion.insert({ + required int id, + this.stringValue = const Value.absent(), + this.intValue = const Value.absent(), + }) : id = Value(id); + static Insertable custom({ + Expression? id, + Expression? stringValue, + Expression? intValue, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (stringValue != null) 'string_value': stringValue, + if (intValue != null) 'int_value': intValue, + }); + } + + StoreEntityCompanion copyWith({ + Value? id, + Value? stringValue, + Value? intValue, + }) { + return StoreEntityCompanion( + id: id ?? this.id, + stringValue: stringValue ?? this.stringValue, + intValue: intValue ?? this.intValue, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (stringValue.present) { + map['string_value'] = Variable(stringValue.value); + } + if (intValue.present) { + map['int_value'] = Variable(intValue.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('StoreEntityCompanion(') + ..write('id: $id, ') + ..write('stringValue: $stringValue, ') + ..write('intValue: $intValue') + ..write(')')) + .toString(); + } +} + +class TrashedLocalAssetEntity extends Table + with TableInfo { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + TrashedLocalAssetEntity(this.attachedDatabase, [this._alias]); + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn type = GeneratedColumn( + 'type', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn updatedAt = GeneratedColumn( + 'updated_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: const CustomExpression('CURRENT_TIMESTAMP'), + ); + late final GeneratedColumn width = GeneratedColumn( + 'width', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn height = GeneratedColumn( + 'height', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn durationInSeconds = GeneratedColumn( + 'duration_in_seconds', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn albumId = GeneratedColumn( + 'album_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + late final GeneratedColumn checksum = GeneratedColumn( + 'checksum', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + late final GeneratedColumn isFavorite = GeneratedColumn( + 'is_favorite', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_favorite" IN (0, 1))', + ), + defaultValue: const CustomExpression('0'), + ); + late final GeneratedColumn orientation = GeneratedColumn( + 'orientation', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: false, + defaultValue: const CustomExpression('0'), + ); + @override + List get $columns => [ + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + albumId, + checksum, + isFavorite, + orientation, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'trashed_local_asset_entity'; + @override + Set get $primaryKey => {id, albumId}; + @override + TrashedLocalAssetEntityData map( + Map data, { + String? tablePrefix, + }) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return TrashedLocalAssetEntityData( + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + type: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}type'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + updatedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}updated_at'], + )!, + width: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}width'], + ), + height: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}height'], + ), + durationInSeconds: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}duration_in_seconds'], + ), + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + albumId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}album_id'], + )!, + checksum: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}checksum'], + ), + isFavorite: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}is_favorite'], + )!, + orientation: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}orientation'], + )!, + ); + } + + @override + TrashedLocalAssetEntity createAlias(String alias) { + return TrashedLocalAssetEntity(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class TrashedLocalAssetEntityData extends DataClass + implements Insertable { + final String name; + final int type; + final DateTime createdAt; + final DateTime updatedAt; + final int? width; + final int? height; + final int? durationInSeconds; + final String id; + final String albumId; + final String? checksum; + final bool isFavorite; + final int orientation; + const TrashedLocalAssetEntityData({ + required this.name, + required this.type, + required this.createdAt, + required this.updatedAt, + this.width, + this.height, + this.durationInSeconds, + required this.id, + required this.albumId, + this.checksum, + required this.isFavorite, + required this.orientation, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['name'] = Variable(name); + map['type'] = Variable(type); + map['created_at'] = Variable(createdAt); + map['updated_at'] = Variable(updatedAt); + if (!nullToAbsent || width != null) { + map['width'] = Variable(width); + } + if (!nullToAbsent || height != null) { + map['height'] = Variable(height); + } + if (!nullToAbsent || durationInSeconds != null) { + map['duration_in_seconds'] = Variable(durationInSeconds); + } + map['id'] = Variable(id); + map['album_id'] = Variable(albumId); + if (!nullToAbsent || checksum != null) { + map['checksum'] = Variable(checksum); + } + map['is_favorite'] = Variable(isFavorite); + map['orientation'] = Variable(orientation); + return map; + } + + factory TrashedLocalAssetEntityData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return TrashedLocalAssetEntityData( + name: serializer.fromJson(json['name']), + type: serializer.fromJson(json['type']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + width: serializer.fromJson(json['width']), + height: serializer.fromJson(json['height']), + durationInSeconds: serializer.fromJson(json['durationInSeconds']), + id: serializer.fromJson(json['id']), + albumId: serializer.fromJson(json['albumId']), + checksum: serializer.fromJson(json['checksum']), + isFavorite: serializer.fromJson(json['isFavorite']), + orientation: serializer.fromJson(json['orientation']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'name': serializer.toJson(name), + 'type': serializer.toJson(type), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'width': serializer.toJson(width), + 'height': serializer.toJson(height), + 'durationInSeconds': serializer.toJson(durationInSeconds), + 'id': serializer.toJson(id), + 'albumId': serializer.toJson(albumId), + 'checksum': serializer.toJson(checksum), + 'isFavorite': serializer.toJson(isFavorite), + 'orientation': serializer.toJson(orientation), + }; + } + + TrashedLocalAssetEntityData copyWith({ + String? name, + int? type, + DateTime? createdAt, + DateTime? updatedAt, + Value width = const Value.absent(), + Value height = const Value.absent(), + Value durationInSeconds = const Value.absent(), + String? id, + String? albumId, + Value checksum = const Value.absent(), + bool? isFavorite, + int? orientation, + }) => TrashedLocalAssetEntityData( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width.present ? width.value : this.width, + height: height.present ? height.value : this.height, + durationInSeconds: durationInSeconds.present + ? durationInSeconds.value + : this.durationInSeconds, + id: id ?? this.id, + albumId: albumId ?? this.albumId, + checksum: checksum.present ? checksum.value : this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + TrashedLocalAssetEntityData copyWithCompanion( + TrashedLocalAssetEntityCompanion data, + ) { + return TrashedLocalAssetEntityData( + name: data.name.present ? data.name.value : this.name, + type: data.type.present ? data.type.value : this.type, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + width: data.width.present ? data.width.value : this.width, + height: data.height.present ? data.height.value : this.height, + durationInSeconds: data.durationInSeconds.present + ? data.durationInSeconds.value + : this.durationInSeconds, + id: data.id.present ? data.id.value : this.id, + albumId: data.albumId.present ? data.albumId.value : this.albumId, + checksum: data.checksum.present ? data.checksum.value : this.checksum, + isFavorite: data.isFavorite.present + ? data.isFavorite.value + : this.isFavorite, + orientation: data.orientation.present + ? data.orientation.value + : this.orientation, + ); + } + + @override + String toString() { + return (StringBuffer('TrashedLocalAssetEntityData(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('albumId: $albumId, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash( + name, + type, + createdAt, + updatedAt, + width, + height, + durationInSeconds, + id, + albumId, + checksum, + isFavorite, + orientation, + ); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is TrashedLocalAssetEntityData && + other.name == this.name && + other.type == this.type && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.width == this.width && + other.height == this.height && + other.durationInSeconds == this.durationInSeconds && + other.id == this.id && + other.albumId == this.albumId && + other.checksum == this.checksum && + other.isFavorite == this.isFavorite && + other.orientation == this.orientation); +} + +class TrashedLocalAssetEntityCompanion + extends UpdateCompanion { + final Value name; + final Value type; + final Value createdAt; + final Value updatedAt; + final Value width; + final Value height; + final Value durationInSeconds; + final Value id; + final Value albumId; + final Value checksum; + final Value isFavorite; + final Value orientation; + const TrashedLocalAssetEntityCompanion({ + this.name = const Value.absent(), + this.type = const Value.absent(), + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + this.id = const Value.absent(), + this.albumId = const Value.absent(), + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }); + TrashedLocalAssetEntityCompanion.insert({ + required String name, + required int type, + this.createdAt = const Value.absent(), + this.updatedAt = const Value.absent(), + this.width = const Value.absent(), + this.height = const Value.absent(), + this.durationInSeconds = const Value.absent(), + required String id, + required String albumId, + this.checksum = const Value.absent(), + this.isFavorite = const Value.absent(), + this.orientation = const Value.absent(), + }) : name = Value(name), + type = Value(type), + id = Value(id), + albumId = Value(albumId); + static Insertable custom({ + Expression? name, + Expression? type, + Expression? createdAt, + Expression? updatedAt, + Expression? width, + Expression? height, + Expression? durationInSeconds, + Expression? id, + Expression? albumId, + Expression? checksum, + Expression? isFavorite, + Expression? orientation, + }) { + return RawValuesInsertable({ + if (name != null) 'name': name, + if (type != null) 'type': type, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (width != null) 'width': width, + if (height != null) 'height': height, + if (durationInSeconds != null) 'duration_in_seconds': durationInSeconds, + if (id != null) 'id': id, + if (albumId != null) 'album_id': albumId, + if (checksum != null) 'checksum': checksum, + if (isFavorite != null) 'is_favorite': isFavorite, + if (orientation != null) 'orientation': orientation, + }); + } + + TrashedLocalAssetEntityCompanion copyWith({ + Value? name, + Value? type, + Value? createdAt, + Value? updatedAt, + Value? width, + Value? height, + Value? durationInSeconds, + Value? id, + Value? albumId, + Value? checksum, + Value? isFavorite, + Value? orientation, + }) { + return TrashedLocalAssetEntityCompanion( + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + width: width ?? this.width, + height: height ?? this.height, + durationInSeconds: durationInSeconds ?? this.durationInSeconds, + id: id ?? this.id, + albumId: albumId ?? this.albumId, + checksum: checksum ?? this.checksum, + isFavorite: isFavorite ?? this.isFavorite, + orientation: orientation ?? this.orientation, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (name.present) { + map['name'] = Variable(name.value); + } + if (type.present) { + map['type'] = Variable(type.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = Variable(updatedAt.value); + } + if (width.present) { + map['width'] = Variable(width.value); + } + if (height.present) { + map['height'] = Variable(height.value); + } + if (durationInSeconds.present) { + map['duration_in_seconds'] = Variable(durationInSeconds.value); + } + if (id.present) { + map['id'] = Variable(id.value); + } + if (albumId.present) { + map['album_id'] = Variable(albumId.value); + } + if (checksum.present) { + map['checksum'] = Variable(checksum.value); + } + if (isFavorite.present) { + map['is_favorite'] = Variable(isFavorite.value); + } + if (orientation.present) { + map['orientation'] = Variable(orientation.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('TrashedLocalAssetEntityCompanion(') + ..write('name: $name, ') + ..write('type: $type, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('width: $width, ') + ..write('height: $height, ') + ..write('durationInSeconds: $durationInSeconds, ') + ..write('id: $id, ') + ..write('albumId: $albumId, ') + ..write('checksum: $checksum, ') + ..write('isFavorite: $isFavorite, ') + ..write('orientation: $orientation') + ..write(')')) + .toString(); + } +} + +class DatabaseAtV14 extends GeneratedDatabase { + DatabaseAtV14(QueryExecutor e) : super(e); + late final UserEntity userEntity = UserEntity(this); + late final RemoteAssetEntity remoteAssetEntity = RemoteAssetEntity(this); + late final StackEntity stackEntity = StackEntity(this); + late final LocalAssetEntity localAssetEntity = LocalAssetEntity(this); + late final RemoteAlbumEntity remoteAlbumEntity = RemoteAlbumEntity(this); + late final LocalAlbumEntity localAlbumEntity = LocalAlbumEntity(this); + late final LocalAlbumAssetEntity localAlbumAssetEntity = + LocalAlbumAssetEntity(this); + late final Index idxLocalAssetChecksum = Index( + 'idx_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_local_asset_checksum ON local_asset_entity (checksum)', + ); + late final Index idxRemoteAssetOwnerChecksum = Index( + 'idx_remote_asset_owner_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_owner_checksum ON remote_asset_entity (owner_id, checksum)', + ); + late final Index uQRemoteAssetsOwnerChecksum = Index( + 'UQ_remote_assets_owner_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_checksum ON remote_asset_entity (owner_id, checksum) WHERE(library_id IS NULL)', + ); + late final Index uQRemoteAssetsOwnerLibraryChecksum = Index( + 'UQ_remote_assets_owner_library_checksum', + 'CREATE UNIQUE INDEX IF NOT EXISTS UQ_remote_assets_owner_library_checksum ON remote_asset_entity (owner_id, library_id, checksum) WHERE(library_id IS NOT NULL)', + ); + late final Index idxRemoteAssetChecksum = Index( + 'idx_remote_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_remote_asset_checksum ON remote_asset_entity (checksum)', + ); + late final AuthUserEntity authUserEntity = AuthUserEntity(this); + late final UserMetadataEntity userMetadataEntity = UserMetadataEntity(this); + late final PartnerEntity partnerEntity = PartnerEntity(this); + late final RemoteExifEntity remoteExifEntity = RemoteExifEntity(this); + late final RemoteAlbumAssetEntity remoteAlbumAssetEntity = + RemoteAlbumAssetEntity(this); + late final RemoteAlbumUserEntity remoteAlbumUserEntity = + RemoteAlbumUserEntity(this); + late final MemoryEntity memoryEntity = MemoryEntity(this); + late final MemoryAssetEntity memoryAssetEntity = MemoryAssetEntity(this); + late final PersonEntity personEntity = PersonEntity(this); + late final AssetFaceEntity assetFaceEntity = AssetFaceEntity(this); + late final StoreEntity storeEntity = StoreEntity(this); + late final TrashedLocalAssetEntity trashedLocalAssetEntity = + TrashedLocalAssetEntity(this); + late final Index idxLatLng = Index( + 'idx_lat_lng', + 'CREATE INDEX IF NOT EXISTS idx_lat_lng ON remote_exif_entity (latitude, longitude)', + ); + late final Index idxTrashedLocalAssetChecksum = Index( + 'idx_trashed_local_asset_checksum', + 'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_checksum ON trashed_local_asset_entity (checksum)', + ); + late final Index idxTrashedLocalAssetAlbum = Index( + 'idx_trashed_local_asset_album', + 'CREATE INDEX IF NOT EXISTS idx_trashed_local_asset_album ON trashed_local_asset_entity (album_id)', + ); + @override + Iterable> get allTables => + allSchemaEntities.whereType>(); + @override + List get allSchemaEntities => [ + userEntity, + remoteAssetEntity, + stackEntity, + localAssetEntity, + remoteAlbumEntity, + localAlbumEntity, + localAlbumAssetEntity, + idxLocalAssetChecksum, + idxRemoteAssetOwnerChecksum, + uQRemoteAssetsOwnerChecksum, + uQRemoteAssetsOwnerLibraryChecksum, + idxRemoteAssetChecksum, + authUserEntity, + userMetadataEntity, + partnerEntity, + remoteExifEntity, + remoteAlbumAssetEntity, + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity, + personEntity, + assetFaceEntity, + storeEntity, + trashedLocalAssetEntity, + idxLatLng, + idxTrashedLocalAssetChecksum, + idxTrashedLocalAssetAlbum, + ]; + @override + int get schemaVersion => 14; + @override + DriftDatabaseOptions get options => + const DriftDatabaseOptions(storeDateTimeAsText: true); +} diff --git a/mobile/test/modules/activity/activity_text_field_test.dart b/mobile/test/modules/activity/activity_text_field_test.dart index 8f28b7f28e..4f4a2c7068 100644 --- a/mobile/test/modules/activity/activity_text_field_test.dart +++ b/mobile/test/modules/activity/activity_text_field_test.dart @@ -77,15 +77,15 @@ void main() { overrides: overrides, ); - expect(find.widgetWithIcon(IconButton, Icons.favorite_rounded), findsOneWidget); - expect(find.widgetWithIcon(IconButton, Icons.favorite_border_rounded), findsNothing); + expect(find.widgetWithIcon(IconButton, Icons.thumb_up), findsOneWidget); + expect(find.widgetWithIcon(IconButton, Icons.thumb_up_off_alt), findsNothing); }); testWidgets('Bordered icon if likedId == null', (tester) async { await tester.pumpConsumerWidget(ActivityTextField(onSubmit: (_) {}), overrides: overrides); - expect(find.widgetWithIcon(IconButton, Icons.favorite_border_rounded), findsOneWidget); - expect(find.widgetWithIcon(IconButton, Icons.favorite_rounded), findsNothing); + expect(find.widgetWithIcon(IconButton, Icons.thumb_up_off_alt), findsOneWidget); + expect(find.widgetWithIcon(IconButton, Icons.thumb_up), findsNothing); }); testWidgets('Adds new like', (tester) async { diff --git a/mobile/test/modules/activity/activity_tile_test.dart b/mobile/test/modules/activity/activity_tile_test.dart index 718dfcce21..538e3c0911 100644 --- a/mobile/test/modules/activity/activity_tile_test.dart +++ b/mobile/test/modules/activity/activity_tile_test.dart @@ -91,17 +91,17 @@ void main() { group('Like Activity', () { final activity = Activity(id: '1', createdAt: DateTime(100), type: ActivityType.like, user: UserStub.admin); - testWidgets('Like contains filled heart as leading', (tester) async { + testWidgets('Like contains filled thumbs-up as leading', (tester) async { await tester.pumpConsumerWidget(ActivityTile(activity), overrides: overrides); // Leading widget should not be null final listTile = tester.widget(find.byType(ListTile)); expect(listTile.leading, isNotNull); - // And should have a favorite icon - final favoIconFinder = find.widgetWithIcon(listTile.leading!.runtimeType, Icons.favorite_rounded); + // And should have a thumb_up icon + final thumbUpIconFinder = find.widgetWithIcon(listTile.leading!.runtimeType, Icons.thumb_up); - expect(favoIconFinder, findsOneWidget); + expect(thumbUpIconFinder, findsOneWidget); }); testWidgets('Like title is center aligned', (tester) async { diff --git a/open-api/typescript-sdk/package.json b/open-api/typescript-sdk/package.json index 56520b0efe..b033fdfd7b 100644 --- a/open-api/typescript-sdk/package.json +++ b/open-api/typescript-sdk/package.json @@ -19,7 +19,7 @@ "@oazapfts/runtime": "^1.0.2" }, "devDependencies": { - "@types/node": "^24.10.1", + "@types/node": "^24.10.3", "typescript": "^5.3.3" }, "repository": { diff --git a/plugins/package-lock.json b/plugins/package-lock.json index 2cdf7b7e53..ca3c99b516 100644 --- a/plugins/package-lock.json +++ b/plugins/package-lock.json @@ -15,9 +15,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.0.tgz", - "integrity": "sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.1.tgz", + "integrity": "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==", "cpu": [ "ppc64" ], @@ -32,9 +32,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.0.tgz", - "integrity": "sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.1.tgz", + "integrity": "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==", "cpu": [ "arm" ], @@ -49,9 +49,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.0.tgz", - "integrity": "sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.1.tgz", + "integrity": "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==", "cpu": [ "arm64" ], @@ -66,9 +66,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.0.tgz", - "integrity": "sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.1.tgz", + "integrity": "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==", "cpu": [ "x64" ], @@ -83,9 +83,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.0.tgz", - "integrity": "sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.1.tgz", + "integrity": "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==", "cpu": [ "arm64" ], @@ -100,9 +100,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.0.tgz", - "integrity": "sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.1.tgz", + "integrity": "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==", "cpu": [ "x64" ], @@ -117,9 +117,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.0.tgz", - "integrity": "sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.1.tgz", + "integrity": "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==", "cpu": [ "arm64" ], @@ -134,9 +134,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.0.tgz", - "integrity": "sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.1.tgz", + "integrity": "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==", "cpu": [ "x64" ], @@ -151,9 +151,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.0.tgz", - "integrity": "sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.1.tgz", + "integrity": "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==", "cpu": [ "arm" ], @@ -168,9 +168,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.0.tgz", - "integrity": "sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.1.tgz", + "integrity": "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==", "cpu": [ "arm64" ], @@ -185,9 +185,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.0.tgz", - "integrity": "sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.1.tgz", + "integrity": "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==", "cpu": [ "ia32" ], @@ -202,9 +202,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.0.tgz", - "integrity": "sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.1.tgz", + "integrity": "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==", "cpu": [ "loong64" ], @@ -219,9 +219,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.0.tgz", - "integrity": "sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.1.tgz", + "integrity": "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==", "cpu": [ "mips64el" ], @@ -236,9 +236,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.0.tgz", - "integrity": "sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.1.tgz", + "integrity": "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==", "cpu": [ "ppc64" ], @@ -253,9 +253,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.0.tgz", - "integrity": "sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.1.tgz", + "integrity": "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==", "cpu": [ "riscv64" ], @@ -270,9 +270,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.0.tgz", - "integrity": "sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.1.tgz", + "integrity": "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==", "cpu": [ "s390x" ], @@ -287,9 +287,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.0.tgz", - "integrity": "sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.1.tgz", + "integrity": "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==", "cpu": [ "x64" ], @@ -304,9 +304,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.0.tgz", - "integrity": "sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.1.tgz", + "integrity": "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==", "cpu": [ "arm64" ], @@ -321,9 +321,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.0.tgz", - "integrity": "sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.1.tgz", + "integrity": "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==", "cpu": [ "x64" ], @@ -338,9 +338,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.0.tgz", - "integrity": "sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.1.tgz", + "integrity": "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==", "cpu": [ "arm64" ], @@ -355,9 +355,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.0.tgz", - "integrity": "sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.1.tgz", + "integrity": "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==", "cpu": [ "x64" ], @@ -372,9 +372,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.0.tgz", - "integrity": "sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.1.tgz", + "integrity": "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==", "cpu": [ "arm64" ], @@ -389,9 +389,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.0.tgz", - "integrity": "sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.1.tgz", + "integrity": "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==", "cpu": [ "x64" ], @@ -406,9 +406,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.0.tgz", - "integrity": "sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.1.tgz", + "integrity": "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==", "cpu": [ "arm64" ], @@ -423,9 +423,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.0.tgz", - "integrity": "sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.1.tgz", + "integrity": "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==", "cpu": [ "ia32" ], @@ -440,9 +440,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.0.tgz", - "integrity": "sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.1.tgz", + "integrity": "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==", "cpu": [ "x64" ], @@ -467,9 +467,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.0.tgz", - "integrity": "sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==", + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.1.tgz", + "integrity": "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -480,32 +480,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.0", - "@esbuild/android-arm": "0.27.0", - "@esbuild/android-arm64": "0.27.0", - "@esbuild/android-x64": "0.27.0", - "@esbuild/darwin-arm64": "0.27.0", - "@esbuild/darwin-x64": "0.27.0", - "@esbuild/freebsd-arm64": "0.27.0", - "@esbuild/freebsd-x64": "0.27.0", - "@esbuild/linux-arm": "0.27.0", - "@esbuild/linux-arm64": "0.27.0", - "@esbuild/linux-ia32": "0.27.0", - "@esbuild/linux-loong64": "0.27.0", - "@esbuild/linux-mips64el": "0.27.0", - "@esbuild/linux-ppc64": "0.27.0", - "@esbuild/linux-riscv64": "0.27.0", - "@esbuild/linux-s390x": "0.27.0", - "@esbuild/linux-x64": "0.27.0", - "@esbuild/netbsd-arm64": "0.27.0", - "@esbuild/netbsd-x64": "0.27.0", - "@esbuild/openbsd-arm64": "0.27.0", - "@esbuild/openbsd-x64": "0.27.0", - "@esbuild/openharmony-arm64": "0.27.0", - "@esbuild/sunos-x64": "0.27.0", - "@esbuild/win32-arm64": "0.27.0", - "@esbuild/win32-ia32": "0.27.0", - "@esbuild/win32-x64": "0.27.0" + "@esbuild/aix-ppc64": "0.27.1", + "@esbuild/android-arm": "0.27.1", + "@esbuild/android-arm64": "0.27.1", + "@esbuild/android-x64": "0.27.1", + "@esbuild/darwin-arm64": "0.27.1", + "@esbuild/darwin-x64": "0.27.1", + "@esbuild/freebsd-arm64": "0.27.1", + "@esbuild/freebsd-x64": "0.27.1", + "@esbuild/linux-arm": "0.27.1", + "@esbuild/linux-arm64": "0.27.1", + "@esbuild/linux-ia32": "0.27.1", + "@esbuild/linux-loong64": "0.27.1", + "@esbuild/linux-mips64el": "0.27.1", + "@esbuild/linux-ppc64": "0.27.1", + "@esbuild/linux-riscv64": "0.27.1", + "@esbuild/linux-s390x": "0.27.1", + "@esbuild/linux-x64": "0.27.1", + "@esbuild/netbsd-arm64": "0.27.1", + "@esbuild/netbsd-x64": "0.27.1", + "@esbuild/openbsd-arm64": "0.27.1", + "@esbuild/openbsd-x64": "0.27.1", + "@esbuild/openharmony-arm64": "0.27.1", + "@esbuild/sunos-x64": "0.27.1", + "@esbuild/win32-arm64": "0.27.1", + "@esbuild/win32-ia32": "0.27.1", + "@esbuild/win32-x64": "0.27.1" } }, "node_modules/typescript": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95e2d4945e..27c6c3f290 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,8 +20,8 @@ importers: .github: devDependencies: prettier: - specifier: ^3.5.3 - version: 3.7.1 + specifier: ^3.7.4 + version: 3.7.4 cli: dependencies: @@ -43,7 +43,7 @@ importers: devDependencies: '@eslint/js': specifier: ^9.8.0 - version: 9.39.1 + version: 9.39.2 '@immich/sdk': specifier: file:../open-api/typescript-sdk version: link:../open-api/typescript-sdk @@ -63,11 +63,11 @@ importers: specifier: ^4.13.1 version: 4.13.4 '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^24.10.3 + version: 24.10.4 '@vitest/coverage-v8': specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) byte-size: specifier: ^9.0.0 version: 9.0.1 @@ -79,16 +79,16 @@ importers: version: 12.1.0 eslint: specifier: ^9.14.0 - version: 9.39.1(jiti@2.6.1) + version: 9.39.2(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.7.1) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.7.4) eslint-plugin-unicorn: specifier: ^62.0.0 - version: 62.0.0(eslint@9.39.1(jiti@2.6.1)) + version: 62.0.0(eslint@9.39.2(jiti@2.6.1)) globals: specifier: ^16.0.0 version: 16.5.0 @@ -96,29 +96,29 @@ importers: specifier: ^5.2.0 version: 5.5.0 prettier: - specifier: ^3.2.5 - version: 3.7.1 + specifier: ^3.7.4 + version: 3.7.4 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.3.0(prettier@3.7.1)(typescript@5.9.3) + version: 4.3.0(prettier@3.7.4)(typescript@5.9.3) typescript: specifier: ^5.3.3 version: 5.9.3 typescript-eslint: specifier: ^8.28.0 - version: 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^7.0.0 - version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) vite-tsconfig-paths: specifier: ^5.0.0 - version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) vitest-fetch-mock: specifier: ^0.4.0 - version: 0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) yaml: specifier: ^2.3.1 version: 2.8.2 @@ -130,7 +130,7 @@ importers: version: 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) '@docusaurus/preset-classic': specifier: ~3.9.0 - version: 3.9.2(@algolia/client-search@5.41.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3) + version: 3.9.2(@algolia/client-search@5.46.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3) '@docusaurus/theme-common': specifier: ~3.9.0 version: 3.9.2(@docusaurus/plugin-content-docs@3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -145,7 +145,7 @@ importers: version: 3.1.1(@types/react@19.2.7)(react@18.3.1) autoprefixer: specifier: ^10.4.17 - version: 10.4.22(postcss@8.5.6) + version: 10.4.23(postcss@8.5.6) docusaurus-lunr-search: specifier: ^3.3.2 version: 3.6.0(@docusaurus/core@3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -169,7 +169,7 @@ importers: version: 18.3.1(react@18.3.1) tailwindcss: specifier: ^3.2.4 - version: 3.4.18(yaml@2.8.2) + version: 3.4.19(yaml@2.8.2) url: specifier: ^0.11.0 version: 0.11.4 @@ -184,8 +184,8 @@ importers: specifier: ^3.7.0 version: 3.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) prettier: - specifier: ^3.2.4 - version: 3.7.1 + specifier: ^3.7.4 + version: 3.7.4 typescript: specifier: ^5.1.6 version: 5.9.3 @@ -194,7 +194,7 @@ importers: devDependencies: '@eslint/js': specifier: ^9.8.0 - version: 9.39.1 + version: 9.39.2 '@faker-js/faker': specifier: ^10.1.0 version: 10.1.0 @@ -214,14 +214,14 @@ importers: specifier: ^3.4.2 version: 3.7.1 '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^24.10.3 + version: 24.10.4 '@types/oidc-provider': specifier: ^9.0.0 version: 9.5.0 '@types/pg': specifier: ^8.15.1 - version: 8.15.6 + version: 8.16.0 '@types/pngjs': specifier: ^6.0.4 version: 6.0.5 @@ -233,19 +233,19 @@ importers: version: 17.2.3 eslint: specifier: ^9.14.0 - version: 9.39.1(jiti@2.6.1) + version: 9.39.2(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.7.1) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.7.4) eslint-plugin-unicorn: specifier: ^62.0.0 - version: 62.0.0(eslint@9.39.1(jiti@2.6.1)) + version: 62.0.0(eslint@9.39.2(jiti@2.6.1)) exiftool-vendored: - specifier: ^33.0.0 - version: 33.5.0 + specifier: ^34.0.0 + version: 34.1.0 globals: specifier: ^16.0.0 version: 16.5.0 @@ -257,7 +257,7 @@ importers: version: 3.7.2 oidc-provider: specifier: ^9.0.0 - version: 9.5.2 + version: 9.6.0 pg: specifier: ^8.11.3 version: 8.16.3 @@ -265,11 +265,11 @@ importers: specifier: ^7.0.0 version: 7.0.0 prettier: - specifier: ^3.2.5 - version: 3.7.1 + specifier: ^3.7.4 + version: 3.7.4 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.3.0(prettier@3.7.1)(typescript@5.9.3) + version: 4.3.0(prettier@3.7.4)(typescript@5.9.3) sharp: specifier: ^0.34.5 version: 0.34.5 @@ -284,23 +284,23 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.28.0 - version: 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) utimes: specifier: ^5.2.1 version: 5.2.1(encoding@0.1.13) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) open-api/typescript-sdk: dependencies: '@oazapfts/runtime': specifier: ^1.0.2 - version: 1.0.4 + version: 1.1.0 devDependencies: '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^24.10.3 + version: 24.10.4 typescript: specifier: ^5.3.3 version: 5.9.3 @@ -312,7 +312,7 @@ importers: version: 1.1.1 esbuild: specifier: ^0.27.0 - version: 0.27.0 + version: 0.27.1 typescript: specifier: ^5.3.2 version: 5.9.3 @@ -324,7 +324,7 @@ importers: version: 2.0.0-rc13 '@nestjs/bullmq': specifier: ^11.0.1 - version: 11.0.4(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(bullmq@5.65.0) + version: 11.0.4(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(bullmq@5.66.0) '@nestjs/common': specifier: ^11.0.4 version: 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -339,7 +339,7 @@ importers: version: 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/websockets@11.1.9)(rxjs@7.8.2) '@nestjs/schedule': specifier: ^6.0.0 - version: 6.0.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9) + version: 6.1.0(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9) '@nestjs/swagger': specifier: ^11.0.2 version: 11.2.3(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2) @@ -381,10 +381,10 @@ importers: version: 1.38.0 '@react-email/components': specifier: ^0.5.0 - version: 0.5.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 0.5.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@react-email/render': specifier: ^1.1.2 - version: 1.4.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + version: 1.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@socket.io/redis-adapter': specifier: ^8.3.0 version: 8.3.0(socket.io-adapter@2.5.5) @@ -405,7 +405,7 @@ importers: version: 2.2.1 bullmq: specifier: ^5.51.0 - version: 5.65.0 + version: 5.66.0 chokidar: specifier: ^4.0.3 version: 4.0.3 @@ -425,14 +425,14 @@ importers: specifier: ^1.4.7 version: 1.4.7 cron: - specifier: 4.3.3 - version: 4.3.3 + specifier: 4.3.5 + version: 4.3.5 exiftool-vendored: - specifier: ^33.0.0 - version: 33.5.0 + specifier: ^34.0.0 + version: 34.1.0 express: specifier: ^5.1.0 - version: 5.2.0 + version: 5.2.1 fast-glob: specifier: ^3.3.2 version: 3.3.3 @@ -459,7 +459,7 @@ importers: version: 4.1.1 jsonwebtoken: specifier: ^9.0.2 - version: 9.0.2 + version: 9.0.3 kysely: specifier: 0.28.2 version: 0.28.2 @@ -480,7 +480,7 @@ importers: version: 2.0.2 nest-commander: specifier: ^3.16.0 - version: 3.20.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(@types/inquirer@8.2.11)(@types/node@24.10.1)(typescript@5.9.3) + version: 3.20.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(@types/inquirer@8.2.12)(@types/node@24.10.4)(typescript@5.9.3) nestjs-cls: specifier: ^5.0.0 version: 5.4.3(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) @@ -510,10 +510,10 @@ importers: version: 3.4.7 react: specifier: ^19.0.0 - version: 19.2.0 + version: 19.2.3 react-dom: specifier: ^19.0.0 - version: 19.2.0(react@19.2.0) + version: 19.2.3(react@19.2.3) react-email: specifier: ^4.0.0 version: 4.3.2 @@ -543,13 +543,13 @@ importers: version: 4.8.1 tailwindcss-preset-email: specifier: ^1.4.0 - version: 1.4.1(tailwindcss@3.4.18(yaml@2.8.2)) + version: 1.4.1(tailwindcss@3.4.19(yaml@2.8.2)) thumbhash: specifier: ^0.1.1 version: 0.1.1 ua-parser-js: specifier: ^2.0.0 - version: 2.0.6 + version: 2.0.7 uuid: specifier: ^11.1.0 version: 11.1.0 @@ -559,10 +559,10 @@ importers: devDependencies: '@eslint/js': specifier: ^9.8.0 - version: 9.39.1 + version: 9.39.2 '@nestjs/cli': specifier: ^11.0.2 - version: 11.0.13(@swc/core@1.15.3(@swc/helpers@0.5.17))(@types/node@24.10.1) + version: 11.0.14(@swc/core@1.15.5(@swc/helpers@0.5.17))(@types/node@24.10.4) '@nestjs/schematics': specifier: ^11.0.0 version: 11.0.9(chokidar@4.0.3)(typescript@5.9.3) @@ -571,7 +571,7 @@ importers: version: 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(@nestjs/platform-express@11.1.9) '@swc/core': specifier: ^1.4.14 - version: 1.15.3(@swc/helpers@0.5.17) + version: 1.15.5(@swc/helpers@0.5.17) '@types/archiver': specifier: ^7.0.0 version: 7.0.0 @@ -589,10 +589,10 @@ importers: version: 1.8.1 '@types/cookie-parser': specifier: ^1.4.8 - version: 1.4.10(@types/express@5.0.5) + version: 1.4.10(@types/express@5.0.6) '@types/express': specifier: ^5.0.0 - version: 5.0.5 + version: 5.0.6 '@types/fluent-ffmpeg': specifier: ^2.1.21 version: 2.1.28 @@ -615,8 +615,8 @@ importers: specifier: ^2.0.0 version: 2.0.0 '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^24.10.3 + version: 24.10.4 '@types/nodemailer': specifier: ^7.0.0 version: 7.0.4 @@ -646,19 +646,19 @@ 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.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) eslint: specifier: ^9.14.0 - version: 9.39.1(jiti@2.6.1) + version: 9.39.2(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.7.1) + version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.7.4) eslint-plugin-unicorn: specifier: ^62.0.0 - version: 62.0.0(eslint@9.39.1(jiti@2.6.1)) + version: 62.0.0(eslint@9.39.2(jiti@2.6.1)) globals: specifier: ^16.0.0 version: 16.5.0 @@ -672,38 +672,38 @@ importers: specifier: ^7.0.0 version: 7.0.0 prettier: - specifier: ^3.0.2 - version: 3.7.1 + specifier: ^3.7.4 + version: 3.7.4 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.3.0(prettier@3.7.1)(typescript@5.9.3) + version: 4.3.0(prettier@3.7.4)(typescript@5.9.3) sql-formatter: specifier: ^15.0.0 - version: 15.6.10 + version: 15.6.12 supertest: specifier: ^7.1.0 version: 7.1.4 tailwindcss: specifier: ^3.4.0 - version: 3.4.18(yaml@2.8.2) + version: 3.4.19(yaml@2.8.2) testcontainers: specifier: ^11.0.0 - version: 11.9.0 + version: 11.10.0 typescript: specifier: ^5.9.2 version: 5.9.3 typescript-eslint: specifier: ^8.28.0 - version: 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) unplugin-swc: specifier: ^1.4.5 - version: 1.5.9(@swc/core@1.15.3(@swc/helpers@0.5.17))(rollup@4.53.3) + version: 1.5.9(@swc/core@1.15.5(@swc/helpers@0.5.17))(rollup@4.53.4) vite-tsconfig-paths: specifier: ^5.0.0 - version: 5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) web: dependencies: @@ -717,8 +717,8 @@ importers: specifier: file:../open-api/typescript-sdk version: link:../open-api/typescript-sdk '@immich/ui': - specifier: ^0.49.2 - version: 0.49.3(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2) + specifier: ^0.50.1 + version: 0.50.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3) '@mapbox/mapbox-gl-rtl-text': specifier: 0.2.3 version: 0.2.3(mapbox-gl@1.13.3) @@ -751,7 +751,7 @@ importers: version: 0.41.4 '@zoom-image/svelte': specifier: ^0.3.0 - version: 0.3.8(svelte@5.45.2) + version: 0.3.8(svelte@5.43.3) async-mutex: specifier: ^0.5.0 version: 0.5.0 @@ -760,7 +760,7 @@ importers: version: 2.6.0 fabric: specifier: ^6.5.4 - version: 6.9.0 + version: 6.9.1 geo-coordinates-parser: specifier: ^1.7.4 version: 1.7.4 @@ -772,7 +772,7 @@ importers: version: 4.7.8 happy-dom: specifier: ^20.0.0 - version: 20.0.10 + version: 20.0.11 intl-messageformat: specifier: ^10.7.11 version: 10.7.18 @@ -787,7 +787,7 @@ importers: version: 3.7.2 maplibre-gl: specifier: ^5.6.2 - version: 5.13.0 + version: 5.14.0 pmtiles: specifier: ^4.3.0 version: 4.3.0 @@ -805,53 +805,56 @@ importers: version: 5.2.2 svelte-i18n: specifier: ^4.0.1 - version: 4.0.1(svelte@5.45.2) + version: 4.0.1(svelte@5.43.3) svelte-maplibre: specifier: ^1.2.5 - version: 1.2.5(svelte@5.45.2) + version: 1.2.5(svelte@5.43.3) svelte-persisted-store: specifier: ^0.12.0 - version: 0.12.0(svelte@5.45.2) + version: 0.12.0(svelte@5.43.3) tabbable: specifier: ^6.2.0 version: 6.3.0 thumbhash: specifier: ^0.1.1 version: 0.1.1 + uplot: + specifier: ^1.6.32 + version: 1.6.32 devDependencies: '@eslint/js': specifier: ^9.36.0 - version: 9.39.1 + version: 9.39.2 '@faker-js/faker': specifier: ^10.0.0 version: 10.1.0 '@koddsson/eslint-plugin-tscompat': specifier: ^0.2.0 - version: 0.2.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + version: 0.2.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@socket.io/component-emitter': specifier: ^3.1.0 version: 3.1.2 '@sveltejs/adapter-static': specifier: ^3.0.8 - version: 3.0.10(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))) + version: 3.0.10(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))) '@sveltejs/enhanced-img': specifier: ^0.9.0 - version: 0.9.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(rollup@4.53.3)(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 0.9.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(rollup@4.53.4)(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@sveltejs/kit': specifier: ^2.27.1 - version: 2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@sveltejs/vite-plugin-svelte': specifier: 6.2.1 - version: 6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@tailwindcss/vite': specifier: ^4.1.7 - version: 4.1.17(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 4.1.18(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(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.2.9(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 5.2.9(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@testing-library/user-event': specifier: ^14.5.2 version: 14.6.1(@testing-library/dom@10.4.1) @@ -875,25 +878,25 @@ importers: version: 1.5.6 '@vitest/coverage-v8': specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) dotenv: specifier: ^17.0.0 version: 17.2.3 eslint: specifier: ^9.36.0 - version: 9.39.1(jiti@2.6.1) + version: 9.39.2(jiti@2.6.1) eslint-config-prettier: specifier: ^10.1.8 - version: 10.1.8(eslint@9.39.1(jiti@2.6.1)) + version: 10.1.8(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-compat: specifier: ^6.0.2 - version: 6.0.2(eslint@9.39.1(jiti@2.6.1)) + version: 6.0.2(eslint@9.39.2(jiti@2.6.1)) eslint-plugin-svelte: specifier: ^3.12.4 - version: 3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@5.45.2) + version: 3.13.1(eslint@9.39.2(jiti@2.6.1))(svelte@5.43.3) eslint-plugin-unicorn: specifier: ^62.0.0 - version: 62.0.0(eslint@9.39.1(jiti@2.6.1)) + version: 62.0.0(eslint@9.39.2(jiti@2.6.1)) factory.ts: specifier: ^1.4.1 version: 1.4.2 @@ -901,58 +904,58 @@ importers: specifier: ^16.0.0 version: 16.5.0 prettier: - specifier: ^3.4.2 - version: 3.7.1 + specifier: ^3.7.4 + version: 3.7.4 prettier-plugin-organize-imports: specifier: ^4.0.0 - version: 4.3.0(prettier@3.7.1)(typescript@5.9.3) + version: 4.3.0(prettier@3.7.4)(typescript@5.9.3) prettier-plugin-sort-json: specifier: ^4.1.1 - version: 4.1.1(prettier@3.7.1) + version: 4.1.1(prettier@3.7.4) prettier-plugin-svelte: specifier: ^3.3.3 - version: 3.4.0(prettier@3.7.1)(svelte@5.45.2) + version: 3.4.1(prettier@3.7.4)(svelte@5.43.3) rollup-plugin-visualizer: specifier: ^6.0.0 - version: 6.0.5(rollup@4.53.3) + version: 6.0.5(rollup@4.53.4) svelte: - specifier: 5.45.2 - version: 5.45.2 + specifier: 5.43.3 + version: 5.43.3 svelte-check: specifier: ^4.1.5 - version: 4.3.4(picomatch@4.0.3)(svelte@5.45.2)(typescript@5.9.3) + version: 4.3.4(picomatch@4.0.3)(svelte@5.43.3)(typescript@5.9.3) svelte-eslint-parser: specifier: ^1.3.3 - version: 1.4.0(svelte@5.45.2) + version: 1.4.1(svelte@5.43.3) tailwindcss: specifier: ^4.1.7 - version: 4.1.17 + version: 4.1.18 typescript: specifier: ^5.8.3 version: 5.9.3 typescript-eslint: specifier: ^8.45.0 - version: 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + version: 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^7.1.2 - version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) vitest: specifier: ^3.0.0 - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) packages: '@adobe/css-tools@4.4.4': resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - '@ai-sdk/gateway@2.0.3': - resolution: {integrity: sha512-/vCoMKtod+A74/BbkWsaAflWKz1ovhX5lmJpIaXQXtd6gyexZncjotBTbFM8rVJT9LKJ/Kx7iVVo3vh+KT+IJg==} + '@ai-sdk/gateway@2.0.21': + resolution: {integrity: sha512-BwV7DU/lAm3Xn6iyyvZdWgVxgLu3SNXzl5y57gMvkW4nGhAOV5269IrJzQwGt03bb107sa6H6uJwWxc77zXoGA==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 - '@ai-sdk/provider-utils@3.0.14': - resolution: {integrity: sha512-CYRU6L7IlR7KslSBVxvlqlybQvXJln/PI57O8swhOaDIURZbjRP2AY3igKgUsrmWqqnFFUHP+AwTN8xqJAknnA==} + '@ai-sdk/provider-utils@3.0.19': + resolution: {integrity: sha512-W41Wc9/jbUVXVwCN/7bWa4IKe8MtxO3EyA0Hfhx6grnmiYlCvpI8neSYWFE0zScXJkgA/YK3BRybzgyiXuu6JA==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -961,18 +964,18 @@ packages: resolution: {integrity: sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA==} engines: {node: '>=18'} - '@ai-sdk/react@2.0.82': - resolution: {integrity: sha512-InaGqykKGFq/XA6Vhh2Hyy38nzeMpqp8eWxjTNEQA5Gwcal0BVNuZyTbTIL5t5VNXV+pQPDhe9ak1+mc9qxjog==} + '@ai-sdk/react@2.0.115': + resolution: {integrity: sha512-Etu7gWSEi2dmXss1PoR5CAZGwGShXsF9+Pon1eRO6EmatjYaBMhq1CfHPyYhGzWrint8jJIK2VaAhiMef29qZw==} engines: {node: '>=18'} peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc + react: ^18 || ~19.0.1 || ~19.1.2 || ^19.2.1 zod: ^3.25.76 || ^4.1.8 peerDependenciesMeta: zod: optional: true - '@algolia/abtesting@1.7.0': - resolution: {integrity: sha512-hOEItTFOvNLI6QX6TSGu7VE4XcUcdoKZT8NwDY+5mWwu87rGhkjlY7uesKTInlg6Sh8cyRkDBYRumxbkoBbBhA==} + '@algolia/abtesting@1.12.0': + resolution: {integrity: sha512-EfW0bfxjPs+C7ANkJDw2TATntfBKsFiy7APh+KO0pQ8A6HYa5I0NjFuCGCXWfzzzLXNZta3QUl3n5Kmm6aJo9Q==} engines: {node: '>= 14.0.0'} '@algolia/autocomplete-core@1.19.2': @@ -989,59 +992,59 @@ packages: '@algolia/client-search': '>= 4.9.1 < 6' algoliasearch: '>= 4.9.1 < 6' - '@algolia/client-abtesting@5.41.0': - resolution: {integrity: sha512-iRuvbEyuHCAhIMkyzG3tfINLxTS7mSKo7q8mQF+FbQpWenlAlrXnfZTN19LRwnVjx0UtAdZq96ThMWGS6cQ61A==} + '@algolia/client-abtesting@5.46.0': + resolution: {integrity: sha512-eG5xV8rujK4ZIHXrRshvv9O13NmU/k42Rnd3w43iKH5RaQ2zWuZO6Q7XjaoJjAFVCsJWqRbXzbYyPGrbF3wGNg==} engines: {node: '>= 14.0.0'} - '@algolia/client-analytics@5.41.0': - resolution: {integrity: sha512-OIPVbGfx/AO8l1V70xYTPSeTt/GCXPEl6vQICLAXLCk9WOUbcLGcy6t8qv0rO7Z7/M/h9afY6Af8JcnI+FBFdQ==} + '@algolia/client-analytics@5.46.0': + resolution: {integrity: sha512-AYh2uL8IUW9eZrbbT+wZElyb7QkkeV3US2NEKY7doqMlyPWE8lErNfkVN1NvZdVcY4/SVic5GDbeDz2ft8YIiQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-common@5.41.0': - resolution: {integrity: sha512-8Mc9niJvfuO8dudWN5vSUlYkz7U3M3X3m1crDLc9N7FZrIVoNGOUETPk3TTHviJIh9y6eKZKbq1hPGoGY9fqPA==} + '@algolia/client-common@5.46.0': + resolution: {integrity: sha512-0emZTaYOeI9WzJi0TcNd2k3SxiN6DZfdWc2x2gHt855Jl9jPUOzfVTL6gTvCCrOlT4McvpDGg5nGO+9doEjjig==} engines: {node: '>= 14.0.0'} - '@algolia/client-insights@5.41.0': - resolution: {integrity: sha512-vXzvCGZS6Ixxn+WyzGUVDeR3HO/QO5POeeWy1kjNJbEf6f+tZSI+OiIU9Ha+T3ntV8oXFyBEuweygw4OLmgfiQ==} + '@algolia/client-insights@5.46.0': + resolution: {integrity: sha512-wrBJ8fE+M0TDG1As4DDmwPn2TXajrvmvAN72Qwpuv8e2JOKNohF7+JxBoF70ZLlvP1A1EiH8DBu+JpfhBbNphQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-personalization@5.41.0': - resolution: {integrity: sha512-tkymXhmlcc7w/HEvLRiHcpHxLFcUB+0PnE9FcG6hfFZ1ZXiWabH+sX+uukCVnluyhfysU9HRU2kUmUWfucx1Dg==} + '@algolia/client-personalization@5.46.0': + resolution: {integrity: sha512-LnkeX4p0ENt0DoftDJJDzQQJig/sFQmD1eQifl/iSjhUOGUIKC/7VTeXRcKtQB78naS8njUAwpzFvxy1CDDXDQ==} engines: {node: '>= 14.0.0'} - '@algolia/client-query-suggestions@5.41.0': - resolution: {integrity: sha512-vyXDoz3kEZnosNeVQQwf0PbBt5IZJoHkozKRIsYfEVm+ylwSDFCW08qy2YIVSHdKy69/rWN6Ue/6W29GgVlmKQ==} + '@algolia/client-query-suggestions@5.46.0': + resolution: {integrity: sha512-aF9tc4ex/smypXw+W3lBPB1jjKoaGHpZezTqofvDOI/oK1dR2sdTpFpK2Ru+7IRzYgwtRqHF3znmTlyoNs9dpA==} engines: {node: '>= 14.0.0'} - '@algolia/client-search@5.41.0': - resolution: {integrity: sha512-G9I2atg1ShtFp0t7zwleP6aPS4DcZvsV4uoQOripp16aR6VJzbEnKFPLW4OFXzX7avgZSpYeBAS+Zx4FOgmpPw==} + '@algolia/client-search@5.46.0': + resolution: {integrity: sha512-22SHEEVNjZfFWkFks3P6HilkR3rS7a6GjnCIqR22Zz4HNxdfT0FG+RE7efTcFVfLUkTTMQQybvaUcwMrHXYa7Q==} engines: {node: '>= 14.0.0'} '@algolia/events@4.0.1': resolution: {integrity: sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==} - '@algolia/ingestion@1.41.0': - resolution: {integrity: sha512-sxU/ggHbZtmrYzTkueTXXNyifn+ozsLP+Wi9S2hOBVhNWPZ8uRiDTDcFyL7cpCs1q72HxPuhzTP5vn4sUl74cQ==} + '@algolia/ingestion@1.46.0': + resolution: {integrity: sha512-2LT0/Z+/sFwEpZLH6V17WSZ81JX2uPjgvv5eNlxgU7rPyup4NXXfuMbtCJ+6uc4RO/LQpEJd3Li59ke3wtyAsA==} engines: {node: '>= 14.0.0'} - '@algolia/monitoring@1.41.0': - resolution: {integrity: sha512-UQ86R6ixraHUpd0hn4vjgTHbViNO8+wA979gJmSIsRI3yli2v89QSFF/9pPcADR6PbtSio/99PmSNxhZy+CR3Q==} + '@algolia/monitoring@1.46.0': + resolution: {integrity: sha512-uivZ9wSWZ8mz2ZU0dgDvQwvVZV8XBv6lYBXf8UtkQF3u7WeTqBPeU8ZoeTyLpf0jAXCYOvc1mAVmK0xPLuEwOQ==} engines: {node: '>= 14.0.0'} - '@algolia/recommend@5.41.0': - resolution: {integrity: sha512-DxP9P8jJ8whJOnvmyA5mf1wv14jPuI0L25itGfOHSU6d4ZAjduVfPjTS3ROuUN5CJoTdlidYZE+DtfWHxJwyzQ==} + '@algolia/recommend@5.46.0': + resolution: {integrity: sha512-O2BB8DuySuddgOAbhyH4jsGbL+KyDGpzJRtkDZkv091OMomqIA78emhhMhX9d/nIRrzS1wNLWB/ix7Hb2eV5rg==} engines: {node: '>= 14.0.0'} - '@algolia/requester-browser-xhr@5.41.0': - resolution: {integrity: sha512-C21J+LYkE48fDwtLX7YXZd2Fn7Fe0/DOEtvohSfr/ODP8dGDhy9faaYeWB0n1AvmZltugjkjAXT7xk0CYNIXsQ==} + '@algolia/requester-browser-xhr@5.46.0': + resolution: {integrity: sha512-eW6xyHCyYrJD0Kjk9Mz33gQ40LfWiEA51JJTVfJy3yeoRSw/NXhAL81Pljpa0qslTs6+LO/5DYPZddct6HvISQ==} engines: {node: '>= 14.0.0'} - '@algolia/requester-fetch@5.41.0': - resolution: {integrity: sha512-FhJy/+QJhMx1Hajf2LL8og4J7SqOAHiAuUXq27cct4QnPhSIuIGROzeRpfDNH5BUbq22UlMuGd44SeD4HRAqvA==} + '@algolia/requester-fetch@5.46.0': + resolution: {integrity: sha512-Vn2+TukMGHy4PIxmdvP667tN/MhS7MPT8EEvEhS6JyFLPx3weLcxSa1F9gVvrfHWCUJhLWoMVJVB2PT8YfRGcw==} engines: {node: '>= 14.0.0'} - '@algolia/requester-node-http@5.41.0': - resolution: {integrity: sha512-tYv3rGbhBS0eZ5D8oCgV88iuWILROiemk+tQ3YsAKZv2J4kKUNvKkrX/If/SreRy4MGP2uJzMlyKcfSfO2mrsQ==} + '@algolia/requester-node-http@5.46.0': + resolution: {integrity: sha512-xaqXyna5yBZ+r1SJ9my/DM6vfTqJg9FJgVydRJ0lnO+D5NhqGW/qaRG/iBGKr/d4fho34el6WakV7BqJvrl/HQ==} engines: {node: '>= 14.0.0'} '@alloc/quick-lru@5.2.0': @@ -1083,9 +1086,6 @@ packages: resolution: {integrity: sha512-J4Jarr0SohdrHcb40gTL4wGPCQ952IMWF1G/MSAQfBAPvA9ZKApYhpxcY7PmehVePve+ujpus1dGsJ7dPxz8Kg==} engines: {node: ^18.19.1 || ^20.11.1 || >=22.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - '@asamuzakjp/css-color@3.2.0': - resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - '@aws-crypto/sha256-browser@5.2.0': resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} @@ -1099,48 +1099,48 @@ packages: '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-sdk/client-sesv2@3.939.0': - resolution: {integrity: sha512-vua5ZoOMMc/0yxAv6UsiN6pcaiqM+L7R1gLAki9fB3hHC+TvJAY0TX0eRrgTxV+ATyuD0lL3njrVA+xV8gHiEQ==} + '@aws-sdk/client-sesv2@3.952.0': + resolution: {integrity: sha512-0avirspZ7/RkHqp9It12xx6UJ2rkO6B6EeNScIgDkgyELl4tGsmF8bhBSPDqeJMZ1HQGYglanzkDRrYFgTN6iA==} engines: {node: '>=18.0.0'} - '@aws-sdk/client-sso@3.936.0': - resolution: {integrity: sha512-0G73S2cDqYwJVvqL08eakj79MZG2QRaB56Ul8/Ps9oQxllr7DMI1IQ/N3j3xjxgpq/U36pkoFZ8aK1n7Sbr3IQ==} + '@aws-sdk/client-sso@3.948.0': + resolution: {integrity: sha512-iWjchXy8bIAVBUsKnbfKYXRwhLgRg3EqCQ5FTr3JbR+QR75rZm4ZOYXlvHGztVTmtAZ+PQVA1Y4zO7v7N87C0A==} engines: {node: '>=18.0.0'} - '@aws-sdk/core@3.936.0': - resolution: {integrity: sha512-eGJ2ySUMvgtOziHhDRDLCrj473RJoL4J1vPjVM3NrKC/fF3/LoHjkut8AAnKmrW6a2uTzNKubigw8dEnpmpERw==} + '@aws-sdk/core@3.947.0': + resolution: {integrity: sha512-Khq4zHhuAkvCFuFbgcy3GrZTzfSX7ZIjIcW1zRDxXRLZKRtuhnZdonqTUfaWi5K42/4OmxkYNpsO7X7trQOeHw==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-env@3.936.0': - resolution: {integrity: sha512-dKajFuaugEA5i9gCKzOaVy9uTeZcApE+7Z5wdcZ6j40523fY1a56khDAUYkCfwqa7sHci4ccmxBkAo+fW1RChA==} + '@aws-sdk/credential-provider-env@3.947.0': + resolution: {integrity: sha512-VR2V6dRELmzwAsCpK4GqxUi6UW5WNhAXS9F9AzWi5jvijwJo3nH92YNJUP4quMpgFZxJHEWyXLWgPjh9u0zYOA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-http@3.936.0': - resolution: {integrity: sha512-5FguODLXG1tWx/x8fBxH+GVrk7Hey2LbXV5h9SFzYCx/2h50URBm0+9hndg0Rd23+xzYe14F6SI9HA9c1sPnjg==} + '@aws-sdk/credential-provider-http@3.947.0': + resolution: {integrity: sha512-inF09lh9SlHj63Vmr5d+LmwPXZc2IbK8lAruhOr3KLsZAIHEgHgGPXWDC2ukTEMzg0pkexQ6FOhXXad6klK4RA==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-ini@3.939.0': - resolution: {integrity: sha512-RHQ3xKz5pn5PMuoBYNYLMIdN4iU8gklxcsfJzOflSrwkhb8ukVRS9LjHXUtyE4qQ2J+dfj1QSr4PFOSxvzRZkA==} + '@aws-sdk/credential-provider-ini@3.952.0': + resolution: {integrity: sha512-N5B15SwzMkZ8/LLopNksTlPEWWZn5tbafZAUfMY5Xde4rSHGWmv5H/ws2M3P8L0X77E2wKnOJsNmu+GsArBreQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-login@3.939.0': - resolution: {integrity: sha512-SbbzlsH2ZSsu2szyl494QOUS69LZgU8bYlFoDnUxy2L89YzLyR4D9wWlJzKCm4cS1eyNxPsOMkbVVL42JRvdZw==} + '@aws-sdk/credential-provider-login@3.952.0': + resolution: {integrity: sha512-jL9zc+e+7sZeJrHzYKK9GOjl1Ktinh0ORU3cM2uRBi7fuH/0zV9pdMN8PQnGXz0i4tJaKcZ1lrE4V0V6LB9NQg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-node@3.939.0': - resolution: {integrity: sha512-OAwCqDNlKC3JmWb+N0zFfsPJJ8J5b8ZD63vWHdSf9c7ZlRKpFRD/uePqVMQKOq4h3DO0P0smAPk/m5p66oYLrw==} + '@aws-sdk/credential-provider-node@3.952.0': + resolution: {integrity: sha512-pj7nidLrb3Dz9llcUPh6N0Yv1dBYTS9xJqi8u0kI8D5sn72HJMB+fIOhcDQVXXAw/dpVolOAH9FOAbog5JDAMg==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-process@3.936.0': - resolution: {integrity: sha512-GpA4AcHb96KQK2PSPUyvChvrsEKiLhQ5NWjeef2IZ3Jc8JoosiedYqp6yhZR+S8cTysuvx56WyJIJc8y8OTrLA==} + '@aws-sdk/credential-provider-process@3.947.0': + resolution: {integrity: sha512-WpanFbHe08SP1hAJNeDdBDVz9SGgMu/gc0XJ9u3uNpW99nKZjDpvPRAdW7WLA4K6essMjxWkguIGNOpij6Do2Q==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-sso@3.939.0': - resolution: {integrity: sha512-gXWI+5xf+2n7kJSqYgDw1VkNLGRe2IYNCjOW/F04/7l8scxOP84SZ634OI9IR/8JWvFwMUjxH4JigPU0j6ZWzQ==} + '@aws-sdk/credential-provider-sso@3.952.0': + resolution: {integrity: sha512-1CQdP5RzxeXuEfytbAD5TgreY1c9OacjtCdO8+n9m05tpzBABoNBof0hcjzw1dtrWFH7deyUgfwCl1TAN3yBWQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/credential-provider-web-identity@3.939.0': - resolution: {integrity: sha512-b/ySLC6DfWwZIAP2Glq9mkJJ/9LIDiKfYN2f9ZenQF+k2lO1i6/QtBuslvLmBJ+mNz0lPRSHW29alyqOpBgeCQ==} + '@aws-sdk/credential-provider-web-identity@3.952.0': + resolution: {integrity: sha512-5hJbfaZdHDAP8JlwplNbXJAat9Vv7L0AbTZzkbPIgjHhC3vrMf5r3a6I1HWFp5i5pXo7J45xyuf5uQGZJxJlCg==} engines: {node: '>=18.0.0'} '@aws-sdk/middleware-host-header@3.936.0': @@ -1151,32 +1151,32 @@ packages: resolution: {integrity: sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-recursion-detection@3.936.0': - resolution: {integrity: sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==} + '@aws-sdk/middleware-recursion-detection@3.948.0': + resolution: {integrity: sha512-Qa8Zj+EAqA0VlAVvxpRnpBpIWJI9KUwaioY1vkeNVwXPlNaz9y9zCKVM9iU9OZ5HXpoUg6TnhATAHXHAE8+QsQ==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-sdk-s3@3.939.0': - resolution: {integrity: sha512-9WMPAAyuSPvEawZJ5ndZKD+UZuISGS885kFyNyfHCNNWMws8Rohji6nysda2gL8SSpGdbvTBZRjSIzim13bYRg==} + '@aws-sdk/middleware-sdk-s3@3.947.0': + resolution: {integrity: sha512-DS2tm5YBKhPW2PthrRBDr6eufChbwXe0NjtTZcYDfUCXf0OR+W6cIqyKguwHMJ+IyYdey30AfVw9/Lb5KB8U8A==} engines: {node: '>=18.0.0'} - '@aws-sdk/middleware-user-agent@3.936.0': - resolution: {integrity: sha512-YB40IPa7K3iaYX0lSnV9easDOLPLh+fJyUDF3BH8doX4i1AOSsYn86L4lVldmOaSX+DwiaqKHpvk4wPBdcIPWw==} + '@aws-sdk/middleware-user-agent@3.947.0': + resolution: {integrity: sha512-7rpKV8YNgCP2R4F9RjWZFcD2R+SO/0R4VHIbY9iZJdH2MzzJ8ZG7h8dZ2m8QkQd1fjx4wrFJGGPJUTYXPV3baA==} engines: {node: '>=18.0.0'} - '@aws-sdk/nested-clients@3.939.0': - resolution: {integrity: sha512-QeNsjHBCbsVRbgEt9FZNnrrbMTUuIYML3FX5xFgEJz4aI5uXwMBjYOi5TvAY+Y4CBHY4cp3dd/zSpHu0gX68GQ==} + '@aws-sdk/nested-clients@3.952.0': + resolution: {integrity: sha512-OtuirjxuOqZyDcI0q4WtoyWfkq3nSnbH41JwJQsXJefduWcww1FQe5TL1JfYCU7seUxHzK8rg2nFxUBuqUlZtg==} engines: {node: '>=18.0.0'} '@aws-sdk/region-config-resolver@3.936.0': resolution: {integrity: sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==} engines: {node: '>=18.0.0'} - '@aws-sdk/signature-v4-multi-region@3.939.0': - resolution: {integrity: sha512-pERVG90nneZWIenPvPoOnEcfqpUHiL9KMHf+TtHIWSBcaRL1kWuNm4CfEs7mo4EM0LHbaMgoZma6woIsJ6MOwA==} + '@aws-sdk/signature-v4-multi-region@3.947.0': + resolution: {integrity: sha512-UaYmzoxf9q3mabIA2hc4T6x5YSFUG2BpNjAZ207EA1bnQMiK+d6vZvb83t7dIWL/U1de1sGV19c1C81Jf14rrA==} engines: {node: '>=18.0.0'} - '@aws-sdk/token-providers@3.939.0': - resolution: {integrity: sha512-paNeLZdr2/sk7XYMZz2OIqFFF3AkA5vUpKYahVDYmMeiMecQTqa/EptA3aVvWa4yWobEF0Kk+WSUPrOIGI3eQg==} + '@aws-sdk/token-providers@3.952.0': + resolution: {integrity: sha512-IpQVC9WOeXQlCEcFVNXWDIKy92CH1Az37u9K0H3DF/HT56AjhyDVKQQfHUy00nt7bHFe3u0K5+zlwErBeKy5ZA==} engines: {node: '>=18.0.0'} '@aws-sdk/types@3.936.0': @@ -1198,8 +1198,8 @@ packages: '@aws-sdk/util-user-agent-browser@3.936.0': resolution: {integrity: sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==} - '@aws-sdk/util-user-agent-node@3.936.0': - resolution: {integrity: sha512-XOEc7PF9Op00pWV2AYCGDSu5iHgYjIO53Py2VUQTIvP7SRCaCsXmA33mjBvC2Ms6FhSyWNa4aK4naUGIz0hQcw==} + '@aws-sdk/util-user-agent-node@3.947.0': + resolution: {integrity: sha512-+vhHoDrdbb+zerV4noQk1DHaUMNzWFWPpPYjVTwW2186k5BEJIecAMChYkghRrBVJ3KPWP1+JnZwOd72F3d4rQ==} engines: {node: '>=18.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1211,8 +1211,8 @@ packages: resolution: {integrity: sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==} engines: {node: '>=18.0.0'} - '@aws/lambda-invoke-store@0.2.1': - resolution: {integrity: sha512-sIyFcoPZkTtNu9xFeEoynMef3bPJIAbOfUh+ueYcfhVl6xm2VRtMcMclSxmZCMnHHd4hlYKJeq/aggmBEWynww==} + '@aws/lambda-invoke-store@0.2.2': + resolution: {integrity: sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==} engines: {node: '>=18.0.0'} '@babel/code-frame@7.27.1': @@ -2003,6 +2003,12 @@ packages: peerDependencies: postcss: ^8.4 + '@csstools/postcss-position-area-property@1.0.0': + resolution: {integrity: sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + '@csstools/postcss-progressive-custom-properties@4.2.1': resolution: {integrity: sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==} engines: {node: '>=18'} @@ -2039,6 +2045,12 @@ packages: peerDependencies: postcss: ^8.4 + '@csstools/postcss-system-ui-font-family@1.0.0': + resolution: {integrity: sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + '@csstools/postcss-text-decoration-shorthand@4.0.3': resolution: {integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==} engines: {node: '>=18'} @@ -2079,11 +2091,25 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} - '@docsearch/css@4.2.0': - resolution: {integrity: sha512-65KU9Fw5fGsPPPlgIghonMcndyx1bszzrDQYLfierN+Ha29yotMHzVS94bPkZS6On9LS8dE4qmW4P/fGjtCf/g==} + '@docsearch/core@4.3.1': + resolution: {integrity: sha512-ktVbkePE+2h9RwqCUMbWXOoebFyDOxHqImAqfs+lC8yOU+XwEW4jgvHGJK079deTeHtdhUNj0PXHSnhJINvHzQ==} + peerDependencies: + '@types/react': '>= 16.8.0 < 20.0.0' + react: '>= 16.8.0 < 20.0.0' + react-dom: '>= 16.8.0 < 20.0.0' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true - '@docsearch/react@4.2.0': - resolution: {integrity: sha512-zSN/KblmtBcerf7Z87yuKIHZQmxuXvYc6/m0+qnjyNu+Ir67AVOagTa1zBqcxkVUVkmBqUExdcyrdo9hbGbqTw==} + '@docsearch/css@4.3.2': + resolution: {integrity: sha512-K3Yhay9MgkBjJJ0WEL5MxnACModX9xuNt3UlQQkDEDZJZ0+aeWKtOkxHNndMRkMBnHdYvQjxkm6mdlneOtU1IQ==} + + '@docsearch/react@4.3.2': + resolution: {integrity: sha512-74SFD6WluwvgsOPqifYOviEEVwDxslxfhakTlra+JviaNcs7KK/rjsPj89kVEoQc9FUxRkAofaJnHIR7pb4TSQ==} peerDependencies: '@types/react': '>= 16.8.0 < 20.0.0' react: '>= 16.8.0 < 20.0.0' @@ -2284,8 +2310,8 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.0': - resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + '@esbuild/aix-ppc64@0.27.1': + resolution: {integrity: sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] @@ -2302,8 +2328,8 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.0': - resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + '@esbuild/android-arm64@0.27.1': + resolution: {integrity: sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] @@ -2320,8 +2346,8 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.0': - resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + '@esbuild/android-arm@0.27.1': + resolution: {integrity: sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg==} engines: {node: '>=18'} cpu: [arm] os: [android] @@ -2338,8 +2364,8 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.0': - resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + '@esbuild/android-x64@0.27.1': + resolution: {integrity: sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ==} engines: {node: '>=18'} cpu: [x64] os: [android] @@ -2356,8 +2382,8 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.0': - resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + '@esbuild/darwin-arm64@0.27.1': + resolution: {integrity: sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] @@ -2374,8 +2400,8 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.0': - resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + '@esbuild/darwin-x64@0.27.1': + resolution: {integrity: sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] @@ -2392,8 +2418,8 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.0': - resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + '@esbuild/freebsd-arm64@0.27.1': + resolution: {integrity: sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] @@ -2410,8 +2436,8 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.0': - resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + '@esbuild/freebsd-x64@0.27.1': + resolution: {integrity: sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] @@ -2428,8 +2454,8 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.0': - resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + '@esbuild/linux-arm64@0.27.1': + resolution: {integrity: sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q==} engines: {node: '>=18'} cpu: [arm64] os: [linux] @@ -2446,8 +2472,8 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.0': - resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + '@esbuild/linux-arm@0.27.1': + resolution: {integrity: sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA==} engines: {node: '>=18'} cpu: [arm] os: [linux] @@ -2464,8 +2490,8 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.0': - resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + '@esbuild/linux-ia32@0.27.1': + resolution: {integrity: sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] @@ -2482,8 +2508,8 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.0': - resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + '@esbuild/linux-loong64@0.27.1': + resolution: {integrity: sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] @@ -2500,8 +2526,8 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.0': - resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + '@esbuild/linux-mips64el@0.27.1': + resolution: {integrity: sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] @@ -2518,8 +2544,8 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.0': - resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + '@esbuild/linux-ppc64@0.27.1': + resolution: {integrity: sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] @@ -2536,8 +2562,8 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.0': - resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + '@esbuild/linux-riscv64@0.27.1': + resolution: {integrity: sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] @@ -2554,8 +2580,8 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.0': - resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + '@esbuild/linux-s390x@0.27.1': + resolution: {integrity: sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] @@ -2572,8 +2598,8 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.0': - resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + '@esbuild/linux-x64@0.27.1': + resolution: {integrity: sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA==} engines: {node: '>=18'} cpu: [x64] os: [linux] @@ -2584,8 +2610,8 @@ packages: cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.0': - resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + '@esbuild/netbsd-arm64@0.27.1': + resolution: {integrity: sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] @@ -2602,8 +2628,8 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.0': - resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + '@esbuild/netbsd-x64@0.27.1': + resolution: {integrity: sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] @@ -2614,8 +2640,8 @@ packages: cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.0': - resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + '@esbuild/openbsd-arm64@0.27.1': + resolution: {integrity: sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] @@ -2632,8 +2658,8 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.0': - resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + '@esbuild/openbsd-x64@0.27.1': + resolution: {integrity: sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] @@ -2644,8 +2670,8 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.0': - resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + '@esbuild/openharmony-arm64@0.27.1': + resolution: {integrity: sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] @@ -2662,8 +2688,8 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.0': - resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + '@esbuild/sunos-x64@0.27.1': + resolution: {integrity: sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] @@ -2680,8 +2706,8 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.0': - resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + '@esbuild/win32-arm64@0.27.1': + resolution: {integrity: sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg==} engines: {node: '>=18'} cpu: [arm64] os: [win32] @@ -2698,8 +2724,8 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.0': - resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + '@esbuild/win32-ia32@0.27.1': + resolution: {integrity: sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ==} engines: {node: '>=18'} cpu: [ia32] os: [win32] @@ -2716,8 +2742,8 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.0': - resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + '@esbuild/win32-x64@0.27.1': + resolution: {integrity: sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -2744,12 +2770,12 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} + '@eslint/js@9.39.2': + resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.7': @@ -2805,8 +2831,8 @@ packages: '@nestjs/common': ^11.0.20 '@nestjs/core': ^11.0.20 - '@grpc/grpc-js@1.14.2': - resolution: {integrity: sha512-QzVUtEFyu05UNx2xr0fCQmStUO17uVQhGNowtxs00IgTZT6/W2PBLfUkj30s0FKJ29VtTa3ArVNIhNP6akQhqA==} + '@grpc/grpc-js@1.14.3': + resolution: {integrity: sha512-Iq8QQQ/7X3Sac15oB6p0FmUg/klxQvXLeileoqrTRGJYLV+/9tubbr9ipz0GKHjmXVsgFPo/+W+2cA8eNcR+XA==} engines: {node: '>=12.10.0'} '@grpc/proto-loader@0.7.15': @@ -2986,8 +3012,8 @@ packages: peerDependencies: svelte: ^5.0.0 - '@immich/ui@0.49.3': - resolution: {integrity: sha512-joqT72Y6gmGK6z25Suzr2VhYANrLo43g20T4UHmbQenz/z/Ax6sl1Ao9SjIOwEkKMm9N3Txoh7WOOzmHVl04OA==} + '@immich/ui@0.50.1': + resolution: {integrity: sha512-fNlQGh75ZFa/UZAgJaYk9/ItHOXHNNzN4CunjCmE7WocVVkUZbUxopN9Ku3F5GULSqD/zJ5gNO6PQAZ1ZoSaaQ==} peerDependencies: svelte: ^5.0.0 @@ -3230,9 +3256,11 @@ packages: resolution: {integrity: sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw==} engines: {node: '>= 14.0.0'} - '@koa/router@14.0.0': - resolution: {integrity: sha512-LBSu5K0qAaaQcXX/0WIB9PGDevyCxxpnc1uq13vV/CgObaVxuis5hKl3Eboq/8gcb6ebnkAStW9NB/Em2eYyFA==} + '@koa/router@15.1.0': + resolution: {integrity: sha512-0zCmuapmgBHrfVSFjBfCdgnkBnXwRGcG5qHnxVs8ZoTNEJiwSSspgJ5+2NugiqLJS/S0d96KMeNntLqTNWaioQ==} engines: {node: '>= 20'} + peerDependencies: + koa: ^2.0.0 || ^3.0.0 '@koddsson/eslint-plugin-tscompat@0.2.0': resolution: {integrity: sha512-Oqd4kWSX0LiO9wWHjcmDfXZNC7TotFV/tLRhwCFU3XUeb//KYvJ75c9OmeSJ+vBv5lkCeB+xYsqyNrBc5j18XA==} @@ -3297,15 +3325,15 @@ packages: resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} engines: {node: '>=6.0.0'} - '@maplibre/maplibre-gl-style-spec@24.3.1': - resolution: {integrity: sha512-TUM5JD40H2mgtVXl5IwWz03BuQabw8oZQLJTmPpJA0YTYF+B+oZppy5lNMO6bMvHzB+/5mxqW9VLG3wFdeqtOw==} + '@maplibre/maplibre-gl-style-spec@24.4.1': + resolution: {integrity: sha512-UKhA4qv1h30XT768ccSv5NjNCX+dgfoq2qlLVmKejspPcSQTYD4SrVucgqegmYcKcmwf06wcNAa/kRd0NHWbUg==} hasBin: true - '@maplibre/mlt@1.1.0': - resolution: {integrity: sha512-anR8WxKIgZUJQLlZtID0v06wd9Q//9K/6lLLU3dOzmeO/xLEzAwmEqP24jEnEUBcnZGkM4vidz9H6Q4guNAAlw==} + '@maplibre/mlt@1.1.2': + resolution: {integrity: sha512-SQKdJ909VGROkA6ovJgtHNs9YXV4YXUPS+VaZ50I2Mt951SLlUm2Cv34x5Xwc1HiFlsd3h2Yrs5cn7xzqBmENw==} - '@maplibre/vt-pbf@4.0.3': - resolution: {integrity: sha512-YsW99BwnT+ukJRkseBcLuZHfITB4puJoxnqPVjo72rhW/TaawVYsgQHcqWLzTxqknttYoDpgyERzWSa/XrETdA==} + '@maplibre/vt-pbf@4.2.0': + resolution: {integrity: sha512-bxrk/kQUwWXZgmqYgwOCnZCMONCRi3MJMqJdza4T3E4AeR5i+VyMnaJ8iDWtWxdfEAJRtrzIOeJtxZSy5mFrFA==} '@mdi/js@7.4.47': resolution: {integrity: sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==} @@ -3316,8 +3344,8 @@ packages: '@mdn/browser-compat-data@5.7.6': resolution: {integrity: sha512-7xdrMX0Wk7grrTZQwAoy1GkvPMFoizStUoL+VmtUkAxegbCCec+3FKwOM6yc/uGU5+BEczQHXAlWiqvM8JeENg==} - '@mdn/browser-compat-data@6.0.27': - resolution: {integrity: sha512-s5kTuDih5Ysb7DS2T2MhvneFLvDS0NwnLY5Jv6dL+zBXbcNVcyFcGdjwn3rttiHvcbb/qF02HP9ywufdwHZbIw==} + '@mdn/browser-compat-data@6.1.5': + resolution: {integrity: sha512-PzdZZzRhcXvKB0begee28n5lvwAcinGKYuLZOVxHAZm+n7y01ddEGfdS1ZXRuVcV+ndG6mSEAE8vgudom5UjYg==} '@mdx-js/mdx@3.1.1': resolution: {integrity: sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==} @@ -3377,8 +3405,8 @@ packages: '@nestjs/core': ^10.0.0 || ^11.0.0 bullmq: ^3.0.0 || ^4.0.0 || ^5.0.0 - '@nestjs/cli@11.0.13': - resolution: {integrity: sha512-cPDDahP/IPDcqraIHjUZQXPupYQDoZlBRFOjgM76vVfcVnWQ45TUaat0tgR2ptfeQG0gY2kwtm4/JYwe5xu/8A==} + '@nestjs/cli@11.0.14': + resolution: {integrity: sha512-YwP03zb5VETTwelXU+AIzMVbEZKk/uxJL+z9pw0mdG9ogAtqZ6/mpmIM4nEq/NU8D0a7CBRLcMYUmWW/55pfqw==} engines: {node: '>= 20.11'} hasBin: true peerDependencies: @@ -3447,8 +3475,8 @@ packages: '@nestjs/websockets': ^11.0.0 rxjs: ^7.1.0 - '@nestjs/schedule@6.0.1': - resolution: {integrity: sha512-v3yO6cSPAoBSSyH67HWnXHzuhPhSNZhRmLY38JvCt2sqY8sPMOODpcU1D79iUMFf7k16DaMEbL4Mgx61ZhiC8Q==} + '@nestjs/schedule@6.1.0': + resolution: {integrity: sha512-W25Ydc933Gzb1/oo7+bWzzDiOissE+h/dhIAPugA39b9MuIzBbLybuXpc1AjoQLczO3v0ldmxaffVl87W0uqoQ==} peerDependencies: '@nestjs/common': ^10.0.0 || ^11.0.0 '@nestjs/core': ^10.0.0 || ^11.0.0 @@ -3529,8 +3557,8 @@ packages: engines: {node: ^14.18.0 || >=16.10.0, npm: '>=5.10.0'} hasBin: true - '@oazapfts/runtime@1.0.4': - resolution: {integrity: sha512-7t6C2shug/6tZhQgkCa532oTYBLEnbASV/i1SG1rH2GB4h3aQQujYciYSPT92hvN4IwTe8S2hPkN/6iiOyTlCg==} + '@oazapfts/runtime@1.1.0': + resolution: {integrity: sha512-PwCn69pexqg/uhc0bpEHSlRFdfTtSnq3icXHd0wf4BQwZSMKsCerTnydzegVScEegYkokzIxMcl9li7on86A2w==} '@opentelemetry/api-logs@0.208.0': resolution: {integrity: sha512-CjruKY9V6NMssL/T1kAFgzosF1v9o6oeN+aX5JB/C/xPNtmgIJqcXHG7fA82Ou1zCpWGl4lROQUKwUNE1pMCyg==} @@ -3618,8 +3646,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.0.0 - '@opentelemetry/host-metrics@0.36.0': - resolution: {integrity: sha512-14lNY57qa21V3ZOl6xrqLMHR0HGlnPIApR6hr3oCw/Dqs5IzxhTwt2X8Stn82vWJJis7j/ezn11oODsizHj2dQ==} + '@opentelemetry/host-metrics@0.36.2': + resolution: {integrity: sha512-eMdea86cfIqx3cdFpcKU3StrjqFkQDIVp7NANVnVWO8O6hDw/DBwGwu4Gi1wJCuoQ2JVwKNWQxUTSRheB6O29Q==} engines: {node: ^18.19.0 || >=20.6.0} peerDependencies: '@opentelemetry/api': ^1.3.0 @@ -3734,8 +3762,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 - '@paralleldrive/cuid2@2.2.2': - resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} + '@paralleldrive/cuid2@2.3.1': + resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} '@photo-sphere-viewer/core@5.14.0': resolution: {integrity: sha512-V0JeDSB1D2Q60Zqn7+0FPjq8gqbKEwuxMzNdTLydefkQugVztLvdZykO+4k5XTpweZ2QAWPH/QOI1xZbsdvR9A==} @@ -3962,113 +3990,113 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.53.3': - resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + '@rollup/rollup-android-arm-eabi@4.53.4': + resolution: {integrity: sha512-PWU3Y92H4DD0bOqorEPp1Y0tbzwAurFmIYpjcObv5axGVOtcTlB0b2UKMd2echo08MgN7jO8WQZSSysvfisFSQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.3': - resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} + '@rollup/rollup-android-arm64@4.53.4': + resolution: {integrity: sha512-Gw0/DuVm3rGsqhMGYkSOXXIx20cC3kTlivZeuaGt4gEgILivykNyBWxeUV5Cf2tDA2nPLah26vq3emlRrWVbng==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.3': - resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + '@rollup/rollup-darwin-arm64@4.53.4': + resolution: {integrity: sha512-+w06QvXsgzKwdVg5qRLZpTHh1bigHZIqoIUPtiqh05ZiJVUQ6ymOxaPkXTvRPRLH88575ZCRSRM3PwIoNma01Q==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.3': - resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + '@rollup/rollup-darwin-x64@4.53.4': + resolution: {integrity: sha512-EB4Na9G2GsrRNRNFPuxfwvDRDUwQEzJPpiK1vo2zMVhEeufZ1k7J1bKnT0JYDfnPC7RNZ2H5YNQhW6/p2QKATw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.3': - resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + '@rollup/rollup-freebsd-arm64@4.53.4': + resolution: {integrity: sha512-bldA8XEqPcs6OYdknoTMaGhjytnwQ0NClSPpWpmufOuGPN5dDmvIa32FygC2gneKK4A1oSx86V1l55hyUWUYFQ==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.3': - resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + '@rollup/rollup-freebsd-x64@4.53.4': + resolution: {integrity: sha512-3T8GPjH6mixCd0YPn0bXtcuSXi1Lj+15Ujw2CEb7dd24j9thcKscCf88IV7n76WaAdorOzAgSSbuVRg4C8V8Qw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': - resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} + '@rollup/rollup-linux-arm-gnueabihf@4.53.4': + resolution: {integrity: sha512-UPMMNeC4LXW7ZSHxeP3Edv09aLsFUMaD1TSVW6n1CWMECnUIJMFFB7+XC2lZTdPtvB36tYC0cJWc86mzSsaviw==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.3': - resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + '@rollup/rollup-linux-arm-musleabihf@4.53.4': + resolution: {integrity: sha512-H8uwlV0otHs5Q7WAMSoyvjV9DJPiy5nJ/xnHolY0QptLPjaSsuX7tw+SPIfiYH6cnVx3fe4EWFafo6gH6ekZKA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.3': - resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} + '@rollup/rollup-linux-arm64-gnu@4.53.4': + resolution: {integrity: sha512-BLRwSRwICXz0TXkbIbqJ1ibK+/dSBpTJqDClF61GWIrxTXZWQE78ROeIhgl5MjVs4B4gSLPCFeD4xML9vbzvCQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.53.3': - resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} + '@rollup/rollup-linux-arm64-musl@4.53.4': + resolution: {integrity: sha512-6bySEjOTbmVcPJAywjpGLckK793A0TJWSbIa0sVwtVGfe/Nz6gOWHOwkshUIAp9j7wg2WKcA4Snu7Y1nUZyQew==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.3': - resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + '@rollup/rollup-linux-loong64-gnu@4.53.4': + resolution: {integrity: sha512-U0ow3bXYJZ5MIbchVusxEycBw7bO6C2u5UvD31i5IMTrnt2p4Fh4ZbHSdc/31TScIJQYHwxbj05BpevB3201ug==} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.3': - resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} + '@rollup/rollup-linux-ppc64-gnu@4.53.4': + resolution: {integrity: sha512-iujDk07ZNwGLVn0YIWM80SFN039bHZHCdCCuX9nyx3Jsa2d9V/0Y32F+YadzwbvDxhSeVo9zefkoPnXEImnM5w==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.3': - resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} + '@rollup/rollup-linux-riscv64-gnu@4.53.4': + resolution: {integrity: sha512-MUtAktiOUSu+AXBpx1fkuG/Bi5rhlorGs3lw5QeJ2X3ziEGAq7vFNdWVde6XGaVqi0LGSvugwjoxSNJfHFTC0g==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.3': - resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + '@rollup/rollup-linux-riscv64-musl@4.53.4': + resolution: {integrity: sha512-btm35eAbDfPtcFEgaXCI5l3c2WXyzwiE8pArhd66SDtoLWmgK5/M7CUxmUglkwtniPzwvWioBKKl6IXLbPf2sQ==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.3': - resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + '@rollup/rollup-linux-s390x-gnu@4.53.4': + resolution: {integrity: sha512-uJlhKE9ccUTCUlK+HUz/80cVtx2RayadC5ldDrrDUFaJK0SNb8/cCmC9RhBhIWuZ71Nqj4Uoa9+xljKWRogdhA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.3': - resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + '@rollup/rollup-linux-x64-gnu@4.53.4': + resolution: {integrity: sha512-jjEMkzvASQBbzzlzf4os7nzSBd/cvPrpqXCUOqoeCh1dQ4BP3RZCJk8XBeik4MUln3m+8LeTJcY54C/u8wb3DQ==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.3': - resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + '@rollup/rollup-linux-x64-musl@4.53.4': + resolution: {integrity: sha512-lu90KG06NNH19shC5rBPkrh6mrTpq5kviFylPBXQVpdEu0yzb0mDgyxLr6XdcGdBIQTH/UAhDJnL+APZTBu1aQ==} cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.53.3': - resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + '@rollup/rollup-openharmony-arm64@4.53.4': + resolution: {integrity: sha512-dFDcmLwsUzhAm/dn0+dMOQZoONVYBtgik0VuY/d5IJUUb787L3Ko/ibvTvddqhb3RaB7vFEozYevHN4ox22R/w==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.3': - resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + '@rollup/rollup-win32-arm64-msvc@4.53.4': + resolution: {integrity: sha512-WvUpUAWmUxZKtRnQWpRKnLW2DEO8HB/l8z6oFFMNuHndMzFTJEXzaYJ5ZAmzNw0L21QQJZsUQFt2oPf3ykAD/w==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.3': - resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + '@rollup/rollup-win32-ia32-msvc@4.53.4': + resolution: {integrity: sha512-JGbeF2/FDU0x2OLySw/jgvkwWUo05BSiJK0dtuI4LyuXbz3wKiC1xHhLB1Tqm5VU6ZZDmAorj45r/IgWNWku5g==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.3': - resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + '@rollup/rollup-win32-x64-gnu@4.53.4': + resolution: {integrity: sha512-zuuC7AyxLWLubP+mlUwEyR8M1ixW1ERNPHJfXm8x7eQNP4Pzkd7hS3qBuKBR70VRiQ04Kw8FNfRMF5TNxuZq2g==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.3': - resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + '@rollup/rollup-win32-x64-msvc@4.53.4': + resolution: {integrity: sha512-Sbx45u/Lbb5RyptSbX7/3deP+/lzEmZ0BTSHxwxN/IMOZDZf8S0AGo0hJD5n/LQssxb5Z3B4og4P2X6Dd8acCA==} cpu: [x64] os: [win32] @@ -4107,32 +4135,32 @@ packages: '@slorber/remark-comment@1.0.0': resolution: {integrity: sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==} - '@smithy/abort-controller@4.2.5': - resolution: {integrity: sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==} + '@smithy/abort-controller@4.2.6': + resolution: {integrity: sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==} engines: {node: '>=18.0.0'} - '@smithy/config-resolver@4.4.3': - resolution: {integrity: sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==} + '@smithy/config-resolver@4.4.4': + resolution: {integrity: sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==} engines: {node: '>=18.0.0'} - '@smithy/core@3.18.5': - resolution: {integrity: sha512-6gnIz3h+PEPQGDj8MnRSjDvKBah042jEoPgjFGJ4iJLBE78L4lY/n98x14XyPF4u3lN179Ub/ZKFY5za9GeLQw==} + '@smithy/core@3.19.0': + resolution: {integrity: sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==} engines: {node: '>=18.0.0'} - '@smithy/credential-provider-imds@4.2.5': - resolution: {integrity: sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==} + '@smithy/credential-provider-imds@4.2.6': + resolution: {integrity: sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==} engines: {node: '>=18.0.0'} - '@smithy/fetch-http-handler@5.3.6': - resolution: {integrity: sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==} + '@smithy/fetch-http-handler@5.3.7': + resolution: {integrity: sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==} engines: {node: '>=18.0.0'} - '@smithy/hash-node@4.2.5': - resolution: {integrity: sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==} + '@smithy/hash-node@4.2.6': + resolution: {integrity: sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==} engines: {node: '>=18.0.0'} - '@smithy/invalid-dependency@4.2.5': - resolution: {integrity: sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==} + '@smithy/invalid-dependency@4.2.6': + resolution: {integrity: sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==} engines: {node: '>=18.0.0'} '@smithy/is-array-buffer@2.2.0': @@ -4143,72 +4171,72 @@ packages: resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-content-length@4.2.5': - resolution: {integrity: sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==} + '@smithy/middleware-content-length@4.2.6': + resolution: {integrity: sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==} engines: {node: '>=18.0.0'} - '@smithy/middleware-endpoint@4.3.12': - resolution: {integrity: sha512-9pAX/H+VQPzNbouhDhkW723igBMLgrI8OtX+++M7iKJgg/zY/Ig3i1e6seCcx22FWhE6Q/S61BRdi2wXBORT+A==} + '@smithy/middleware-endpoint@4.4.0': + resolution: {integrity: sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==} engines: {node: '>=18.0.0'} - '@smithy/middleware-retry@4.4.12': - resolution: {integrity: sha512-S4kWNKFowYd0lID7/DBqWHOQxmxlsf0jBaos9chQZUWTVOjSW1Ogyh8/ib5tM+agFDJ/TCxuCTvrnlc+9cIBcQ==} + '@smithy/middleware-retry@4.4.16': + resolution: {integrity: sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==} engines: {node: '>=18.0.0'} - '@smithy/middleware-serde@4.2.6': - resolution: {integrity: sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==} + '@smithy/middleware-serde@4.2.7': + resolution: {integrity: sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==} engines: {node: '>=18.0.0'} - '@smithy/middleware-stack@4.2.5': - resolution: {integrity: sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==} + '@smithy/middleware-stack@4.2.6': + resolution: {integrity: sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==} engines: {node: '>=18.0.0'} - '@smithy/node-config-provider@4.3.5': - resolution: {integrity: sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==} + '@smithy/node-config-provider@4.3.6': + resolution: {integrity: sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==} engines: {node: '>=18.0.0'} - '@smithy/node-http-handler@4.4.5': - resolution: {integrity: sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==} + '@smithy/node-http-handler@4.4.6': + resolution: {integrity: sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==} engines: {node: '>=18.0.0'} - '@smithy/property-provider@4.2.5': - resolution: {integrity: sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==} + '@smithy/property-provider@4.2.6': + resolution: {integrity: sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==} engines: {node: '>=18.0.0'} - '@smithy/protocol-http@5.3.5': - resolution: {integrity: sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==} + '@smithy/protocol-http@5.3.6': + resolution: {integrity: sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==} engines: {node: '>=18.0.0'} - '@smithy/querystring-builder@4.2.5': - resolution: {integrity: sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==} + '@smithy/querystring-builder@4.2.6': + resolution: {integrity: sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==} engines: {node: '>=18.0.0'} - '@smithy/querystring-parser@4.2.5': - resolution: {integrity: sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==} + '@smithy/querystring-parser@4.2.6': + resolution: {integrity: sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==} engines: {node: '>=18.0.0'} - '@smithy/service-error-classification@4.2.5': - resolution: {integrity: sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==} + '@smithy/service-error-classification@4.2.6': + resolution: {integrity: sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==} engines: {node: '>=18.0.0'} - '@smithy/shared-ini-file-loader@4.4.0': - resolution: {integrity: sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==} + '@smithy/shared-ini-file-loader@4.4.1': + resolution: {integrity: sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==} engines: {node: '>=18.0.0'} - '@smithy/signature-v4@5.3.5': - resolution: {integrity: sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==} + '@smithy/signature-v4@5.3.6': + resolution: {integrity: sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==} engines: {node: '>=18.0.0'} - '@smithy/smithy-client@4.9.8': - resolution: {integrity: sha512-8xgq3LgKDEFoIrLWBho/oYKyWByw9/corz7vuh1upv7ZBm0ZMjGYBhbn6v643WoIqA9UTcx5A5htEp/YatUwMA==} + '@smithy/smithy-client@4.10.1': + resolution: {integrity: sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==} engines: {node: '>=18.0.0'} - '@smithy/types@4.9.0': - resolution: {integrity: sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==} + '@smithy/types@4.10.0': + resolution: {integrity: sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==} engines: {node: '>=18.0.0'} - '@smithy/url-parser@4.2.5': - resolution: {integrity: sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==} + '@smithy/url-parser@4.2.6': + resolution: {integrity: sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==} engines: {node: '>=18.0.0'} '@smithy/util-base64@4.3.0': @@ -4235,32 +4263,32 @@ packages: resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-browser@4.3.11': - resolution: {integrity: sha512-yHv+r6wSQXEXTPVCIQTNmXVWs7ekBTpMVErjqZoWkYN75HIFN5y9+/+sYOejfAuvxWGvgzgxbTHa/oz61YTbKw==} + '@smithy/util-defaults-mode-browser@4.3.15': + resolution: {integrity: sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==} engines: {node: '>=18.0.0'} - '@smithy/util-defaults-mode-node@4.2.14': - resolution: {integrity: sha512-ljZN3iRvaJUgulfvobIuG97q1iUuCMrvXAlkZ4msY+ZuVHQHDIqn7FKZCEj+bx8omz6kF5yQXms/xhzjIO5XiA==} + '@smithy/util-defaults-mode-node@4.2.18': + resolution: {integrity: sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==} engines: {node: '>=18.0.0'} - '@smithy/util-endpoints@3.2.5': - resolution: {integrity: sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==} + '@smithy/util-endpoints@3.2.6': + resolution: {integrity: sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==} engines: {node: '>=18.0.0'} '@smithy/util-hex-encoding@4.2.0': resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} engines: {node: '>=18.0.0'} - '@smithy/util-middleware@4.2.5': - resolution: {integrity: sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==} + '@smithy/util-middleware@4.2.6': + resolution: {integrity: sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==} engines: {node: '>=18.0.0'} - '@smithy/util-retry@4.2.5': - resolution: {integrity: sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==} + '@smithy/util-retry@4.2.6': + resolution: {integrity: sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==} engines: {node: '>=18.0.0'} - '@smithy/util-stream@4.5.6': - resolution: {integrity: sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==} + '@smithy/util-stream@4.5.7': + resolution: {integrity: sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==} engines: {node: '>=18.0.0'} '@smithy/util-uri-escape@4.2.0': @@ -4288,8 +4316,8 @@ packages: peerDependencies: socket.io-adapter: ^2.5.4 - '@standard-schema/spec@1.0.0': - resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} '@sveltejs/acorn-typescript@1.0.8': resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==} @@ -4308,8 +4336,8 @@ packages: svelte: ^5.0.0 vite: ^6.3.0 || >=7.0.0 - '@sveltejs/kit@2.49.0': - resolution: {integrity: sha512-oH8tXw7EZnie8FdOWYrF7Yn4IKrqTFHhXvl8YxXxbKwTMcD/5NNCryUSEXRk2ZR4ojnub0P8rNrsVGHXWqIDtA==} + '@sveltejs/kit@2.49.2': + resolution: {integrity: sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -4321,8 +4349,8 @@ packages: '@opentelemetry/api': optional: true - '@sveltejs/vite-plugin-svelte-inspector@5.0.0': - resolution: {integrity: sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==} + '@sveltejs/vite-plugin-svelte-inspector@5.0.1': + resolution: {integrity: sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==} engines: {node: ^20.19 || ^22.12 || >=24} peerDependencies: '@sveltejs/vite-plugin-svelte': ^6.0.0-next.0 @@ -4414,68 +4442,68 @@ packages: resolution: {integrity: sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==} engines: {node: '>=14'} - '@swc/core-darwin-arm64@1.15.3': - resolution: {integrity: sha512-AXfeQn0CvcQ4cndlIshETx6jrAM45oeUrK8YeEY6oUZU/qzz0Id0CyvlEywxkWVC81Ajpd8TQQ1fW5yx6zQWkQ==} + '@swc/core-darwin-arm64@1.15.5': + resolution: {integrity: sha512-RvdpUcXrIz12yONzOdQrJbEnq23cOc2IHOU1eB8kPxPNNInlm4YTzZEA3zf3PusNpZZLxwArPVLCg0QsFQoTYw==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] - '@swc/core-darwin-x64@1.15.3': - resolution: {integrity: sha512-p68OeCz1ui+MZYG4wmfJGvcsAcFYb6Sl25H9TxWl+GkBgmNimIiRdnypK9nBGlqMZAcxngNPtnG3kEMNnvoJ2A==} + '@swc/core-darwin-x64@1.15.5': + resolution: {integrity: sha512-ufJnz3UAff/8G5OfqZZc5cTQfGtXyXVLTB8TGT0xjkvEbfFg8jZUMDBnZT/Cn0k214JhMjiLCNl0A8aY/OKsYQ==} engines: {node: '>=10'} cpu: [x64] os: [darwin] - '@swc/core-linux-arm-gnueabihf@1.15.3': - resolution: {integrity: sha512-Nuj5iF4JteFgwrai97mUX+xUOl+rQRHqTvnvHMATL/l9xE6/TJfPBpd3hk/PVpClMXG3Uvk1MxUFOEzM1JrMYg==} + '@swc/core-linux-arm-gnueabihf@1.15.5': + resolution: {integrity: sha512-Yqu92wIT0FZKLDWes+69kBykX97hc8KmnyFwNZGXJlbKUGIE0hAIhbuBbcY64FGSwey4aDWsZ7Ojk89KUu9Kzw==} engines: {node: '>=10'} cpu: [arm] os: [linux] - '@swc/core-linux-arm64-gnu@1.15.3': - resolution: {integrity: sha512-2Nc/s8jE6mW2EjXWxO/lyQuLKShcmTrym2LRf5Ayp3ICEMX6HwFqB1EzDhwoMa2DcUgmnZIalesq2lG3krrUNw==} + '@swc/core-linux-arm64-gnu@1.15.5': + resolution: {integrity: sha512-3gR3b5V1abe/K1GpD0vVyZgqgV+ykuB5QNecDYzVroX4QuN+amCzQaNSsVM8Aj6DbShQCBTh3hGHd2f3vZ8gCw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.15.3': - resolution: {integrity: sha512-j4SJniZ/qaZ5g8op+p1G9K1z22s/EYGg1UXIb3+Cg4nsxEpF5uSIGEE4mHUfA70L0BR9wKT2QF/zv3vkhfpX4g==} + '@swc/core-linux-arm64-musl@1.15.5': + resolution: {integrity: sha512-Of+wmVh5h47tTpN9ghHVjfL0CJrgn99XmaJjmzWFW7agPdVY6gTDgkk6zQ6q4hcDQ7hXb0BGw6YFpuanBzNPow==} engines: {node: '>=10'} cpu: [arm64] os: [linux] - '@swc/core-linux-x64-gnu@1.15.3': - resolution: {integrity: sha512-aKttAZnz8YB1VJwPQZtyU8Uk0BfMP63iDMkvjhJzRZVgySmqt/apWSdnoIcZlUoGheBrcqbMC17GGUmur7OT5A==} + '@swc/core-linux-x64-gnu@1.15.5': + resolution: {integrity: sha512-98kuPS0lZVgjmc/2uTm39r1/OfwKM0PM13ZllOAWi5avJVjRd/j1xA9rKeUzHDWt+ocH9mTCQsAT1jjKSq45bg==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.15.3': - resolution: {integrity: sha512-oe8FctPu1gnUsdtGJRO2rvOUIkkIIaHqsO9xxN0bTR7dFTlPTGi2Fhk1tnvXeyAvCPxLIcwD8phzKg6wLv9yug==} + '@swc/core-linux-x64-musl@1.15.5': + resolution: {integrity: sha512-Rk+OtNQP3W/dZExL74LlaakXAQn6/vbrgatmjFqJPO4RZkq+nLo5g7eDUVjyojuERh7R2yhqNvZ/ZZQe8JQqqA==} engines: {node: '>=10'} cpu: [x64] os: [linux] - '@swc/core-win32-arm64-msvc@1.15.3': - resolution: {integrity: sha512-L9AjzP2ZQ/Xh58e0lTRMLvEDrcJpR7GwZqAtIeNLcTK7JVE+QineSyHp0kLkO1rttCHyCy0U74kDTj0dRz6raA==} + '@swc/core-win32-arm64-msvc@1.15.5': + resolution: {integrity: sha512-e3RTdJ769+PrN25iCAlxmsljEVu6iIWS7sE21zmlSiipftBQvSAOWuCDv2A8cH9lm5pSbZtwk8AUpIYCNsj2oQ==} engines: {node: '>=10'} cpu: [arm64] os: [win32] - '@swc/core-win32-ia32-msvc@1.15.3': - resolution: {integrity: sha512-B8UtogMzErUPDWUoKONSVBdsgKYd58rRyv2sHJWKOIMCHfZ22FVXICR4O/VwIYtlnZ7ahERcjayBHDlBZpR0aw==} + '@swc/core-win32-ia32-msvc@1.15.5': + resolution: {integrity: sha512-NmOdl6kyAw6zMz36zCdopTgaK2tcLA53NhUsTRopBc/796Fp87XdsslRHglybQ1HyXIGOQOKv2Y14IUbeci4BA==} engines: {node: '>=10'} cpu: [ia32] os: [win32] - '@swc/core-win32-x64-msvc@1.15.3': - resolution: {integrity: sha512-SpZKMR9QBTecHeqpzJdYEfgw30Oo8b/Xl6rjSzBt1g0ZsXyy60KLXrp6IagQyfTYqNYE/caDvwtF2FPn7pomog==} + '@swc/core-win32-x64-msvc@1.15.5': + resolution: {integrity: sha512-EPXJRf0A8eOi8woXf/qgVIWRl9yeSl0oN1ykGZNCGI7oElsfxUobJFmpJFJoVqKFfd1l0c+GPmWsN2xavTFkNw==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.15.3': - resolution: {integrity: sha512-Qd8eBPkUFL4eAONgGjycZXj1jFCBW8Fd+xF0PzdTlBCWQIV1xnUT7B93wUANtW3KGjl3TRcOyxwSx/u/jyKw/Q==} + '@swc/core@1.15.5': + resolution: {integrity: sha512-VRy+AEO0zqUkwV9uOgqXtdI5tNj3y3BZI+9u28fHNjNVTtWYVNIq3uYhoGgdBOv7gdzXlqfHKuxH5a9IFAvopQ==} engines: {node: '>=10'} peerDependencies: '@swc/helpers': '>=0.5.17' @@ -4496,65 +4524,65 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} - '@tailwindcss/node@4.1.17': - resolution: {integrity: sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg==} + '@tailwindcss/node@4.1.18': + resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==} - '@tailwindcss/oxide-android-arm64@4.1.17': - resolution: {integrity: sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ==} + '@tailwindcss/oxide-android-arm64@4.1.18': + resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.1.17': - resolution: {integrity: sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg==} + '@tailwindcss/oxide-darwin-arm64@4.1.18': + resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.1.17': - resolution: {integrity: sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog==} + '@tailwindcss/oxide-darwin-x64@4.1.18': + resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.1.17': - resolution: {integrity: sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g==} + '@tailwindcss/oxide-freebsd-x64@4.1.18': + resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17': - resolution: {integrity: sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': + resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.1.17': - resolution: {integrity: sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ==} + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': + resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.1.17': - resolution: {integrity: sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg==} + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': + resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.1.17': - resolution: {integrity: sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ==} + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': + resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.1.17': - resolution: {integrity: sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ==} + '@tailwindcss/oxide-linux-x64-musl@4.1.18': + resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-wasm32-wasi@4.1.17': - resolution: {integrity: sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg==} + '@tailwindcss/oxide-wasm32-wasi@4.1.18': + resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} engines: {node: '>=14.0.0'} cpu: [wasm32] bundledDependencies: @@ -4565,24 +4593,24 @@ packages: - '@emnapi/wasi-threads' - tslib - '@tailwindcss/oxide-win32-arm64-msvc@4.1.17': - resolution: {integrity: sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A==} + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': + resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.1.17': - resolution: {integrity: sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw==} + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': + resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.1.17': - resolution: {integrity: sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA==} + '@tailwindcss/oxide@4.1.18': + resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==} engines: {node: '>= 10'} - '@tailwindcss/vite@4.1.17': - resolution: {integrity: sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA==} + '@tailwindcss/vite@4.1.18': + resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==} peerDependencies: vite: ^5.2.0 || ^6 || ^7 @@ -4628,14 +4656,14 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} - '@turf/boolean-point-in-polygon@7.2.0': - resolution: {integrity: sha512-lvEOjxeXIp+wPXgl9kJA97dqzMfNexjqHou+XHVcfxQgolctoJiRYmcVCWGpiZ9CBf/CJha1KmD1qQoRIsjLaA==} + '@turf/boolean-point-in-polygon@7.3.1': + resolution: {integrity: sha512-BUPW63vE43LctwkgannjmEFTX1KFR/18SS7WzFahJWK1ZoP0s1jrfxGX+pi0BH/3Dd9mA71hkGKDDnj1Ndcz0g==} - '@turf/helpers@7.2.0': - resolution: {integrity: sha512-cXo7bKNZoa7aC7ydLmUR02oB3IgDe7MxiPuRz3cCtYQHn+BJ6h1tihmamYDWWUlPHgSNF0i3ATc4WmDECZafKw==} + '@turf/helpers@7.3.1': + resolution: {integrity: sha512-zkL34JVhi5XhsuMEO0MUTIIFEJ8yiW1InMu4hu/oRqamlY4mMoZql0viEmH6Dafh/p+zOl8OYvMJ3Vm3rFshgg==} - '@turf/invariant@7.2.0': - resolution: {integrity: sha512-kV4u8e7Gkpq+kPbAKNC21CmyrXzlbBgFjO1PhrHPgEdNqXqDawoZ3i6ivE3ULJj2rSesCjduUaC/wyvH/sNr2Q==} + '@turf/invariant@7.3.1': + resolution: {integrity: sha512-IdZJfDjIDCLH+Gu2yLFoSM7H23sdetIo5t4ET1/25X8gi3GE2XSqbZwaGjuZgNh02nisBewLqNiJs2bo+hrqZA==} '@types/accepts@1.3.7': resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} @@ -4664,11 +4692,11 @@ packages: '@types/byte-size@8.1.2': resolution: {integrity: sha512-jGyVzYu6avI8yuqQCNTZd65tzI8HZrLjKX9sdMqZrGWVlNChu0rf6p368oVEDCYJe5BMx2Ov04tD1wqtgTwGSA==} - '@types/chai@5.2.2': - resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - '@types/chrome@0.0.328': - resolution: {integrity: sha512-Mv/TQMFMpGBTqWQOQsYcAd3qDncH/Q+Dz7iJVjkwb98uLeM8xZVEYH3VR5Jh+su9IBksbumJeazakK8WqBAgFA==} + '@types/chrome@0.1.32': + resolution: {integrity: sha512-n5Cqlh7zyAqRLQWLXkeV5K/1BgDZdVcO/dJSTa8x+7w+sx7m73UrDmduAptg4KorMtyTW2TNnPu8RGeaDMKNGg==} '@types/chromecast-caf-sender@1.0.11': resolution: {integrity: sha512-Pv3xvNYtxD/cTM/tKfuZRlLasvpxAm+CFni0GJd6Cp8XgiZS9g9tMZkR1uymsi5fIFv057SZKKAWVFFgy7fJtw==} @@ -4699,8 +4727,8 @@ packages: '@types/cookiejar@2.1.5': resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} - '@types/cookies@0.9.1': - resolution: {integrity: sha512-E/DPgzifH4sM1UMadJMWd6mO2jOd4g1Ejwzx8/uRCDpJis1IrlyQEcGAYEomtAqRYmD5ORbNXMeI9U0RiVGZbg==} + '@types/cookies@0.9.2': + resolution: {integrity: sha512-1AvkDdZM2dbyFybL4fxpuNCaWyv//0AwsuUk2DWeXyM1/5ZKm6W3z6mQi24RZ4l2ucY+bkSHzbDVpySqPGuV8A==} '@types/cors@2.8.19': resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} @@ -4741,8 +4769,8 @@ packages: '@types/express@4.17.25': resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - '@types/express@5.0.5': - resolution: {integrity: sha512-LuIQOcb6UmnF7C1PCFmEU1u2hmiHL43fgFQX67sN3H4Z+0Yk0Neo++mFsBjhOAuLzvlQeqAAkeDOZrJs9rzumQ==} + '@types/express@5.0.6': + resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==} '@types/filesystem@0.0.36': resolution: {integrity: sha512-vPDXOZuannb9FZdxgHnqSwAG/jvdGM8Wq+6N4D/d80z+D4HWH+bItqsZaVRQykAn6WEVeEkLm2oQigyHtgb0RA==} @@ -4789,8 +4817,8 @@ packages: '@types/http-proxy@1.17.17': resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} - '@types/inquirer@8.2.11': - resolution: {integrity: sha512-15UboTvxb9SOaPG7CcXZ9dkv8lNqfiAwuh/5WxJDLjmElBt9tbx1/FDsEnJddUBKvN4mlPKvr8FyO1rAmBanzg==} + '@types/inquirer@8.2.12': + resolution: {integrity: sha512-YxURZF2ZsSjU5TAe06tW0M3sL4UI9AMPA6dd8I72uOtppzNafcY38xkYgCZ/vsVOAyNdzHmvtTpLWilOrbP0dQ==} '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -4816,11 +4844,11 @@ packages: '@types/keygrip@1.0.6': resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} - '@types/koa-compose@3.2.8': - resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} + '@types/koa-compose@3.2.9': + resolution: {integrity: sha512-BroAZ9FTvPiCy0Pi8tjD1OfJ7bgU1gQf0eR6e1Vm+JJATy9eKOG3hQMFtMciMawiSOVnLMdmUOC46s7HBhSTsA==} - '@types/koa@3.0.0': - resolution: {integrity: sha512-MOcVYdVYmkSutVHZZPh8j3+dAjLyR5Tl59CN0eKgpkE1h/LBSmPAsQQuWs+bKu7WtGNn+hKfJH9Gzml+PulmDg==} + '@types/koa@3.0.1': + resolution: {integrity: sha512-VkB6WJUQSe0zBpR+Q7/YIUESGp5wPHcaXr0xueU5W0EOUWtlSbblsl+Kl31lyRQ63nIILh0e/7gXjQ09JXJIHw==} '@types/leaflet@1.9.21': resolution: {integrity: sha512-TbAd9DaPGSnzp6QvtYngntMZgcRk+igFELwR2N99XZn7RXUdKgsXMR+28bUO0rPsWp8MIu/f47luLIQuSLYv/w==} @@ -4867,11 +4895,11 @@ packages: '@types/node@18.19.130': resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} - '@types/node@20.19.24': - resolution: {integrity: sha512-FE5u0ezmi6y9OZEzlJfg37mqqf6ZDSF2V/NLjUyGrR9uTZ7Sb9F7bLNZ03S4XVUNRWGA7Ck4c1kK+YnuWjl+DA==} + '@types/node@20.19.27': + resolution: {integrity: sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==} - '@types/node@24.10.1': - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@24.10.4': + resolution: {integrity: sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==} '@types/nodemailer@7.0.4': resolution: {integrity: sha512-ee8fxWqOchH+Hv6MDDNNy028kwvVnLplrStm4Zf/3uHWw5zzo8FoYYeffpJtGs2wWysEumMH0ZIdMGMY1eMAow==} @@ -4888,6 +4916,9 @@ packages: '@types/pg@8.15.6': resolution: {integrity: sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ==} + '@types/pg@8.16.0': + resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==} + '@types/picomatch@4.0.2': resolution: {integrity: sha512-qHHxQ+P9PysNEGbALT8f8YOSHW0KJu6l2xU8DYY0fu/EmGxXdVnuTLvFUvBgPJMSqXq29SYHveejeAha+4AYgA==} @@ -4945,6 +4976,9 @@ packages: '@types/serve-static@1.15.10': resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/serve-static@2.2.0': + resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==} + '@types/sockjs@0.3.36': resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} @@ -4990,73 +5024,73 @@ packages: '@types/yargs-parser@21.0.3': resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - '@types/yargs@17.0.34': - resolution: {integrity: sha512-KExbHVa92aJpw9WDQvzBaGVE2/Pz+pLZQloT2hjL8IqsZnV62rlPOYvNnLmf/L2dyllfVUOVBj64M0z/46eR2A==} + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - '@typescript-eslint/eslint-plugin@8.48.0': - resolution: {integrity: sha512-XxXP5tL1txl13YFtrECECQYeZjBZad4fyd3cFV4a19LkAY/bIp9fev3US4S5fDVV2JaYFiKAZ/GRTOLer+mbyQ==} + '@typescript-eslint/eslint-plugin@8.50.0': + resolution: {integrity: sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.48.0 + '@typescript-eslint/parser': ^8.50.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.48.0': - resolution: {integrity: sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==} + '@typescript-eslint/parser@8.50.0': + resolution: {integrity: sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.48.0': - resolution: {integrity: sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==} + '@typescript-eslint/project-service@8.50.0': + resolution: {integrity: sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.48.0': - resolution: {integrity: sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==} + '@typescript-eslint/scope-manager@8.50.0': + resolution: {integrity: sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.48.0': - resolution: {integrity: sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==} + '@typescript-eslint/tsconfig-utils@8.50.0': + resolution: {integrity: sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.48.0': - resolution: {integrity: sha512-zbeVaVqeXhhab6QNEKfK96Xyc7UQuoFWERhEnj3mLVnUWrQnv15cJNseUni7f3g557gm0e46LZ6IJ4NJVOgOpw==} + '@typescript-eslint/type-utils@8.50.0': + resolution: {integrity: sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/types@8.48.0': - resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==} + '@typescript-eslint/types@8.50.0': + resolution: {integrity: sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.48.0': - resolution: {integrity: sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==} + '@typescript-eslint/typescript-estree@8.50.0': + resolution: {integrity: sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.48.0': - resolution: {integrity: sha512-yTJO1XuGxCsSfIVt1+1UrLHtue8xz16V8apzPYI06W0HbEbEWHxHXgZaAgavIkoh+GeV6hKKd5jm0sS6OYxWXQ==} + '@typescript-eslint/utils@8.50.0': + resolution: {integrity: sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/visitor-keys@8.48.0': - resolution: {integrity: sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==} + '@typescript-eslint/visitor-keys@8.50.0': + resolution: {integrity: sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - '@vercel/oidc@3.0.3': - resolution: {integrity: sha512-yNEQvPcVrK9sIe637+I0jD6leluPxzwJKx/Haw6F4H77CdDsszUn5V3o96LPziXkSNE2B83+Z3mjqGKBK/R6Gg==} + '@vercel/oidc@3.0.5': + resolution: {integrity: sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw==} engines: {node: '>= 20'} '@vitest/coverage-v8@3.2.4': @@ -5223,8 +5257,8 @@ packages: resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} engines: {node: '>=8'} - ai@5.0.82: - resolution: {integrity: sha512-wmZZfsU40qB77umrcj3YzMSk6cUP5gxLXZDPfiSQLBLegTVXPUdSJC603tR7JB5JkhBDzN5VLaliuRKQGKpUXg==} + ai@5.0.113: + resolution: {integrity: sha512-26vivpSO/mzZj0k1Si2IpsFspp26ttQICHRySQiMrtWcRd5mnJMX2a8sG28vmZ38C+JUn1cWmfZrsLMxkSMw9g==} engines: {node: '>=18'} peerDependencies: zod: ^3.25.76 || ^4.1.8 @@ -5261,13 +5295,13 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - algoliasearch-helper@3.26.0: - resolution: {integrity: sha512-Rv2x3GXleQ3ygwhkhJubhhYGsICmShLAiqtUuJTUkr9uOCOXyF2E71LVT4XDnVffbknv8XgScP4U0Oxtgm+hIw==} + algoliasearch-helper@3.26.1: + resolution: {integrity: sha512-CAlCxm4fYBXtvc5MamDzP6Svu8rW4z9me4DCBY1rQ2UDJ0u0flWmusQ8M3nOExZsLLRcUwUPoRAPMrhzOG3erw==} peerDependencies: algoliasearch: '>= 3.1 < 6' - algoliasearch@5.41.0: - resolution: {integrity: sha512-9E4b3rJmYbBkn7e3aAPt1as+VVnRhsR4qwRRgOzpeyz4PAOuwKh0HI4AN6mTrqK0S0M9fCCSTOUnuJ8gPY/tvA==} + algoliasearch@5.46.0: + resolution: {integrity: sha512-7ML6fa2K93FIfifG3GMWhDEwT5qQzPTmoHKCTvhzGEwdbQ4n0yYUWZlLYT75WllTGJCJtNUI0C1ybN4BCegqvg==} engines: {node: '>= 14.0.0'} ansi-align@3.0.1: @@ -5320,8 +5354,8 @@ packages: append-field@1.0.0: resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==} - aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + aproba@2.1.0: + resolution: {integrity: sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==} archiver-utils@5.0.2: resolution: {integrity: sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==} @@ -5378,8 +5412,8 @@ packages: ast-metadata-inferer@0.8.1: resolution: {integrity: sha512-ht3Dm6Zr7SXv6t1Ra6gFo0+kLDglHGrEbYihTkcycrbHw7WCcuhBzPlJYHEsIpycaUwzsJHje+vUcxXUX4ztTA==} - ast-v8-to-istanbul@0.3.3: - resolution: {integrity: sha512-MuXMrSLVVoA6sYN/6Hke18vMzrT4TZNbZIj/hvh0fnYFpO+/kFXcLIaiPwXXWaQUPg4yJD8fj+lfJ7/1EBconw==} + ast-v8-to-istanbul@0.3.8: + resolution: {integrity: sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ==} astring@1.9.0: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} @@ -5403,8 +5437,8 @@ packages: autocomplete.js@0.37.1: resolution: {integrity: sha512-PgSe9fHYhZEsm/9jggbjtVsGXJkPLvd+9mC7gZJ662vVL5CRWEtm/mIrrzCx0MrNxHVwxD5d00UOn6NsmL2LUQ==} - autoprefixer@10.4.22: - resolution: {integrity: sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==} + autoprefixer@10.4.23: + resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==} engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: @@ -5414,8 +5448,13 @@ packages: resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} engines: {node: '>= 0.4'} - b4a@1.6.7: - resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} + b4a@1.7.3: + resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} + peerDependencies: + react-native-b4a: '*' + peerDependenciesMeta: + react-native-b4a: + optional: true babel-loader@9.2.1: resolution: {integrity: sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==} @@ -5496,12 +5535,12 @@ packages: resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} engines: {node: ^4.5.0 || >= 5.9} - baseline-browser-mapping@2.8.31: - resolution: {integrity: sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==} + baseline-browser-mapping@2.9.7: + resolution: {integrity: sha512-k9xFKplee6KIio3IDbwj+uaCLpqzOwakOgmqzPezM0sFJlFKcg30vk2wOiAJtkTSfx0SSQDSe8q+mWA/fSH5Zg==} hasBin: true - batch-cluster@15.0.1: - resolution: {integrity: sha512-eUmh0ld1AUPKTEmdzwGF9QTSexXAyt9rA1F5zDfW1wUi3okA3Tal4NLdCeFI6aiKpBenQhR6NmK9bW9tBHTGPQ==} + batch-cluster@16.0.0: + resolution: {integrity: sha512-+T7Ho09ikx/kP4P8M+GEnpuePzRQa4gTUhtPIu6ApFC8+0GY0sri1y1PuB+yfXlQWl5DkHC/e58z3U6g0qCz/A==} engines: {node: '>=20'} batch@0.6.1: @@ -5548,8 +5587,8 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - bowser@2.13.0: - resolution: {integrity: sha512-yHAbSRuT6LTeKi6k2aS40csueHqgAsFEgmrOsfRyFpJnFv5O2hl9FYmWEUZ97gZ/dG17U4IQQcTx4YAFYPuWRQ==} + bowser@2.13.1: + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} boxen@6.2.1: resolution: {integrity: sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==} @@ -5569,8 +5608,8 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - browserslist@4.28.0: - resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -5598,8 +5637,8 @@ packages: resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} engines: {node: '>=18.20'} - bullmq@5.65.0: - resolution: {integrity: sha512-fyOcyf2ad4zrNmE18vdF/ie7DrW0TwhLt5e0DkqDxbRpDNiUdYqgp2QZJW2ntnUN08T2mDMC4deUUhF2UOAmeQ==} + bullmq@5.66.0: + resolution: {integrity: sha512-LSe8yEiVTllOOq97Q0C/EhczKS5Yd0AUJleGJCIh0cyJE5nWUqEpGC/uZQuuAYniBSoMT8LqwrxE7N5MZVrLoQ==} bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} @@ -5684,8 +5723,8 @@ packages: caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} - caniuse-lite@1.0.30001757: - resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==} + caniuse-lite@1.0.30001760: + resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==} canvas@2.11.2: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} @@ -5694,9 +5733,9 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - chai@5.2.0: - resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} - engines: {node: '>=12'} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -6030,14 +6069,14 @@ packages: peerDependencies: webpack: ^5.1.0 - core-js-compat@3.46.0: - resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} + core-js-compat@3.47.0: + resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} - core-js-pure@3.46.0: - resolution: {integrity: sha512-NMCW30bHNofuhwLhYPt66OLOKTMbOhgTTatKVbaQC3KRHpTCiRIBYvtshr+NBYSnBxwAFhjW/RfJ0XbIjS16rw==} + core-js-pure@3.47.0: + resolution: {integrity: sha512-BcxeDbzUrRnXGYIVAGFtcGQVNpFcUhVjr6W7F8XktvQW2iJP9e66GP6xdKotCRFlrxBvNIBrhwKteRXqMV86Nw==} - core-js@3.46.0: - resolution: {integrity: sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==} + core-js@3.47.0: + resolution: {integrity: sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -6072,8 +6111,8 @@ packages: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} - cron@4.3.3: - resolution: {integrity: sha512-B/CJj5yL3sjtlun6RtYHvoSB26EmQ2NUmhq9ZiJSyKIM4K/fqfh9aelDFlIayD2YMeFZqWLi9hHV+c+pq2Djkw==} + cron@4.3.5: + resolution: {integrity: sha512-hKPP7fq1+OfyCqoePkKfVq7tNAdFwiQORr4lZUHwrf0tebC65fYEeWgOrXOL6prn1/fegGOdTfrM6e34PJfksg==} engines: {node: '>=18.x'} cross-spawn@7.0.6: @@ -6172,8 +6211,8 @@ packages: csscolorparser@1.0.3: resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==} - cssdb@8.4.2: - resolution: {integrity: sha512-PzjkRkRUS+IHDJohtxkIczlxPPZqRo0nXplsYXOMBRPjcVRjj1W4DfvRgshUYTVuUigU7ptVYkFJQ7abUB0nyg==} + cssdb@8.5.2: + resolution: {integrity: sha512-Pmoj9RmD8RIoIzA2EQWO4D4RMeDts0tgAH0VXdlNdxjuBGI3a9wMOIcUwaPNmD4r2qtIa06gqkIf7sECl+cBCg==} cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} @@ -6218,10 +6257,6 @@ packages: resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} engines: {node: '>=8'} - cssstyle@4.6.0: - resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} - engines: {node: '>=18'} - csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} @@ -6241,10 +6276,6 @@ packages: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} - data-urls@5.0.0: - resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} - engines: {node: '>=18'} - debounce@1.2.1: resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} @@ -6314,12 +6345,12 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - default-browser-id@5.0.0: - resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} engines: {node: '>=18'} - default-browser@5.2.1: - resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + default-browser@5.4.0: + resolution: {integrity: sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==} engines: {node: '>=18'} defaults@1.0.4: @@ -6387,8 +6418,8 @@ packages: engines: {node: '>= 4.0.0'} hasBin: true - devalue@5.5.0: - resolution: {integrity: sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==} + devalue@5.6.1: + resolution: {integrity: sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==} devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -6516,8 +6547,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.260: - resolution: {integrity: sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==} + electron-to-chromium@1.5.267: + resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -6538,10 +6569,6 @@ packages: emoticon@4.1.0: resolution: {integrity: sha512-VWZfnxqwNcc51hIy/sbOdEem6D+cVtpPzEEtVAFdaas30+1dgkyaOQ4sQ6Bp0tOMqWO1v+HQfYaoodOkdhK6SQ==} - encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -6563,8 +6590,8 @@ packages: resolution: {integrity: sha512-ZCkIjSYNDyGn0R6ewHDtXgns/Zre/NT6Agvq1/WobF7JXgFff4SeDroKiCO3fNJreU9YG429Sc81o4w5ok/W5g==} engines: {node: '>=10.2.0'} - enhanced-resolve@5.18.3: - resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} + enhanced-resolve@5.18.4: + resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} engines: {node: '>=10.13.0'} entities@2.2.0: @@ -6637,8 +6664,8 @@ packages: engines: {node: '>=18'} hasBin: true - esbuild@0.27.0: - resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + esbuild@0.27.1: + resolution: {integrity: sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA==} engines: {node: '>=18'} hasBin: true @@ -6696,8 +6723,8 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-svelte@3.13.0: - resolution: {integrity: sha512-2ohCCQJJTNbIpQCSDSTWj+FN0OVfPmSO03lmSNT7ytqMaWF6kpT86LdzDqtm4sh7TVPl/OEWJ/d7R87bXP2Vjg==} + eslint-plugin-svelte@3.13.1: + resolution: {integrity: sha512-Ng+kV/qGS8P/isbNYVE3sJORtubB+yLEcYICMkUWNaDTb0SwZni/JhAYXh/Dz/q2eThUwWY0VMPZ//KYD1n3eQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.1 || ^9.0.0 @@ -6728,8 +6755,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} + eslint@9.39.2: + resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -6758,8 +6785,8 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - esrap@2.2.0: - resolution: {integrity: sha512-WBmtxe7R9C5mvL4n2le8nMUe4mD5V9oiK2vJpQ9I3y20ENPUomPcphBXE8D1x/Bm84oN1V+lOfgXxtqmxTp3Xg==} + esrap@2.2.1: + resolution: {integrity: sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==} esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} @@ -6808,8 +6835,8 @@ packages: resolution: {integrity: sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==} engines: {node: '>=6.0.0'} - eta@4.0.1: - resolution: {integrity: sha512-0h0oBEsF6qAJU7eu9ztvJoTo8D2PAq/4FvXVIQA1fek3WOTe6KPsVJycekG1+g1N6mfpblkheoGwaUhMtnlH4A==} + eta@4.5.0: + resolution: {integrity: sha512-qifAYjuW5AM1eEEIsFnOwB+TGqu6ynU3OKj9WbUTOtUBHFPZqL03XUW34kbp3zm19Ald+U8dEyRXaVsUck+Y1g==} engines: {node: '>=20'} etag@1.8.1: @@ -6845,21 +6872,21 @@ packages: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} - exiftool-vendored.exe@13.42.0: - resolution: {integrity: sha512-6AFybe5IakduMWleuQBfep9OWGSVZSedt2uKL+LzufRsATp+beOF7tZyKtMztjb6VRH1GF/4F9EvBVam6zm70w==} + exiftool-vendored.exe@13.44.0: + resolution: {integrity: sha512-PzQrrz9k4YzxtcX1r/hEy+xzj6MKXXiEBCU+FhYlipr4fuKKeXgspB7kliPSfSSFAChYoSH294zd23ZUXgB4TQ==} os: [win32] - exiftool-vendored.pl@13.42.0: - resolution: {integrity: sha512-EF5IdxQNIJIvZjHf4bG4jnwAHVVSLkYZToo2q+Mm89kSuppKfRvHz/lngIxN0JALE8rFdC4zt6NWY/PKqRdCcg==} + exiftool-vendored.pl@13.44.0: + resolution: {integrity: sha512-KPqyZK5guU/HKJ4x7OdxC0bqwClz34AtQYeirvvGFBjvfpG6Ewt+Kx9TEd/JbvJyLgMS5k5GHvkH5R5iAL+Arg==} os: ['!win32'] hasBin: true - exiftool-vendored@33.5.0: - resolution: {integrity: sha512-7cCh6izwdmC5ZaCxpHFehnExIr2Yp7CJuxHg4WFiGcm81yyxXLtvSE+85ep9VsNwhlOtSpk+XxiqrlddjY5lAw==} + exiftool-vendored@34.1.0: + resolution: {integrity: sha512-piPUu8oaBT0JQcR0gH/ZLjnTrHu51lMs+GjAQPrtVyvt8bfB1vzTWYbw+9jN4qyO8HwCweJuj7xivmWS0/fa/A==} engines: {node: '>=20.0.0'} - expect-type@1.2.1: - resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} exponential-backoff@3.1.3: @@ -6873,12 +6900,12 @@ packages: resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==} engines: {node: '>= 18'} - express@5.2.0: - resolution: {integrity: sha512-XdpJDLxfztVY59X0zPI6sibRiGcxhTPXRD3IhJmjKf2jwMvkRGV1j7loB8U+heeamoU3XvihAaGRTR4aXXUN3A==} + express@5.2.1: + resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} - exsolve@1.0.7: - resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} + exsolve@1.0.8: + resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} ext@1.7.0: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} @@ -6890,8 +6917,8 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - fabric@6.9.0: - resolution: {integrity: sha512-ILIbG4Us/41Z4rU8/gveN4Hb7NvgBorqV9xj+9Dl7YsXiyUPXdxV8+q5OvaNghmYzQoK1Am3m0wTvmovOxrJAg==} + fabric@6.9.1: + resolution: {integrity: sha512-TqG08Xbt4rtlPsXgCjSUcZz/RsyEP57Qo21nCVRkw7zz9nR0co4SLkL9Q/zQh3tC1Yxap6M5jKFHUKV6SgPovg==} engines: {node: '>=16.20.0'} factory.ts@1.4.2: @@ -7201,8 +7228,8 @@ packages: resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} hasBin: true - glob@11.0.3: - resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} engines: {node: 20 || >=22} hasBin: true @@ -7258,9 +7285,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - gray-matter@4.0.3: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} @@ -7280,8 +7304,8 @@ packages: engines: {node: '>=0.4.7'} hasBin: true - happy-dom@20.0.10: - resolution: {integrity: sha512-6umCCHcjQrhP5oXhrHQQvLB0bwb1UzHAHdsXy+FjtKoYjUhmNZsQL8NivwM1vDvNEChJabVrUYxUnp/ZdYmy2g==} + happy-dom@20.0.11: + resolution: {integrity: sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==} engines: {node: '>=20.0.0'} has-flag@4.0.0: @@ -7340,8 +7364,8 @@ packages: hast-util-to-jsx-runtime@2.3.6: resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} - hast-util-to-parse5@8.0.0: - resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + hast-util-to-parse5@8.0.1: + resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} hast-util-to-string@1.0.4: resolution: {integrity: sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w==} @@ -7386,10 +7410,6 @@ packages: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} - html-encoding-sniffer@4.0.0: - resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} - engines: {node: '>=18'} - html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -7414,8 +7434,8 @@ packages: html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - html-webpack-plugin@5.6.4: - resolution: {integrity: sha512-V/PZeWsqhfpE27nKeX9EO2sbR+D17A+tLf6qU+ht66jdUsN0QLKJN27Z+1+gHrVMKgndBahes0PU6rRihDgHTw==} + html-webpack-plugin@5.6.5: + resolution: {integrity: sha512-4xynFbKNNk+WlzXeQQ+6YYsH2g7mpfPszQZUi3ovKlj+pDmngQ7vRXjrrmGROabmKwyQkcgcX5hqfOwHbFmK5g==} engines: {node: '>=10.13.0'} peerDependencies: '@rspack/core': 0.x || 1.x @@ -7450,10 +7470,6 @@ packages: resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} engines: {node: '>= 0.6'} - http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - http-errors@2.0.1: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} @@ -7514,8 +7530,8 @@ packages: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - iconv-lite@0.7.0: - resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==} + iconv-lite@0.7.1: + resolution: {integrity: sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==} engines: {node: '>=0.10.0'} icss-utils@5.1.0: @@ -7591,9 +7607,6 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} - inline-style-parser@0.2.4: - resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} - inline-style-parser@0.2.7: resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} @@ -7615,16 +7628,16 @@ packages: resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==} engines: {node: '>=12.22.0'} - ip-address@10.0.1: - resolution: {integrity: sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==} + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} engines: {node: '>= 12'} ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - ipaddr.js@2.2.0: - resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + ipaddr.js@2.3.0: + resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} engines: {node: '>= 10'} is-alphabetical@2.0.1: @@ -7828,8 +7841,8 @@ packages: resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} - istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} iterare@1.2.1: @@ -7873,8 +7886,8 @@ packages: jose@5.10.0: resolution: {integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==} - jose@6.1.0: - resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==} + jose@6.1.3: + resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -7899,15 +7912,6 @@ packages: canvas: optional: true - jsdom@26.1.0: - resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} - engines: {node: '>=18'} - peerDependencies: - canvas: 2.11.2 - peerDependenciesMeta: - canvas: - optional: true - jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -7945,8 +7949,8 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - jsonwebtoken@9.0.2: - resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + jsonwebtoken@9.0.3: + resolution: {integrity: sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==} engines: {node: '>=12', npm: '>=6'} just-compare@2.3.0: @@ -7955,11 +7959,11 @@ packages: justified-layout@4.1.0: resolution: {integrity: sha512-M5FimNMXgiOYerVRGsXZ2YK9YNCaTtwtYp7Hb2308U1Q9TXXHx5G0p08mcVR5O53qf8bWY4NJcPBxE6zuayXSg==} - jwa@1.4.2: - resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} + jwa@2.0.1: + resolution: {integrity: sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==} - jws@3.2.2: - resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + jws@4.0.1: + resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==} kdbush@3.0.0: resolution: {integrity: sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==} @@ -8218,8 +8222,8 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true - loupe@3.1.4: - resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -8280,8 +8284,8 @@ packages: resolution: {integrity: sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==} engines: {node: '>=6.4.0'} - maplibre-gl@5.13.0: - resolution: {integrity: sha512-UsIVP34rZdM4TjrjhwBAhbC3HT7AzFx9p/draiAPlLr8/THozZF6WmJnZ9ck4q94uO55z7P7zoGCh+AZVoagsQ==} + maplibre-gl@5.14.0: + resolution: {integrity: sha512-O2ok6N/bQ9NA9nJ22r/PRQQYkUe9JwfDMjBPkQ+8OwsVH4TpA5skIAM2wc0k+rni5lVbAVONVyBvgi1rF2vEPA==} engines: {node: '>=16.14.0', npm: '>=8.1.0'} mark.js@8.11.1: @@ -8302,8 +8306,8 @@ packages: engines: {node: '>= 18'} hasBin: true - marked@16.4.1: - resolution: {integrity: sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==} + marked@16.4.2: + resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==} engines: {node: '>= 20'} hasBin: true @@ -8356,8 +8360,8 @@ packages: mdast-util-phrasing@4.1.0: resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - mdast-util-to-hast@13.2.0: - resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + mdast-util-to-hast@13.2.1: + resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} mdast-util-to-markdown@2.1.2: resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} @@ -8383,8 +8387,8 @@ packages: resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} engines: {node: '>= 4.0.0'} - memfs@4.50.0: - resolution: {integrity: sha512-N0LUYQMUA1yS5tJKmMtU9yprPm6ZIg24yr/OVv/7t6q0kKDIho4cBbXRi1XKttUmNYDYgF/q45qrKE/UhGO0CA==} + memfs@4.51.1: + resolution: {integrity: sha512-Eyt3XrufitN2ZL9c/uIRMyDwXanLI88h/L3MoWqNY747ha3dMR9dWqp8cRT5ntjZ0U1TNuq4U91ZXK0sMBjYOQ==} memoizee@0.4.17: resolution: {integrity: sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA==} @@ -8731,8 +8735,8 @@ packages: mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nan@2.23.1: - resolution: {integrity: sha512-r7bBUGKzlqk8oPBDYxt6Z0aEdF1G1rwlMcLk8LCOMbOzf0mG+JUfUzG4fIMWwHWP0iyaLWEQZJmtB7nOHEm/qw==} + nan@2.24.0: + resolution: {integrity: sha512-Vpf9qnVW1RaDkoNKFUvfxqAbtI8ncb8OJlqZ9wwpXzWPEsvsB1nvdUi6oYrHIkQ1Y/tMDnr1h4nczS0VB9Xykg==} nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} @@ -8829,8 +8833,8 @@ packages: encoding: optional: true - node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + node-forge@1.3.3: + resolution: {integrity: sha512-rLvcdSyRCyouf6jcOIPe/BgwG/d7hKjzMKOas33/pHEr6gbq18IK9zV7DiPvzsz0oBJPme6qr6H6kGZuI9/DZg==} engines: {node: '>= 6.13.0'} node-gyp-build-optional-packages@5.2.2: @@ -8871,10 +8875,6 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} - normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - normalize-url@8.1.0: resolution: {integrity: sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==} engines: {node: '>=14.16'} @@ -8905,16 +8905,16 @@ packages: peerDependencies: webpack: ^4.0.0 || ^5.0.0 - nwsapi@2.2.22: - resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==} + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} nypm@0.6.0: resolution: {integrity: sha512-mn8wBFV9G9+UFHIrq+pZ2r2zL4aPau/by3kJb3cM7+5tQHMt6HGQB8FDIeKFYp8o0D2pnH6nVsO88N4AmUxIWg==} engines: {node: ^14.16.0 || >=16.10.0} hasBin: true - oauth4webapi@3.8.2: - resolution: {integrity: sha512-FzZZ+bht5X0FKe7Mwz3DAVAmlH1BV5blSak/lHMBKz0/EBMhX6B10GlQYI51+oRp8ObJaX0g6pXrAxZh5s8rjw==} + oauth4webapi@3.8.3: + resolution: {integrity: sha512-pQ5BsX3QRTgnt5HxgHwgunIRaDXBdkT23tf8dfzmtTIL2LTpdmxgbpbBm0VgFWAIDlezQvQCTgnVIUmHupXHxw==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} @@ -8942,8 +8942,8 @@ packages: obuf@1.1.2: resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - oidc-provider@9.5.2: - resolution: {integrity: sha512-lTI6U7ESvf34xuu9XPUfJX6sbIXuOsV2MUPT9YoT7dzDtajufc50iWSY2t/4xB/TuFQ4t0Q++JU2Cu270d11pg==} + oidc-provider@9.6.0: + resolution: {integrity: sha512-CCRUYPOumEy/DT+L86H40WgXjXfDHlsJYZdyd4ZKGFxJh/kAd7DxMX3dwpbX0g+WjB+NWU+kla1b/yZmHNcR0Q==} on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} @@ -9614,8 +9614,8 @@ packages: peerDependencies: postcss: ^8.4 - postcss-preset-env@10.4.0: - resolution: {integrity: sha512-2kqpOthQ6JhxqQq1FSAAZGe9COQv75Aw8WbsOvQVNJ2nSevc9Yx/IKZGuZ7XJ+iOTtVon7LfO7ELRzg8AZ+sdw==} + postcss-preset-env@10.5.0: + resolution: {integrity: sha512-xgxFQPAPxeWmsgy8cR7GM1PGAL/smA5E9qU7K//D4vucS01es3M0fDujhDJn3kY8Ip7/vVYcecbe1yY+vBo3qQ==} engines: {node: '>=18'} peerDependencies: postcss: ^8.4 @@ -9671,8 +9671,8 @@ packages: resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} engines: {node: '>=4'} - postcss-selector-parser@7.1.0: - resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} engines: {node: '>=4'} postcss-sort-media-queries@5.2.0: @@ -9756,14 +9756,14 @@ packages: peerDependencies: prettier: ^3.0.0 - prettier-plugin-svelte@3.4.0: - resolution: {integrity: sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==} + prettier-plugin-svelte@3.4.1: + resolution: {integrity: sha512-xL49LCloMoZRvSwa6IEdN2GV6cq2IqpYGstYtMT+5wmml1/dClEoI0MZR78MiVPpu6BdQFfN0/y73yO6+br5Pg==} peerDependencies: prettier: ^3.0.0 svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0 - prettier@3.7.1: - resolution: {integrity: sha512-RWKXE4qB3u5Z6yz7omJkjWwmTfLdcbv44jUVHC5NpfXwFGzvpQM798FGv/6WNK879tc+Cn0AAyherCl1KjbyZQ==} + prettier@3.7.4: + resolution: {integrity: sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==} engines: {node: '>=14'} hasBin: true @@ -9819,9 +9819,6 @@ packages: property-information@5.6.0: resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} - property-information@6.5.0: - resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} - property-information@7.1.0: resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} @@ -9926,10 +9923,10 @@ packages: peerDependencies: react: ^18.3.1 - react-dom@19.2.0: - resolution: {integrity: sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==} + react-dom@19.2.3: + resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: - react: ^19.2.0 + react: ^19.2.3 react-email@4.3.2: resolution: {integrity: sha512-WaZcnv9OAIRULY236zDRdk+8r511ooJGH5UOb7FnVsV33hGPI+l5aIZ6drVjXi4QrlLTmLm8PsYvmXRSv31MPA==} @@ -9981,8 +9978,8 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} - react@19.2.0: - resolution: {integrity: sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==} + react@19.2.3: + resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==} engines: {node: '>=0.10.0'} read-cache@1.0.0: @@ -10122,8 +10119,8 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-in-the-middle@8.0.0: - resolution: {integrity: sha512-9s0pnM5tH8G4dSI3pms2GboYOs25LwOGnRMxN/Hx3TYT1K0rh6OjaWf4dI0DAQnMyaEXWoGVnSTPQasqwzTTAA==} + require-in-the-middle@8.0.1: + resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} require-like@0.1.2: @@ -10206,8 +10203,8 @@ packages: rollup: optional: true - rollup@4.53.3: - resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} + rollup@4.53.4: + resolution: {integrity: sha512-YpXaaArg0MvrnJpvduEDYIp7uGOqKXbH9NsHGQ6SxKCOsNAjZF018MmxefFUulVP2KLtiGw1UvZbr+/ekjvlDg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -10215,9 +10212,6 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - rrweb-cssom@0.8.0: - resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} - rtlcss@4.3.0: resolution: {integrity: sha512-FI+pHEn7Wc4NqKXMXFM+VAYKEj/mRIcW4h24YVwVtyjI+EqGrLc2Hx/Ny0lrZ21cBWU2goLy36eqMcNj3AQJig==} engines: {node: '>=12.0.0'} @@ -10271,8 +10265,8 @@ packages: sanitize-html@2.17.0: resolution: {integrity: sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==} - sax@1.4.1: - resolution: {integrity: sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==} + sax@1.4.3: + resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==} saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} @@ -10325,16 +10319,12 @@ packages: engines: {node: '>=10'} hasBin: true - send@0.19.0: - resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} engines: {node: '>= 0.8.0'} - send@0.19.1: - resolution: {integrity: sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==} - engines: {node: '>= 0.8.0'} - - send@1.2.0: - resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==} + send@1.2.1: + resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} serialize-javascript@6.0.2: @@ -10347,12 +10337,12 @@ packages: resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} engines: {node: '>= 0.8.0'} - serve-static@1.16.2: - resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} engines: {node: '>= 0.8.0'} - serve-static@2.2.0: - resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==} + serve-static@2.2.1: + resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} set-blocking@2.0.0: @@ -10544,8 +10534,8 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sql-formatter@15.6.10: - resolution: {integrity: sha512-0bJOPQrRO/JkjQhiThVayq0hOKnI1tHI+2OTkmT7TGtc6kqS+V7kveeMzRW+RNQGxofmTmet9ILvztyuxv0cJQ==} + sql-formatter@15.6.12: + resolution: {integrity: sha512-mkpF+RG402P66VMsnQkWewTRzDBWfu9iLbOfxaW/nAKOS/2A9MheQmcU5cmX0D0At9azrorZwpvcBRNNBozACQ==} hasBin: true srcset@4.0.0: @@ -10573,10 +10563,6 @@ packages: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} - statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} @@ -10659,21 +10645,18 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@3.0.0: - resolution: {integrity: sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strnum@2.1.1: - resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} + strnum@2.1.2: + resolution: {integrity: sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==} strtok3@10.3.4: resolution: {integrity: sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==} engines: {node: '>=18'} - style-to-js@1.1.18: - resolution: {integrity: sha512-JFPn62D4kJaPTnhFUI244MThx+FEGbi+9dw1b9yBBQ+1CZpV7QAT8kUtJ7b7EUNdHajjF/0x8fT+16oLJoojLg==} - - style-to-object@1.0.11: - resolution: {integrity: sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==} + style-to-js@1.1.21: + resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} style-to-object@1.0.14: resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} @@ -10723,9 +10706,9 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 typescript: '>=5.0.0' - svelte-eslint-parser@1.4.0: - resolution: {integrity: sha512-fjPzOfipR5S7gQ/JvI9r2H8y9gMGXO3JtmrylHLLyahEMquXI0lrebcjT+9/hNgDej0H7abTyox5HpHmW1PSWA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0, pnpm: 10.18.3} + svelte-eslint-parser@1.4.1: + resolution: {integrity: sha512-1eqkfQ93goAhjAXxZiu1SaKI9+0/sxp4JIWQwUpsz7ybehRE5L8dNuz7Iry7K22R47p5/+s9EM+38nHV2OlgXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0, pnpm: 10.24.0} peerDependencies: svelte: ^3.37.0 || ^4.0.0 || ^5.0.0 peerDependenciesMeta: @@ -10777,8 +10760,8 @@ packages: peerDependencies: svelte: ^5.30.2 - svelte@5.45.2: - resolution: {integrity: sha512-yyXdW2u3H0H/zxxWoGwJoQlRgaSJLp+Vhktv12iRw2WRDlKqUPT54Fi0K/PkXqrdkcQ98aBazpy0AH4BCBVfoA==} + svelte@5.43.3: + resolution: {integrity: sha512-kjkAjCk41mJfvJZG56XcJNOdJSke94JxtcX8zFzzz2vrt47E0LnoBzU6azIZ1aBxJgUep8qegAkguSf1GjxLXQ==} engines: {node: '>=18'} svg-parser@2.0.4: @@ -10792,8 +10775,8 @@ packages: swagger-ui-dist@5.30.2: resolution: {integrity: sha512-HWCg1DTNE/Nmapt+0m2EPXFwNKNeKK4PwMjkwveN/zn1cV2Kxi9SURd+m0SpdcSgWEK/O64sf8bzXdtUhigtHA==} - swr@2.3.6: - resolution: {integrity: sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==} + swr@2.3.8: + resolution: {integrity: sha512-gaCPRVoMq8WGDcWj9p4YWzCMPHzE0WNl6W8ADIx9c3JBEIdMkJGMzW+uzXvxHMltwcYACr9jP+32H8/hgwMR7w==} peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -10847,13 +10830,13 @@ packages: peerDependencies: tailwindcss: '>=3.4.17' - tailwindcss@3.4.18: - resolution: {integrity: sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==} + tailwindcss@3.4.19: + resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==} engines: {node: '>=14.0.0'} hasBin: true - tailwindcss@4.1.17: - resolution: {integrity: sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q==} + tailwindcss@4.1.18: + resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==} tapable@2.3.0: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} @@ -10880,8 +10863,8 @@ packages: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} - terser-webpack-plugin@5.3.14: - resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} + terser-webpack-plugin@5.3.16: + resolution: {integrity: sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -10896,8 +10879,8 @@ packages: uglify-js: optional: true - terser@5.44.0: - resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==} + terser@5.44.1: + resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} engines: {node: '>=10'} hasBin: true @@ -10905,8 +10888,8 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} - testcontainers@11.9.0: - resolution: {integrity: sha512-SQ6OqQUig7HcGVF72i+ZVIMvxPSpEz8cgC/B63ekqMzgf98DnveoBbOmqux/Wa5wQAQCt4mEPNMa/Jz7vMg9fQ==} + testcontainers@11.10.0: + resolution: {integrity: sha512-8hwK2EnrOZfrHPpDC7CPe03q7H8Vv8j3aXdcmFFyNV8dzpBzgZYmqyDtduJ8YQ5kbzj+A+jUXMQ6zI8B5U3z+g==} text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -10931,8 +10914,8 @@ packages: three@0.179.1: resolution: {integrity: sha512-5y/elSIQbrvKOISxpwXCR4sQqHtGiOI+MKLc3SsBdDXA2hz3Mdp3X59aUp8DyybMa34aeBwbFTpdoLJaUDEWSw==} - three@0.180.0: - resolution: {integrity: sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w==} + three@0.182.0: + resolution: {integrity: sha512-GbHabT+Irv+ihI1/f5kIIsZ+Ef9Sl5A1Y7imvS5RQjWgtTPfPnZ43JmlYI7NtCRDK9zir20lQpfg8/9Yd02OvQ==} throttleit@2.1.0: resolution: {integrity: sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==} @@ -10984,17 +10967,10 @@ packages: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} - tinyspy@4.0.3: - resolution: {integrity: sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==} + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} engines: {node: '>=14.0.0'} - tldts-core@6.1.86: - resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - - tldts@6.1.86: - resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} - hasBin: true - tmp@0.2.5: resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} engines: {node: '>=14.14'} @@ -11022,10 +10998,6 @@ packages: resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} - tough-cookie@5.1.2: - resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} - engines: {node: '>=16'} - tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -11033,10 +11005,6 @@ packages: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} engines: {node: '>=12'} - tr46@5.1.1: - resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} - engines: {node: '>=18'} - tree-dump@1.1.0: resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} engines: {node: '>=10.0'} @@ -11125,8 +11093,8 @@ packages: typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - typescript-eslint@8.48.0: - resolution: {integrity: sha512-fcKOvQD9GUn3Xw63EgiDqhvWJ5jsyZUaekl3KVpGsDJnN46WJTe3jWxtQP9lMZm1LJNkFLlTaWAxK2vUQR+cqw==} + typescript-eslint@8.50.0: + resolution: {integrity: sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -11140,8 +11108,8 @@ packages: ua-is-frozen@0.1.2: resolution: {integrity: sha512-RwKDW2p3iyWn4UbaxpP2+VxwqXh0jpvdxsYpZ5j/MLLiQOfbsV5shpgQiw93+KMYQPcteeMQ289MaAFzs3G9pw==} - ua-parser-js@2.0.6: - resolution: {integrity: sha512-EmaxXfltJaDW75SokrY4/lXMrVyXomE/0FpIIqP2Ctic93gK7rlme55Cwkz8l3YZ6gqf94fCU7AnIkidd/KXPg==} + ua-parser-js@2.0.7: + resolution: {integrity: sha512-CFdHVHr+6YfbktNZegH3qbYvYgC7nRNEUm2tk7nSFXSODUu4tDBpaFpP1jdXBUOKKwapVlWRfTtS8bCPzsQ47w==} hasBin: true uglify-js@3.19.3: @@ -11266,8 +11234,8 @@ packages: resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} engines: {node: '>=18.12.0'} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + update-browserslist-db@1.2.2: + resolution: {integrity: sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -11276,6 +11244,9 @@ packages: resolution: {integrity: sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==} engines: {node: '>=14.16'} + uplot@1.6.32: + resolution: {integrity: sha512-KIMVnG68zvu5XXUbC4LQEPnhwOxBuLyW1AHtpm6IKTXImkbLgkMy+jabjLgSLMasNuGGzQm/ep3tOkyTxpiQIw==} + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -11383,8 +11354,8 @@ packages: vite: optional: true - vite@7.2.4: - resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} + vite@7.3.0: + resolution: {integrity: sha512-dZwN5L1VlUBewiP6H9s2+B3e3Jg96D0vzN+Ry73sOefebhYr9f94wwkMNN/9ouoU8pV1BqA1d1zGk8928cx0rg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -11472,10 +11443,6 @@ packages: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} - watchpack@2.4.4: resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==} engines: {node: '>=10.13.0'} @@ -11573,26 +11540,14 @@ packages: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - whatwg-url@11.0.0: resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} engines: {node: '>=12'} - whatwg-url@14.2.0: - resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} - engines: {node: '>=18'} - whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -11705,10 +11660,6 @@ packages: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} - xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} - engines: {node: '>=18'} - xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -11785,8 +11736,8 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} - zod@4.1.12: - resolution: {integrity: sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==} + zod@4.2.1: + resolution: {integrity: sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==} zwitch@1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} @@ -11798,141 +11749,141 @@ snapshots: '@adobe/css-tools@4.4.4': {} - '@ai-sdk/gateway@2.0.3(zod@4.1.12)': + '@ai-sdk/gateway@2.0.21(zod@4.2.1)': dependencies: '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.14(zod@4.1.12) - '@vercel/oidc': 3.0.3 - zod: 4.1.12 + '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) + '@vercel/oidc': 3.0.5 + zod: 4.2.1 - '@ai-sdk/provider-utils@3.0.14(zod@4.1.12)': + '@ai-sdk/provider-utils@3.0.19(zod@4.2.1)': dependencies: '@ai-sdk/provider': 2.0.0 - '@standard-schema/spec': 1.0.0 + '@standard-schema/spec': 1.1.0 eventsource-parser: 3.0.6 - zod: 4.1.12 + zod: 4.2.1 '@ai-sdk/provider@2.0.0': dependencies: json-schema: 0.4.0 - '@ai-sdk/react@2.0.82(react@18.3.1)(zod@4.1.12)': + '@ai-sdk/react@2.0.115(react@18.3.1)(zod@4.2.1)': dependencies: - '@ai-sdk/provider-utils': 3.0.14(zod@4.1.12) - ai: 5.0.82(zod@4.1.12) + '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) + ai: 5.0.113(zod@4.2.1) react: 18.3.1 - swr: 2.3.6(react@18.3.1) + swr: 2.3.8(react@18.3.1) throttleit: 2.1.0 optionalDependencies: - zod: 4.1.12 + zod: 4.2.1 - '@algolia/abtesting@1.7.0': + '@algolia/abtesting@1.12.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/autocomplete-core@1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.3)': + '@algolia/autocomplete-core@1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.3) - '@algolia/autocomplete-shared': 1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0) + '@algolia/autocomplete-plugin-algolia-insights': 1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0)(search-insights@2.17.3) + '@algolia/autocomplete-shared': 1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0) transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - search-insights - '@algolia/autocomplete-plugin-algolia-insights@1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.3)': + '@algolia/autocomplete-plugin-algolia-insights@1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0)(search-insights@2.17.3)': dependencies: - '@algolia/autocomplete-shared': 1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0) + '@algolia/autocomplete-shared': 1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0) search-insights: 2.17.3 transitivePeerDependencies: - '@algolia/client-search' - algoliasearch - '@algolia/autocomplete-shared@1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)': + '@algolia/autocomplete-shared@1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0)': dependencies: - '@algolia/client-search': 5.41.0 - algoliasearch: 5.41.0 + '@algolia/client-search': 5.46.0 + algoliasearch: 5.46.0 - '@algolia/client-abtesting@5.41.0': + '@algolia/client-abtesting@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/client-analytics@5.41.0': + '@algolia/client-analytics@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/client-common@5.41.0': {} + '@algolia/client-common@5.46.0': {} - '@algolia/client-insights@5.41.0': + '@algolia/client-insights@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/client-personalization@5.41.0': + '@algolia/client-personalization@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/client-query-suggestions@5.41.0': + '@algolia/client-query-suggestions@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/client-search@5.41.0': + '@algolia/client-search@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 '@algolia/events@4.0.1': {} - '@algolia/ingestion@1.41.0': + '@algolia/ingestion@1.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/monitoring@1.41.0': + '@algolia/monitoring@1.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/recommend@5.41.0': + '@algolia/recommend@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/client-common': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 - '@algolia/requester-browser-xhr@5.41.0': + '@algolia/requester-browser-xhr@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 + '@algolia/client-common': 5.46.0 - '@algolia/requester-fetch@5.41.0': + '@algolia/requester-fetch@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 + '@algolia/client-common': 5.46.0 - '@algolia/requester-node-http@5.41.0': + '@algolia/requester-node-http@5.46.0': dependencies: - '@algolia/client-common': 5.41.0 + '@algolia/client-common': 5.46.0 '@alloc/quick-lru@5.2.0': {} @@ -11963,11 +11914,11 @@ snapshots: optionalDependencies: chokidar: 4.0.3 - '@angular-devkit/schematics-cli@19.2.19(@types/node@24.10.1)(chokidar@4.0.3)': + '@angular-devkit/schematics-cli@19.2.19(@types/node@24.10.4)(chokidar@4.0.3)': dependencies: '@angular-devkit/core': 19.2.19(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.19(chokidar@4.0.3) - '@inquirer/prompts': 7.3.2(@types/node@24.10.1) + '@inquirer/prompts': 7.3.2(@types/node@24.10.4) ansi-colors: 4.1.3 symbol-observable: 4.0.0 yargs-parser: 21.1.1 @@ -11995,15 +11946,6 @@ snapshots: transitivePeerDependencies: - chokidar - '@asamuzakjp/css-color@3.2.0': - dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 10.4.3 - optional: true - '@aws-crypto/sha256-browser@5.2.0': dependencies: '@aws-crypto/sha256-js': 5.2.0 @@ -12030,210 +11972,210 @@ snapshots: '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 - '@aws-sdk/client-sesv2@3.939.0': + '@aws-sdk/client-sesv2@3.952.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 - '@aws-sdk/credential-provider-node': 3.939.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/credential-provider-node': 3.952.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 - '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.948.0 + '@aws-sdk/middleware-user-agent': 3.947.0 '@aws-sdk/region-config-resolver': 3.936.0 - '@aws-sdk/signature-v4-multi-region': 3.939.0 + '@aws-sdk/signature-v4-multi-region': 3.947.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 - '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 - '@smithy/fetch-http-handler': 5.3.6 - '@smithy/hash-node': 4.2.5 - '@smithy/invalid-dependency': 4.2.5 - '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 - '@smithy/middleware-serde': 4.2.6 - '@smithy/middleware-stack': 4.2.5 - '@smithy/node-config-provider': 4.3.5 - '@smithy/node-http-handler': 4.4.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 - '@smithy/url-parser': 4.2.5 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.4 + '@smithy/core': 3.19.0 + '@smithy/fetch-http-handler': 5.3.7 + '@smithy/hash-node': 4.2.6 + '@smithy/invalid-dependency': 4.2.6 + '@smithy/middleware-content-length': 4.2.6 + '@smithy/middleware-endpoint': 4.4.0 + '@smithy/middleware-retry': 4.4.16 + '@smithy/middleware-serde': 4.2.7 + '@smithy/middleware-stack': 4.2.6 + '@smithy/node-config-provider': 4.3.6 + '@smithy/node-http-handler': 4.4.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 + '@smithy/url-parser': 4.2.6 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 - '@smithy/util-endpoints': 3.2.5 - '@smithy/util-middleware': 4.2.5 - '@smithy/util-retry': 4.2.5 + '@smithy/util-defaults-mode-browser': 4.3.15 + '@smithy/util-defaults-mode-node': 4.2.18 + '@smithy/util-endpoints': 3.2.6 + '@smithy/util-middleware': 4.2.6 + '@smithy/util-retry': 4.2.6 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso@3.936.0': + '@aws-sdk/client-sso@3.948.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 - '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.948.0 + '@aws-sdk/middleware-user-agent': 3.947.0 '@aws-sdk/region-config-resolver': 3.936.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 - '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 - '@smithy/fetch-http-handler': 5.3.6 - '@smithy/hash-node': 4.2.5 - '@smithy/invalid-dependency': 4.2.5 - '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 - '@smithy/middleware-serde': 4.2.6 - '@smithy/middleware-stack': 4.2.5 - '@smithy/node-config-provider': 4.3.5 - '@smithy/node-http-handler': 4.4.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 - '@smithy/url-parser': 4.2.5 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.4 + '@smithy/core': 3.19.0 + '@smithy/fetch-http-handler': 5.3.7 + '@smithy/hash-node': 4.2.6 + '@smithy/invalid-dependency': 4.2.6 + '@smithy/middleware-content-length': 4.2.6 + '@smithy/middleware-endpoint': 4.4.0 + '@smithy/middleware-retry': 4.4.16 + '@smithy/middleware-serde': 4.2.7 + '@smithy/middleware-stack': 4.2.6 + '@smithy/node-config-provider': 4.3.6 + '@smithy/node-http-handler': 4.4.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 + '@smithy/url-parser': 4.2.6 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 - '@smithy/util-endpoints': 3.2.5 - '@smithy/util-middleware': 4.2.5 - '@smithy/util-retry': 4.2.5 + '@smithy/util-defaults-mode-browser': 4.3.15 + '@smithy/util-defaults-mode-node': 4.2.18 + '@smithy/util-endpoints': 3.2.6 + '@smithy/util-middleware': 4.2.6 + '@smithy/util-retry': 4.2.6 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/core@3.936.0': + '@aws-sdk/core@3.947.0': dependencies: '@aws-sdk/types': 3.936.0 '@aws-sdk/xml-builder': 3.930.0 - '@smithy/core': 3.18.5 - '@smithy/node-config-provider': 4.3.5 - '@smithy/property-provider': 4.2.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/signature-v4': 5.3.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 + '@smithy/core': 3.19.0 + '@smithy/node-config-provider': 4.3.6 + '@smithy/property-provider': 4.2.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/signature-v4': 5.3.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 '@smithy/util-base64': 4.3.0 - '@smithy/util-middleware': 4.2.5 + '@smithy/util-middleware': 4.2.6 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-env@3.936.0': + '@aws-sdk/credential-provider-env@3.947.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/types': 3.936.0 - '@smithy/property-provider': 4.2.5 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-http@3.936.0': + '@aws-sdk/credential-provider-http@3.947.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/types': 3.936.0 - '@smithy/fetch-http-handler': 5.3.6 - '@smithy/node-http-handler': 4.4.5 - '@smithy/property-provider': 4.2.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 - '@smithy/util-stream': 4.5.6 + '@smithy/fetch-http-handler': 5.3.7 + '@smithy/node-http-handler': 4.4.6 + '@smithy/property-provider': 4.2.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 + '@smithy/util-stream': 4.5.7 tslib: 2.8.1 - '@aws-sdk/credential-provider-ini@3.939.0': + '@aws-sdk/credential-provider-ini@3.952.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/credential-provider-env': 3.936.0 - '@aws-sdk/credential-provider-http': 3.936.0 - '@aws-sdk/credential-provider-login': 3.939.0 - '@aws-sdk/credential-provider-process': 3.936.0 - '@aws-sdk/credential-provider-sso': 3.939.0 - '@aws-sdk/credential-provider-web-identity': 3.939.0 - '@aws-sdk/nested-clients': 3.939.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/credential-provider-env': 3.947.0 + '@aws-sdk/credential-provider-http': 3.947.0 + '@aws-sdk/credential-provider-login': 3.952.0 + '@aws-sdk/credential-provider-process': 3.947.0 + '@aws-sdk/credential-provider-sso': 3.952.0 + '@aws-sdk/credential-provider-web-identity': 3.952.0 + '@aws-sdk/nested-clients': 3.952.0 '@aws-sdk/types': 3.936.0 - '@smithy/credential-provider-imds': 4.2.5 - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/credential-provider-imds': 4.2.6 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-login@3.939.0': + '@aws-sdk/credential-provider-login@3.952.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/nested-clients': 3.939.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.952.0 '@aws-sdk/types': 3.936.0 - '@smithy/property-provider': 4.2.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-node@3.939.0': + '@aws-sdk/credential-provider-node@3.952.0': dependencies: - '@aws-sdk/credential-provider-env': 3.936.0 - '@aws-sdk/credential-provider-http': 3.936.0 - '@aws-sdk/credential-provider-ini': 3.939.0 - '@aws-sdk/credential-provider-process': 3.936.0 - '@aws-sdk/credential-provider-sso': 3.939.0 - '@aws-sdk/credential-provider-web-identity': 3.939.0 + '@aws-sdk/credential-provider-env': 3.947.0 + '@aws-sdk/credential-provider-http': 3.947.0 + '@aws-sdk/credential-provider-ini': 3.952.0 + '@aws-sdk/credential-provider-process': 3.947.0 + '@aws-sdk/credential-provider-sso': 3.952.0 + '@aws-sdk/credential-provider-web-identity': 3.952.0 '@aws-sdk/types': 3.936.0 - '@smithy/credential-provider-imds': 4.2.5 - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/credential-provider-imds': 4.2.6 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-process@3.936.0': + '@aws-sdk/credential-provider-process@3.947.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/types': 3.936.0 - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/credential-provider-sso@3.939.0': + '@aws-sdk/credential-provider-sso@3.952.0': dependencies: - '@aws-sdk/client-sso': 3.936.0 - '@aws-sdk/core': 3.936.0 - '@aws-sdk/token-providers': 3.939.0 + '@aws-sdk/client-sso': 3.948.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/token-providers': 3.952.0 '@aws-sdk/types': 3.936.0 - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt - '@aws-sdk/credential-provider-web-identity@3.939.0': + '@aws-sdk/credential-provider-web-identity@3.952.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/nested-clients': 3.939.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.952.0 '@aws-sdk/types': 3.936.0 - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt @@ -12241,89 +12183,89 @@ snapshots: '@aws-sdk/middleware-host-header@3.936.0': dependencies: '@aws-sdk/types': 3.936.0 - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 '@aws-sdk/middleware-logger@3.936.0': dependencies: '@aws-sdk/types': 3.936.0 - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/middleware-recursion-detection@3.936.0': + '@aws-sdk/middleware-recursion-detection@3.948.0': dependencies: '@aws-sdk/types': 3.936.0 - '@aws/lambda-invoke-store': 0.2.1 - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@aws/lambda-invoke-store': 0.2.2 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/middleware-sdk-s3@3.939.0': + '@aws-sdk/middleware-sdk-s3@3.947.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-arn-parser': 3.893.0 - '@smithy/core': 3.18.5 - '@smithy/node-config-provider': 4.3.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/signature-v4': 5.3.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 + '@smithy/core': 3.19.0 + '@smithy/node-config-provider': 4.3.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/signature-v4': 5.3.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 '@smithy/util-config-provider': 4.2.0 - '@smithy/util-middleware': 4.2.5 - '@smithy/util-stream': 4.5.6 + '@smithy/util-middleware': 4.2.6 + '@smithy/util-stream': 4.5.7 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@aws-sdk/middleware-user-agent@3.936.0': + '@aws-sdk/middleware-user-agent@3.947.0': dependencies: - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 - '@smithy/core': 3.18.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/core': 3.19.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/nested-clients@3.939.0': + '@aws-sdk/nested-clients@3.952.0': dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.936.0 + '@aws-sdk/core': 3.947.0 '@aws-sdk/middleware-host-header': 3.936.0 '@aws-sdk/middleware-logger': 3.936.0 - '@aws-sdk/middleware-recursion-detection': 3.936.0 - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.948.0 + '@aws-sdk/middleware-user-agent': 3.947.0 '@aws-sdk/region-config-resolver': 3.936.0 '@aws-sdk/types': 3.936.0 '@aws-sdk/util-endpoints': 3.936.0 '@aws-sdk/util-user-agent-browser': 3.936.0 - '@aws-sdk/util-user-agent-node': 3.936.0 - '@smithy/config-resolver': 4.4.3 - '@smithy/core': 3.18.5 - '@smithy/fetch-http-handler': 5.3.6 - '@smithy/hash-node': 4.2.5 - '@smithy/invalid-dependency': 4.2.5 - '@smithy/middleware-content-length': 4.2.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-retry': 4.4.12 - '@smithy/middleware-serde': 4.2.6 - '@smithy/middleware-stack': 4.2.5 - '@smithy/node-config-provider': 4.3.5 - '@smithy/node-http-handler': 4.4.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 - '@smithy/url-parser': 4.2.5 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.4 + '@smithy/core': 3.19.0 + '@smithy/fetch-http-handler': 5.3.7 + '@smithy/hash-node': 4.2.6 + '@smithy/invalid-dependency': 4.2.6 + '@smithy/middleware-content-length': 4.2.6 + '@smithy/middleware-endpoint': 4.4.0 + '@smithy/middleware-retry': 4.4.16 + '@smithy/middleware-serde': 4.2.7 + '@smithy/middleware-stack': 4.2.6 + '@smithy/node-config-provider': 4.3.6 + '@smithy/node-http-handler': 4.4.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 + '@smithy/url-parser': 4.2.6 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.11 - '@smithy/util-defaults-mode-node': 4.2.14 - '@smithy/util-endpoints': 3.2.5 - '@smithy/util-middleware': 4.2.5 - '@smithy/util-retry': 4.2.5 + '@smithy/util-defaults-mode-browser': 4.3.15 + '@smithy/util-defaults-mode-node': 4.2.18 + '@smithy/util-endpoints': 3.2.6 + '@smithy/util-middleware': 4.2.6 + '@smithy/util-retry': 4.2.6 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 transitivePeerDependencies: @@ -12332,35 +12274,35 @@ snapshots: '@aws-sdk/region-config-resolver@3.936.0': dependencies: '@aws-sdk/types': 3.936.0 - '@smithy/config-resolver': 4.4.3 - '@smithy/node-config-provider': 4.3.5 - '@smithy/types': 4.9.0 + '@smithy/config-resolver': 4.4.4 + '@smithy/node-config-provider': 4.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/signature-v4-multi-region@3.939.0': + '@aws-sdk/signature-v4-multi-region@3.947.0': dependencies: - '@aws-sdk/middleware-sdk-s3': 3.939.0 + '@aws-sdk/middleware-sdk-s3': 3.947.0 '@aws-sdk/types': 3.936.0 - '@smithy/protocol-http': 5.3.5 - '@smithy/signature-v4': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/signature-v4': 5.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@aws-sdk/token-providers@3.939.0': + '@aws-sdk/token-providers@3.952.0': dependencies: - '@aws-sdk/core': 3.936.0 - '@aws-sdk/nested-clients': 3.939.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.952.0 '@aws-sdk/types': 3.936.0 - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 transitivePeerDependencies: - aws-crt '@aws-sdk/types@3.936.0': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 '@aws-sdk/util-arn-parser@3.893.0': @@ -12370,9 +12312,9 @@ snapshots: '@aws-sdk/util-endpoints@3.936.0': dependencies: '@aws-sdk/types': 3.936.0 - '@smithy/types': 4.9.0 - '@smithy/url-parser': 4.2.5 - '@smithy/util-endpoints': 3.2.5 + '@smithy/types': 4.10.0 + '@smithy/url-parser': 4.2.6 + '@smithy/util-endpoints': 3.2.6 tslib: 2.8.1 '@aws-sdk/util-locate-window@3.893.0': @@ -12382,25 +12324,25 @@ snapshots: '@aws-sdk/util-user-agent-browser@3.936.0': dependencies: '@aws-sdk/types': 3.936.0 - '@smithy/types': 4.9.0 - bowser: 2.13.0 + '@smithy/types': 4.10.0 + bowser: 2.13.1 tslib: 2.8.1 - '@aws-sdk/util-user-agent-node@3.936.0': + '@aws-sdk/util-user-agent-node@3.947.0': dependencies: - '@aws-sdk/middleware-user-agent': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.947.0 '@aws-sdk/types': 3.936.0 - '@smithy/node-config-provider': 4.3.5 - '@smithy/types': 4.9.0 + '@smithy/node-config-provider': 4.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 '@aws-sdk/xml-builder@3.930.0': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 fast-xml-parser: 5.2.5 tslib: 2.8.1 - '@aws/lambda-invoke-store@0.2.1': {} + '@aws/lambda-invoke-store@0.2.2': {} '@babel/code-frame@7.27.1': dependencies: @@ -12446,7 +12388,7 @@ snapshots: dependencies: '@babel/compat-data': 7.28.5 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.0 + browserslist: 4.28.1 lru-cache: 5.1.1 semver: 6.3.1 @@ -13091,7 +13033,7 @@ snapshots: babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.5) babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.5) babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.5) - core-js-compat: 3.46.0 + core-js-compat: 3.47.0 semver: 6.3.1 transitivePeerDependencies: - supports-color @@ -13128,7 +13070,7 @@ snapshots: '@babel/runtime-corejs3@7.28.4': dependencies: - core-js-pure: 3.46.0 + core-js-pure: 3.47.0 '@babel/runtime@7.28.4': {} @@ -13205,9 +13147,9 @@ snapshots: '@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.6)': dependencies: - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 '@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.6)': dependencies: @@ -13313,9 +13255,9 @@ snapshots: '@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.6)': dependencies: - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 '@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.6)': dependencies: @@ -13383,6 +13325,10 @@ snapshots: '@csstools/utilities': 2.0.0(postcss@8.5.6) postcss: 8.5.6 + '@csstools/postcss-position-area-property@1.0.0(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + '@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.6)': dependencies: postcss: 8.5.6 @@ -13407,7 +13353,7 @@ snapshots: '@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.6)': dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 '@csstools/postcss-sign-functions@1.1.4(postcss@8.5.6)': dependencies: @@ -13423,6 +13369,12 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.6 + '@csstools/postcss-system-ui-font-family@1.0.0(postcss@8.5.6)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + postcss: 8.5.6 + '@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.6)': dependencies: '@csstools/color-helpers': 5.1.0 @@ -13440,13 +13392,13 @@ snapshots: dependencies: postcss: 8.5.6 - '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.0)': + '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)': dependencies: - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 - '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': + '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)': dependencies: - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 '@csstools/utilities@2.0.0(postcss@8.5.6)': dependencies: @@ -13454,17 +13406,24 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} - '@docsearch/css@4.2.0': {} + '@docsearch/core@4.3.1(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + optionalDependencies: + '@types/react': 19.2.7 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) - '@docsearch/react@4.2.0(@algolia/client-search@5.41.0)(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': + '@docsearch/css@4.3.2': {} + + '@docsearch/react@4.3.2(@algolia/client-search@5.46.0)(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)': dependencies: - '@ai-sdk/react': 2.0.82(react@18.3.1)(zod@4.1.12) - '@algolia/autocomplete-core': 1.19.2(@algolia/client-search@5.41.0)(algoliasearch@5.41.0)(search-insights@2.17.3) - '@docsearch/css': 4.2.0 - ai: 5.0.82(zod@4.1.12) - algoliasearch: 5.41.0 - marked: 16.4.1 - zod: 4.1.12 + '@ai-sdk/react': 2.0.115(react@18.3.1)(zod@4.2.1) + '@algolia/autocomplete-core': 1.19.2(@algolia/client-search@5.46.0)(algoliasearch@5.46.0)(search-insights@2.17.3) + '@docsearch/core': 4.3.1(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@docsearch/css': 4.3.2 + ai: 5.0.113(zod@4.2.1) + algoliasearch: 5.46.0 + marked: 16.4.2 + zod: 4.2.1 optionalDependencies: '@types/react': 19.2.7 react: 18.3.1 @@ -13519,8 +13478,8 @@ snapshots: null-loader: 4.0.1(webpack@5.103.0) postcss: 8.5.6 postcss-loader: 7.3.4(postcss@8.5.6)(typescript@5.9.3)(webpack@5.103.0) - postcss-preset-env: 10.4.0(postcss@8.5.6) - terser-webpack-plugin: 5.3.14(webpack@5.103.0) + postcss-preset-env: 10.5.0(postcss@8.5.6) + terser-webpack-plugin: 5.3.16(webpack@5.103.0) tslib: 2.8.1 url-loader: 4.1.1(file-loader@6.2.0(webpack@5.103.0))(webpack@5.103.0) webpack: 5.103.0 @@ -13556,7 +13515,7 @@ snapshots: cli-table3: 0.6.5 combine-promises: 1.2.0 commander: 5.1.0 - core-js: 3.46.0 + core-js: 3.47.0 detect-port: 1.6.1 escape-html: 1.0.3 eta: 2.2.0 @@ -13564,7 +13523,7 @@ snapshots: execa: 5.1.1 fs-extra: 11.3.2 html-tags: 3.3.1 - html-webpack-plugin: 5.6.4(webpack@5.103.0) + html-webpack-plugin: 5.6.5(webpack@5.103.0) leven: 3.1.0 lodash: 4.17.21 open: 8.4.2 @@ -13975,7 +13934,7 @@ snapshots: - utf-8-validate - webpack-cli - '@docusaurus/preset-classic@3.9.2(@algolia/client-search@5.41.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3)': + '@docusaurus/preset-classic@3.9.2(@algolia/client-search@5.46.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3)': dependencies: '@docusaurus/core': 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) '@docusaurus/plugin-content-blog': 3.9.2(@docusaurus/plugin-content-docs@3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) @@ -13990,7 +13949,7 @@ snapshots: '@docusaurus/plugin-svgr': 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) '@docusaurus/theme-classic': 3.9.2(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) '@docusaurus/theme-common': 3.9.2(@docusaurus/plugin-content-docs@3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@docusaurus/theme-search-algolia': 3.9.2(@algolia/client-search@5.41.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3) + '@docusaurus/theme-search-algolia': 3.9.2(@algolia/client-search@5.46.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3) '@docusaurus/types': 3.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -14091,9 +14050,9 @@ snapshots: - uglify-js - webpack-cli - '@docusaurus/theme-search-algolia@3.9.2(@algolia/client-search@5.41.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3)': + '@docusaurus/theme-search-algolia@3.9.2(@algolia/client-search@5.46.0)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3)(typescript@5.9.3)': dependencies: - '@docsearch/react': 4.2.0(@algolia/client-search@5.41.0)(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) + '@docsearch/react': 4.3.2(@algolia/client-search@5.46.0)(@types/react@19.2.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(search-insights@2.17.3) '@docusaurus/core': 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) '@docusaurus/logger': 3.9.2 '@docusaurus/plugin-content-docs': 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3) @@ -14101,8 +14060,8 @@ snapshots: '@docusaurus/theme-translations': 3.9.2 '@docusaurus/utils': 3.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@docusaurus/utils-validation': 3.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - algoliasearch: 5.41.0 - algoliasearch-helper: 3.26.0(algoliasearch@5.41.0) + algoliasearch: 5.46.0 + algoliasearch-helper: 3.26.1(algoliasearch@5.46.0) clsx: 2.1.1 eta: 2.2.0 fs-extra: 11.3.2 @@ -14235,7 +14194,7 @@ snapshots: '@esbuild/aix-ppc64@0.25.12': optional: true - '@esbuild/aix-ppc64@0.27.0': + '@esbuild/aix-ppc64@0.27.1': optional: true '@esbuild/android-arm64@0.19.12': @@ -14244,7 +14203,7 @@ snapshots: '@esbuild/android-arm64@0.25.12': optional: true - '@esbuild/android-arm64@0.27.0': + '@esbuild/android-arm64@0.27.1': optional: true '@esbuild/android-arm@0.19.12': @@ -14253,7 +14212,7 @@ snapshots: '@esbuild/android-arm@0.25.12': optional: true - '@esbuild/android-arm@0.27.0': + '@esbuild/android-arm@0.27.1': optional: true '@esbuild/android-x64@0.19.12': @@ -14262,7 +14221,7 @@ snapshots: '@esbuild/android-x64@0.25.12': optional: true - '@esbuild/android-x64@0.27.0': + '@esbuild/android-x64@0.27.1': optional: true '@esbuild/darwin-arm64@0.19.12': @@ -14271,7 +14230,7 @@ snapshots: '@esbuild/darwin-arm64@0.25.12': optional: true - '@esbuild/darwin-arm64@0.27.0': + '@esbuild/darwin-arm64@0.27.1': optional: true '@esbuild/darwin-x64@0.19.12': @@ -14280,7 +14239,7 @@ snapshots: '@esbuild/darwin-x64@0.25.12': optional: true - '@esbuild/darwin-x64@0.27.0': + '@esbuild/darwin-x64@0.27.1': optional: true '@esbuild/freebsd-arm64@0.19.12': @@ -14289,7 +14248,7 @@ snapshots: '@esbuild/freebsd-arm64@0.25.12': optional: true - '@esbuild/freebsd-arm64@0.27.0': + '@esbuild/freebsd-arm64@0.27.1': optional: true '@esbuild/freebsd-x64@0.19.12': @@ -14298,7 +14257,7 @@ snapshots: '@esbuild/freebsd-x64@0.25.12': optional: true - '@esbuild/freebsd-x64@0.27.0': + '@esbuild/freebsd-x64@0.27.1': optional: true '@esbuild/linux-arm64@0.19.12': @@ -14307,7 +14266,7 @@ snapshots: '@esbuild/linux-arm64@0.25.12': optional: true - '@esbuild/linux-arm64@0.27.0': + '@esbuild/linux-arm64@0.27.1': optional: true '@esbuild/linux-arm@0.19.12': @@ -14316,7 +14275,7 @@ snapshots: '@esbuild/linux-arm@0.25.12': optional: true - '@esbuild/linux-arm@0.27.0': + '@esbuild/linux-arm@0.27.1': optional: true '@esbuild/linux-ia32@0.19.12': @@ -14325,7 +14284,7 @@ snapshots: '@esbuild/linux-ia32@0.25.12': optional: true - '@esbuild/linux-ia32@0.27.0': + '@esbuild/linux-ia32@0.27.1': optional: true '@esbuild/linux-loong64@0.19.12': @@ -14334,7 +14293,7 @@ snapshots: '@esbuild/linux-loong64@0.25.12': optional: true - '@esbuild/linux-loong64@0.27.0': + '@esbuild/linux-loong64@0.27.1': optional: true '@esbuild/linux-mips64el@0.19.12': @@ -14343,7 +14302,7 @@ snapshots: '@esbuild/linux-mips64el@0.25.12': optional: true - '@esbuild/linux-mips64el@0.27.0': + '@esbuild/linux-mips64el@0.27.1': optional: true '@esbuild/linux-ppc64@0.19.12': @@ -14352,7 +14311,7 @@ snapshots: '@esbuild/linux-ppc64@0.25.12': optional: true - '@esbuild/linux-ppc64@0.27.0': + '@esbuild/linux-ppc64@0.27.1': optional: true '@esbuild/linux-riscv64@0.19.12': @@ -14361,7 +14320,7 @@ snapshots: '@esbuild/linux-riscv64@0.25.12': optional: true - '@esbuild/linux-riscv64@0.27.0': + '@esbuild/linux-riscv64@0.27.1': optional: true '@esbuild/linux-s390x@0.19.12': @@ -14370,7 +14329,7 @@ snapshots: '@esbuild/linux-s390x@0.25.12': optional: true - '@esbuild/linux-s390x@0.27.0': + '@esbuild/linux-s390x@0.27.1': optional: true '@esbuild/linux-x64@0.19.12': @@ -14379,13 +14338,13 @@ snapshots: '@esbuild/linux-x64@0.25.12': optional: true - '@esbuild/linux-x64@0.27.0': + '@esbuild/linux-x64@0.27.1': optional: true '@esbuild/netbsd-arm64@0.25.12': optional: true - '@esbuild/netbsd-arm64@0.27.0': + '@esbuild/netbsd-arm64@0.27.1': optional: true '@esbuild/netbsd-x64@0.19.12': @@ -14394,13 +14353,13 @@ snapshots: '@esbuild/netbsd-x64@0.25.12': optional: true - '@esbuild/netbsd-x64@0.27.0': + '@esbuild/netbsd-x64@0.27.1': optional: true '@esbuild/openbsd-arm64@0.25.12': optional: true - '@esbuild/openbsd-arm64@0.27.0': + '@esbuild/openbsd-arm64@0.27.1': optional: true '@esbuild/openbsd-x64@0.19.12': @@ -14409,13 +14368,13 @@ snapshots: '@esbuild/openbsd-x64@0.25.12': optional: true - '@esbuild/openbsd-x64@0.27.0': + '@esbuild/openbsd-x64@0.27.1': optional: true '@esbuild/openharmony-arm64@0.25.12': optional: true - '@esbuild/openharmony-arm64@0.27.0': + '@esbuild/openharmony-arm64@0.27.1': optional: true '@esbuild/sunos-x64@0.19.12': @@ -14424,7 +14383,7 @@ snapshots: '@esbuild/sunos-x64@0.25.12': optional: true - '@esbuild/sunos-x64@0.27.0': + '@esbuild/sunos-x64@0.27.1': optional: true '@esbuild/win32-arm64@0.19.12': @@ -14433,7 +14392,7 @@ snapshots: '@esbuild/win32-arm64@0.25.12': optional: true - '@esbuild/win32-arm64@0.27.0': + '@esbuild/win32-arm64@0.27.1': optional: true '@esbuild/win32-ia32@0.19.12': @@ -14442,7 +14401,7 @@ snapshots: '@esbuild/win32-ia32@0.25.12': optional: true - '@esbuild/win32-ia32@0.27.0': + '@esbuild/win32-ia32@0.27.1': optional: true '@esbuild/win32-x64@0.19.12': @@ -14451,12 +14410,12 @@ snapshots: '@esbuild/win32-x64@0.25.12': optional: true - '@esbuild/win32-x64@0.27.0': + '@esbuild/win32-x64@0.27.1': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(jiti@2.6.1))': + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.6.1))': dependencies: - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.2(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} @@ -14477,7 +14436,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1': + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 debug: 4.4.3 @@ -14491,7 +14450,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.39.1': {} + '@eslint/js@9.39.2': {} '@eslint/object-schema@2.1.7': {} @@ -14511,7 +14470,7 @@ snapshots: '@fig/complete-commander@3.2.0(commander@11.1.0)': dependencies: commander: 11.1.0 - prettier: 3.7.1 + prettier: 3.7.4 '@floating-ui/core@1.7.3': dependencies: @@ -14556,7 +14515,7 @@ snapshots: '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(@nestjs/websockets@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) lodash: 4.17.21 - '@grpc/grpc-js@1.14.2': + '@grpc/grpc-js@1.14.3': dependencies: '@grpc/proto-loader': 0.8.0 '@js-sdsl/ordered-map': 4.4.2 @@ -14690,165 +14649,165 @@ snapshots: '@immich/justified-layout-wasm@0.4.3': {} - '@immich/svelte-markdown-preprocess@0.1.0(svelte@5.45.2)': + '@immich/svelte-markdown-preprocess@0.1.0(svelte@5.43.3)': dependencies: - svelte: 5.45.2 + svelte: 5.43.3 - '@immich/ui@0.49.3(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)': + '@immich/ui@0.50.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)': dependencies: - '@immich/svelte-markdown-preprocess': 0.1.0(svelte@5.45.2) + '@immich/svelte-markdown-preprocess': 0.1.0(svelte@5.43.3) '@internationalized/date': 3.10.0 '@mdi/js': 7.4.47 - bits-ui: 2.14.4(@internationalized/date@3.10.0)(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2) + bits-ui: 2.14.4(@internationalized/date@3.10.0)(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3) luxon: 3.7.2 simple-icons: 15.22.0 - svelte: 5.45.2 + svelte: 5.43.3 svelte-highlight: 7.9.0 tailwind-merge: 3.4.0 - tailwind-variants: 3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.17) - tailwindcss: 4.1.17 + tailwind-variants: 3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.18) + tailwindcss: 4.1.18 transitivePeerDependencies: - '@sveltejs/kit' '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.2(@types/node@24.10.1)': + '@inquirer/checkbox@4.3.2(@types/node@24.10.4)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/confirm@5.1.21(@types/node@24.10.1)': + '@inquirer/confirm@5.1.21(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/core@10.3.2(@types/node@24.10.1)': + '@inquirer/core@10.3.2(@types/node@24.10.4)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.4) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/editor@4.2.23(@types/node@24.10.1)': + '@inquirer/editor@4.2.23(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/external-editor': 1.0.3(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/expand@4.0.23(@types/node@24.10.1)': + '@inquirer/expand@4.0.23(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/external-editor@1.0.3(@types/node@24.10.1)': + '@inquirer/external-editor@1.0.3(@types/node@24.10.4)': dependencies: chardet: 2.1.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.1 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.1(@types/node@24.10.1)': + '@inquirer/input@4.3.1(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/number@3.0.23(@types/node@24.10.1)': + '@inquirer/number@3.0.23(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/password@4.0.23(@types/node@24.10.1)': + '@inquirer/password@4.0.23(@types/node@24.10.4)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/prompts@7.10.1(@types/node@24.10.1)': + '@inquirer/prompts@7.10.1(@types/node@24.10.4)': dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@24.10.1) - '@inquirer/confirm': 5.1.21(@types/node@24.10.1) - '@inquirer/editor': 4.2.23(@types/node@24.10.1) - '@inquirer/expand': 4.0.23(@types/node@24.10.1) - '@inquirer/input': 4.3.1(@types/node@24.10.1) - '@inquirer/number': 3.0.23(@types/node@24.10.1) - '@inquirer/password': 4.0.23(@types/node@24.10.1) - '@inquirer/rawlist': 4.1.11(@types/node@24.10.1) - '@inquirer/search': 3.2.2(@types/node@24.10.1) - '@inquirer/select': 4.4.2(@types/node@24.10.1) + '@inquirer/checkbox': 4.3.2(@types/node@24.10.4) + '@inquirer/confirm': 5.1.21(@types/node@24.10.4) + '@inquirer/editor': 4.2.23(@types/node@24.10.4) + '@inquirer/expand': 4.0.23(@types/node@24.10.4) + '@inquirer/input': 4.3.1(@types/node@24.10.4) + '@inquirer/number': 3.0.23(@types/node@24.10.4) + '@inquirer/password': 4.0.23(@types/node@24.10.4) + '@inquirer/rawlist': 4.1.11(@types/node@24.10.4) + '@inquirer/search': 3.2.2(@types/node@24.10.4) + '@inquirer/select': 4.4.2(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/prompts@7.3.2(@types/node@24.10.1)': + '@inquirer/prompts@7.3.2(@types/node@24.10.4)': dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@24.10.1) - '@inquirer/confirm': 5.1.21(@types/node@24.10.1) - '@inquirer/editor': 4.2.23(@types/node@24.10.1) - '@inquirer/expand': 4.0.23(@types/node@24.10.1) - '@inquirer/input': 4.3.1(@types/node@24.10.1) - '@inquirer/number': 3.0.23(@types/node@24.10.1) - '@inquirer/password': 4.0.23(@types/node@24.10.1) - '@inquirer/rawlist': 4.1.11(@types/node@24.10.1) - '@inquirer/search': 3.2.2(@types/node@24.10.1) - '@inquirer/select': 4.4.2(@types/node@24.10.1) + '@inquirer/checkbox': 4.3.2(@types/node@24.10.4) + '@inquirer/confirm': 5.1.21(@types/node@24.10.4) + '@inquirer/editor': 4.2.23(@types/node@24.10.4) + '@inquirer/expand': 4.0.23(@types/node@24.10.4) + '@inquirer/input': 4.3.1(@types/node@24.10.4) + '@inquirer/number': 3.0.23(@types/node@24.10.4) + '@inquirer/password': 4.0.23(@types/node@24.10.4) + '@inquirer/rawlist': 4.1.11(@types/node@24.10.4) + '@inquirer/search': 3.2.2(@types/node@24.10.4) + '@inquirer/select': 4.4.2(@types/node@24.10.4) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/rawlist@4.1.11(@types/node@24.10.1)': + '@inquirer/rawlist@4.1.11(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) + '@inquirer/type': 3.0.10(@types/node@24.10.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/search@3.2.2(@types/node@24.10.1)': + '@inquirer/search@3.2.2(@types/node@24.10.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/select@4.4.2(@types/node@24.10.1)': + '@inquirer/select@4.4.2(@types/node@24.10.4)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.10.1) + '@inquirer/core': 10.3.2(@types/node@24.10.4) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.10.1) + '@inquirer/type': 3.0.10(@types/node@24.10.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@inquirer/type@3.0.10(@types/node@24.10.1)': + '@inquirer/type@3.0.10(@types/node@24.10.4)': optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@internationalized/date@3.10.0': dependencies: @@ -14886,8 +14845,8 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 24.10.1 - '@types/yargs': 17.0.34 + '@types/node': 24.10.4 + '@types/yargs': 17.0.35 chalk: 4.1.2 '@jridgewell/gen-mapping@0.3.13': @@ -14956,21 +14915,22 @@ snapshots: dependencies: vary: 1.1.2 - '@koa/router@14.0.0': + '@koa/router@15.1.0(koa@3.1.1)': dependencies: debug: 4.4.3 http-errors: 2.0.1 + koa: 3.1.1 koa-compose: 4.1.0 path-to-regexp: 8.3.0 transitivePeerDependencies: - supports-color - '@koddsson/eslint-plugin-tscompat@0.2.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': + '@koddsson/eslint-plugin-tscompat@0.2.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@mdn/browser-compat-data': 6.0.27 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - browserslist: 4.28.0 + '@mdn/browser-compat-data': 6.1.5 + '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + browserslist: 4.28.1 transitivePeerDependencies: - eslint - supports-color @@ -15052,7 +15012,7 @@ snapshots: '@mapbox/whoots-js@3.1.0': {} - '@maplibre/maplibre-gl-style-spec@24.3.1': + '@maplibre/maplibre-gl-style-spec@24.4.1': dependencies: '@mapbox/jsonlint-lines-primitives': 2.0.2 '@mapbox/unitbezier': 0.0.1 @@ -15062,11 +15022,11 @@ snapshots: rw: 1.3.3 tinyqueue: 3.0.0 - '@maplibre/mlt@1.1.0': + '@maplibre/mlt@1.1.2': dependencies: '@mapbox/point-geometry': 1.1.0 - '@maplibre/vt-pbf@4.0.3': + '@maplibre/vt-pbf@4.2.0': dependencies: '@mapbox/point-geometry': 1.1.0 '@mapbox/vector-tile': 2.0.4 @@ -15084,7 +15044,7 @@ snapshots: '@mdn/browser-compat-data@5.7.6': {} - '@mdn/browser-compat-data@6.0.27': {} + '@mdn/browser-compat-data@6.1.5': {} '@mdx-js/mdx@3.1.1': dependencies: @@ -15150,36 +15110,36 @@ snapshots: '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(@nestjs/websockets@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) tslib: 2.8.1 - '@nestjs/bullmq@11.0.4(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(bullmq@5.65.0)': + '@nestjs/bullmq@11.0.4(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(bullmq@5.66.0)': dependencies: '@nestjs/bull-shared': 11.0.4(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9) '@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(@nestjs/websockets@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) - bullmq: 5.65.0 + bullmq: 5.66.0 tslib: 2.8.1 - '@nestjs/cli@11.0.13(@swc/core@1.15.3(@swc/helpers@0.5.17))(@types/node@24.10.1)': + '@nestjs/cli@11.0.14(@swc/core@1.15.5(@swc/helpers@0.5.17))(@types/node@24.10.4)': dependencies: '@angular-devkit/core': 19.2.19(chokidar@4.0.3) '@angular-devkit/schematics': 19.2.19(chokidar@4.0.3) - '@angular-devkit/schematics-cli': 19.2.19(@types/node@24.10.1)(chokidar@4.0.3) - '@inquirer/prompts': 7.10.1(@types/node@24.10.1) + '@angular-devkit/schematics-cli': 19.2.19(@types/node@24.10.4)(chokidar@4.0.3) + '@inquirer/prompts': 7.10.1(@types/node@24.10.4) '@nestjs/schematics': 11.0.9(chokidar@4.0.3)(typescript@5.9.3) ansis: 4.2.0 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.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17))) + fork-ts-checker-webpack-plugin: 9.1.0(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17))) 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.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17)) + webpack: 5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17)) webpack-node-externals: 3.0.0 optionalDependencies: - '@swc/core': 1.15.3(@swc/helpers@0.5.17) + '@swc/core': 1.15.5(@swc/helpers@0.5.17) transitivePeerDependencies: - '@types/node' - esbuild @@ -15248,11 +15208,11 @@ snapshots: - supports-color - utf-8-validate - '@nestjs/schedule@6.0.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)': + '@nestjs/schedule@6.1.0(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)': dependencies: '@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(@nestjs/websockets@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) - cron: 4.3.3 + cron: 4.3.5 '@nestjs/schematics@11.0.9(chokidar@4.0.3)(typescript@5.9.3)': dependencies: @@ -15332,7 +15292,7 @@ snapshots: dependencies: consola: 3.4.2 - '@oazapfts/runtime@1.0.4': {} + '@oazapfts/runtime@1.1.0': {} '@opentelemetry/api-logs@0.208.0': dependencies: @@ -15351,7 +15311,7 @@ snapshots: '@opentelemetry/exporter-logs-otlp-grpc@0.208.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.14.2 + '@grpc/grpc-js': 1.14.3 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/otlp-exporter-base': 0.208.0(@opentelemetry/api@1.9.0) @@ -15381,7 +15341,7 @@ snapshots: '@opentelemetry/exporter-metrics-otlp-grpc@0.208.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.14.2 + '@grpc/grpc-js': 1.14.3 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/exporter-metrics-otlp-http': 0.208.0(@opentelemetry/api@1.9.0) @@ -15419,7 +15379,7 @@ snapshots: '@opentelemetry/exporter-trace-otlp-grpc@0.208.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.14.2 + '@grpc/grpc-js': 1.14.3 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/otlp-exporter-base': 0.208.0(@opentelemetry/api@1.9.0) @@ -15454,7 +15414,7 @@ snapshots: '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.38.0 - '@opentelemetry/host-metrics@0.36.0(@opentelemetry/api@1.9.0)': + '@opentelemetry/host-metrics@0.36.2(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 systeminformation: 5.23.8 @@ -15502,7 +15462,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/api-logs': 0.208.0 import-in-the-middle: 2.0.0 - require-in-the-middle: 8.0.0 + require-in-the-middle: 8.0.1 transitivePeerDependencies: - supports-color @@ -15514,7 +15474,7 @@ snapshots: '@opentelemetry/otlp-grpc-exporter-base@0.208.0(@opentelemetry/api@1.9.0)': dependencies: - '@grpc/grpc-js': 1.14.2 + '@grpc/grpc-js': 1.14.3 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/otlp-exporter-base': 0.208.0(@opentelemetry/api@1.9.0) @@ -15611,7 +15571,7 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) - '@paralleldrive/cuid2@2.2.2': + '@paralleldrive/cuid2@2.3.1': dependencies: '@noble/hashes': 1.8.0 @@ -15623,7 +15583,7 @@ snapshots: dependencies: '@photo-sphere-viewer/core': 5.14.0 '@photo-sphere-viewer/video-plugin': 5.14.0(@photo-sphere-viewer/core@5.14.0) - three: 0.180.0 + three: 0.182.0 '@photo-sphere-viewer/markers-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)': dependencies: @@ -15641,7 +15601,7 @@ snapshots: '@photo-sphere-viewer/video-plugin@5.14.0(@photo-sphere-viewer/core@5.14.0)': dependencies: '@photo-sphere-viewer/core': 5.14.0 - three: 0.180.0 + three: 0.182.0 '@photostructure/tz-lookup@11.3.0': {} @@ -15691,190 +15651,190 @@ snapshots: '@protobufjs/utf8@1.1.0': {} - '@react-email/body@0.1.0(react@19.2.0)': + '@react-email/body@0.1.0(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/button@0.2.0(react@19.2.0)': + '@react-email/button@0.2.0(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/code-block@0.1.0(react@19.2.0)': + '@react-email/code-block@0.1.0(react@19.2.3)': dependencies: prismjs: 1.30.0 - react: 19.2.0 + react: 19.2.3 - '@react-email/code-inline@0.0.5(react@19.2.0)': + '@react-email/code-inline@0.0.5(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/column@0.0.13(react@19.2.0)': + '@react-email/column@0.0.13(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/components@0.5.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@react-email/components@0.5.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: - '@react-email/body': 0.1.0(react@19.2.0) - '@react-email/button': 0.2.0(react@19.2.0) - '@react-email/code-block': 0.1.0(react@19.2.0) - '@react-email/code-inline': 0.0.5(react@19.2.0) - '@react-email/column': 0.0.13(react@19.2.0) - '@react-email/container': 0.0.15(react@19.2.0) - '@react-email/font': 0.0.9(react@19.2.0) - '@react-email/head': 0.0.12(react@19.2.0) - '@react-email/heading': 0.0.15(react@19.2.0) - '@react-email/hr': 0.0.11(react@19.2.0) - '@react-email/html': 0.0.11(react@19.2.0) - '@react-email/img': 0.0.11(react@19.2.0) - '@react-email/link': 0.0.12(react@19.2.0) - '@react-email/markdown': 0.0.16(react@19.2.0) - '@react-email/preview': 0.0.13(react@19.2.0) - '@react-email/render': 1.4.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0) - '@react-email/row': 0.0.12(react@19.2.0) - '@react-email/section': 0.0.16(react@19.2.0) - '@react-email/tailwind': 1.2.2(react@19.2.0) - '@react-email/text': 0.1.5(react@19.2.0) - react: 19.2.0 + '@react-email/body': 0.1.0(react@19.2.3) + '@react-email/button': 0.2.0(react@19.2.3) + '@react-email/code-block': 0.1.0(react@19.2.3) + '@react-email/code-inline': 0.0.5(react@19.2.3) + '@react-email/column': 0.0.13(react@19.2.3) + '@react-email/container': 0.0.15(react@19.2.3) + '@react-email/font': 0.0.9(react@19.2.3) + '@react-email/head': 0.0.12(react@19.2.3) + '@react-email/heading': 0.0.15(react@19.2.3) + '@react-email/hr': 0.0.11(react@19.2.3) + '@react-email/html': 0.0.11(react@19.2.3) + '@react-email/img': 0.0.11(react@19.2.3) + '@react-email/link': 0.0.12(react@19.2.3) + '@react-email/markdown': 0.0.16(react@19.2.3) + '@react-email/preview': 0.0.13(react@19.2.3) + '@react-email/render': 1.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@react-email/row': 0.0.12(react@19.2.3) + '@react-email/section': 0.0.16(react@19.2.3) + '@react-email/tailwind': 1.2.2(react@19.2.3) + '@react-email/text': 0.1.5(react@19.2.3) + react: 19.2.3 transitivePeerDependencies: - react-dom - '@react-email/container@0.0.15(react@19.2.0)': + '@react-email/container@0.0.15(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/font@0.0.9(react@19.2.0)': + '@react-email/font@0.0.9(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/head@0.0.12(react@19.2.0)': + '@react-email/head@0.0.12(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/heading@0.0.15(react@19.2.0)': + '@react-email/heading@0.0.15(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/hr@0.0.11(react@19.2.0)': + '@react-email/hr@0.0.11(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/html@0.0.11(react@19.2.0)': + '@react-email/html@0.0.11(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/img@0.0.11(react@19.2.0)': + '@react-email/img@0.0.11(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/link@0.0.12(react@19.2.0)': + '@react-email/link@0.0.12(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/markdown@0.0.16(react@19.2.0)': + '@react-email/markdown@0.0.16(react@19.2.3)': dependencies: marked: 15.0.12 - react: 19.2.0 + react: 19.2.3 - '@react-email/preview@0.0.13(react@19.2.0)': + '@react-email/preview@0.0.13(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/render@1.4.0(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + '@react-email/render@1.4.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: html-to-text: 9.0.5 - prettier: 3.7.1 - react: 19.2.0 - react-dom: 19.2.0(react@19.2.0) + prettier: 3.7.4 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) react-promise-suspense: 0.3.4 - '@react-email/row@0.0.12(react@19.2.0)': + '@react-email/row@0.0.12(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/section@0.0.16(react@19.2.0)': + '@react-email/section@0.0.16(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/tailwind@1.2.2(react@19.2.0)': + '@react-email/tailwind@1.2.2(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@react-email/text@0.1.5(react@19.2.0)': + '@react-email/text@0.1.5(react@19.2.3)': dependencies: - react: 19.2.0 + react: 19.2.3 - '@rollup/pluginutils@5.3.0(rollup@4.53.3)': + '@rollup/pluginutils@5.3.0(rollup@4.53.4)': dependencies: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 optionalDependencies: - rollup: 4.53.3 + rollup: 4.53.4 - '@rollup/rollup-android-arm-eabi@4.53.3': + '@rollup/rollup-android-arm-eabi@4.53.4': optional: true - '@rollup/rollup-android-arm64@4.53.3': + '@rollup/rollup-android-arm64@4.53.4': optional: true - '@rollup/rollup-darwin-arm64@4.53.3': + '@rollup/rollup-darwin-arm64@4.53.4': optional: true - '@rollup/rollup-darwin-x64@4.53.3': + '@rollup/rollup-darwin-x64@4.53.4': optional: true - '@rollup/rollup-freebsd-arm64@4.53.3': + '@rollup/rollup-freebsd-arm64@4.53.4': optional: true - '@rollup/rollup-freebsd-x64@4.53.3': + '@rollup/rollup-freebsd-x64@4.53.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + '@rollup/rollup-linux-arm-gnueabihf@4.53.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.3': + '@rollup/rollup-linux-arm-musleabihf@4.53.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.3': + '@rollup/rollup-linux-arm64-gnu@4.53.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.3': + '@rollup/rollup-linux-arm64-musl@4.53.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.3': + '@rollup/rollup-linux-loong64-gnu@4.53.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.3': + '@rollup/rollup-linux-ppc64-gnu@4.53.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.3': + '@rollup/rollup-linux-riscv64-gnu@4.53.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.3': + '@rollup/rollup-linux-riscv64-musl@4.53.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.3': + '@rollup/rollup-linux-s390x-gnu@4.53.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.3': + '@rollup/rollup-linux-x64-gnu@4.53.4': optional: true - '@rollup/rollup-linux-x64-musl@4.53.3': + '@rollup/rollup-linux-x64-musl@4.53.4': optional: true - '@rollup/rollup-openharmony-arm64@4.53.3': + '@rollup/rollup-openharmony-arm64@4.53.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.3': + '@rollup/rollup-win32-arm64-msvc@4.53.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.3': + '@rollup/rollup-win32-ia32-msvc@4.53.4': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.3': + '@rollup/rollup-win32-x64-gnu@4.53.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.3': + '@rollup/rollup-win32-x64-msvc@4.53.4': optional: true '@scarf/scarf@1.4.0': {} @@ -15914,59 +15874,59 @@ snapshots: micromark-util-character: 1.2.0 micromark-util-symbol: 1.1.0 - '@smithy/abort-controller@4.2.5': + '@smithy/abort-controller@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/config-resolver@4.4.3': + '@smithy/config-resolver@4.4.4': dependencies: - '@smithy/node-config-provider': 4.3.5 - '@smithy/types': 4.9.0 + '@smithy/node-config-provider': 4.3.6 + '@smithy/types': 4.10.0 '@smithy/util-config-provider': 4.2.0 - '@smithy/util-endpoints': 3.2.5 - '@smithy/util-middleware': 4.2.5 + '@smithy/util-endpoints': 3.2.6 + '@smithy/util-middleware': 4.2.6 tslib: 2.8.1 - '@smithy/core@3.18.5': + '@smithy/core@3.19.0': dependencies: - '@smithy/middleware-serde': 4.2.6 - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/middleware-serde': 4.2.7 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 - '@smithy/util-middleware': 4.2.5 - '@smithy/util-stream': 4.5.6 + '@smithy/util-middleware': 4.2.6 + '@smithy/util-stream': 4.5.7 '@smithy/util-utf8': 4.2.0 '@smithy/uuid': 1.1.0 tslib: 2.8.1 - '@smithy/credential-provider-imds@4.2.5': + '@smithy/credential-provider-imds@4.2.6': dependencies: - '@smithy/node-config-provider': 4.3.5 - '@smithy/property-provider': 4.2.5 - '@smithy/types': 4.9.0 - '@smithy/url-parser': 4.2.5 + '@smithy/node-config-provider': 4.3.6 + '@smithy/property-provider': 4.2.6 + '@smithy/types': 4.10.0 + '@smithy/url-parser': 4.2.6 tslib: 2.8.1 - '@smithy/fetch-http-handler@5.3.6': + '@smithy/fetch-http-handler@5.3.7': dependencies: - '@smithy/protocol-http': 5.3.5 - '@smithy/querystring-builder': 4.2.5 - '@smithy/types': 4.9.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/querystring-builder': 4.2.6 + '@smithy/types': 4.10.0 '@smithy/util-base64': 4.3.0 tslib: 2.8.1 - '@smithy/hash-node@4.2.5': + '@smithy/hash-node@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 '@smithy/util-buffer-from': 4.2.0 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@smithy/invalid-dependency@4.2.5': + '@smithy/invalid-dependency@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 '@smithy/is-array-buffer@2.2.0': @@ -15977,120 +15937,120 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/middleware-content-length@4.2.5': + '@smithy/middleware-content-length@4.2.6': dependencies: - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/middleware-endpoint@4.3.12': + '@smithy/middleware-endpoint@4.4.0': dependencies: - '@smithy/core': 3.18.5 - '@smithy/middleware-serde': 4.2.6 - '@smithy/node-config-provider': 4.3.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 - '@smithy/url-parser': 4.2.5 - '@smithy/util-middleware': 4.2.5 + '@smithy/core': 3.19.0 + '@smithy/middleware-serde': 4.2.7 + '@smithy/node-config-provider': 4.3.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 + '@smithy/url-parser': 4.2.6 + '@smithy/util-middleware': 4.2.6 tslib: 2.8.1 - '@smithy/middleware-retry@4.4.12': + '@smithy/middleware-retry@4.4.16': dependencies: - '@smithy/node-config-provider': 4.3.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/service-error-classification': 4.2.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 - '@smithy/util-middleware': 4.2.5 - '@smithy/util-retry': 4.2.5 + '@smithy/node-config-provider': 4.3.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/service-error-classification': 4.2.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 + '@smithy/util-middleware': 4.2.6 + '@smithy/util-retry': 4.2.6 '@smithy/uuid': 1.1.0 tslib: 2.8.1 - '@smithy/middleware-serde@4.2.6': + '@smithy/middleware-serde@4.2.7': dependencies: - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/middleware-stack@4.2.5': + '@smithy/middleware-stack@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/node-config-provider@4.3.5': + '@smithy/node-config-provider@4.3.6': dependencies: - '@smithy/property-provider': 4.2.5 - '@smithy/shared-ini-file-loader': 4.4.0 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/shared-ini-file-loader': 4.4.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/node-http-handler@4.4.5': + '@smithy/node-http-handler@4.4.6': dependencies: - '@smithy/abort-controller': 4.2.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/querystring-builder': 4.2.5 - '@smithy/types': 4.9.0 + '@smithy/abort-controller': 4.2.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/querystring-builder': 4.2.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/property-provider@4.2.5': + '@smithy/property-provider@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/protocol-http@5.3.5': + '@smithy/protocol-http@5.3.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/querystring-builder@4.2.5': + '@smithy/querystring-builder@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 '@smithy/util-uri-escape': 4.2.0 tslib: 2.8.1 - '@smithy/querystring-parser@4.2.5': + '@smithy/querystring-parser@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/service-error-classification@4.2.5': + '@smithy/service-error-classification@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 - '@smithy/shared-ini-file-loader@4.4.0': + '@smithy/shared-ini-file-loader@4.4.1': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/signature-v4@5.3.5': + '@smithy/signature-v4@5.3.6': dependencies: '@smithy/is-array-buffer': 4.2.0 - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 '@smithy/util-hex-encoding': 4.2.0 - '@smithy/util-middleware': 4.2.5 + '@smithy/util-middleware': 4.2.6 '@smithy/util-uri-escape': 4.2.0 '@smithy/util-utf8': 4.2.0 tslib: 2.8.1 - '@smithy/smithy-client@4.9.8': + '@smithy/smithy-client@4.10.1': dependencies: - '@smithy/core': 3.18.5 - '@smithy/middleware-endpoint': 4.3.12 - '@smithy/middleware-stack': 4.2.5 - '@smithy/protocol-http': 5.3.5 - '@smithy/types': 4.9.0 - '@smithy/util-stream': 4.5.6 + '@smithy/core': 3.19.0 + '@smithy/middleware-endpoint': 4.4.0 + '@smithy/middleware-stack': 4.2.6 + '@smithy/protocol-http': 5.3.6 + '@smithy/types': 4.10.0 + '@smithy/util-stream': 4.5.7 tslib: 2.8.1 - '@smithy/types@4.9.0': + '@smithy/types@4.10.0': dependencies: tslib: 2.8.1 - '@smithy/url-parser@4.2.5': + '@smithy/url-parser@4.2.6': dependencies: - '@smithy/querystring-parser': 4.2.5 - '@smithy/types': 4.9.0 + '@smithy/querystring-parser': 4.2.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 '@smithy/util-base64@4.3.0': @@ -16121,49 +16081,49 @@ snapshots: dependencies: tslib: 2.8.1 - '@smithy/util-defaults-mode-browser@4.3.11': + '@smithy/util-defaults-mode-browser@4.3.15': dependencies: - '@smithy/property-provider': 4.2.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 + '@smithy/property-provider': 4.2.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/util-defaults-mode-node@4.2.14': + '@smithy/util-defaults-mode-node@4.2.18': dependencies: - '@smithy/config-resolver': 4.4.3 - '@smithy/credential-provider-imds': 4.2.5 - '@smithy/node-config-provider': 4.3.5 - '@smithy/property-provider': 4.2.5 - '@smithy/smithy-client': 4.9.8 - '@smithy/types': 4.9.0 + '@smithy/config-resolver': 4.4.4 + '@smithy/credential-provider-imds': 4.2.6 + '@smithy/node-config-provider': 4.3.6 + '@smithy/property-provider': 4.2.6 + '@smithy/smithy-client': 4.10.1 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/util-endpoints@3.2.5': + '@smithy/util-endpoints@3.2.6': dependencies: - '@smithy/node-config-provider': 4.3.5 - '@smithy/types': 4.9.0 + '@smithy/node-config-provider': 4.3.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 '@smithy/util-hex-encoding@4.2.0': dependencies: tslib: 2.8.1 - '@smithy/util-middleware@4.2.5': + '@smithy/util-middleware@4.2.6': dependencies: - '@smithy/types': 4.9.0 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/util-retry@4.2.5': + '@smithy/util-retry@4.2.6': dependencies: - '@smithy/service-error-classification': 4.2.5 - '@smithy/types': 4.9.0 + '@smithy/service-error-classification': 4.2.6 + '@smithy/types': 4.10.0 tslib: 2.8.1 - '@smithy/util-stream@4.5.6': + '@smithy/util-stream@4.5.7': dependencies: - '@smithy/fetch-http-handler': 5.3.6 - '@smithy/node-http-handler': 4.4.5 - '@smithy/types': 4.9.0 + '@smithy/fetch-http-handler': 5.3.7 + '@smithy/node-http-handler': 4.4.6 + '@smithy/types': 4.10.0 '@smithy/util-base64': 4.3.0 '@smithy/util-buffer-from': 4.2.0 '@smithy/util-hex-encoding': 4.2.0 @@ -16199,39 +16159,39 @@ snapshots: transitivePeerDependencies: - supports-color - '@standard-schema/spec@1.0.0': {} + '@standard-schema/spec@1.1.0': {} '@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)': dependencies: acorn: 8.15.0 - '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))': + '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))': dependencies: - '@sveltejs/kit': 2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@sveltejs/kit': 2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) - '@sveltejs/enhanced-img@0.9.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(rollup@4.53.3)(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@sveltejs/enhanced-img@0.9.2(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(rollup@4.53.4)(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) magic-string: 0.30.21 sharp: 0.34.5 - svelte: 5.45.2 - svelte-parse-markup: 0.1.5(svelte@5.45.2) - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) - vite-imagetools: 9.0.2(rollup@4.53.3) + svelte: 5.43.3 + svelte-parse-markup: 0.1.5(svelte@5.43.3) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) + vite-imagetools: 9.0.2(rollup@4.53.4) zimmerframe: 1.1.4 transitivePeerDependencies: - rollup - supports-color - '@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: - '@standard-schema/spec': 1.0.0 + '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 - devalue: 5.5.0 + devalue: 5.6.1 esm-env: 1.2.2 kleur: 4.1.5 magic-string: 0.30.21 @@ -16239,29 +16199,29 @@ snapshots: sade: 1.8.1 set-cookie-parser: 2.7.2 sirv: 3.0.2 - svelte: 5.45.2 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + svelte: 5.43.3 + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) optionalDependencies: '@opentelemetry/api': 1.9.0 - '@sveltejs/vite-plugin-svelte-inspector@5.0.0(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: - '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@sveltejs/vite-plugin-svelte': 6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) debug: 4.4.3 - svelte: 5.45.2 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + svelte: 5.43.3 + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 5.0.0(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) debug: 4.4.3 deepmerge: 4.3.1 magic-string: 0.30.21 - svelte: 5.45.2 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) - vitefu: 1.1.1(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + svelte: 5.43.3 + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) + vitefu: 1.1.1(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) transitivePeerDependencies: - supports-color @@ -16358,51 +16318,51 @@ snapshots: - supports-color - typescript - '@swc/core-darwin-arm64@1.15.3': + '@swc/core-darwin-arm64@1.15.5': optional: true - '@swc/core-darwin-x64@1.15.3': + '@swc/core-darwin-x64@1.15.5': optional: true - '@swc/core-linux-arm-gnueabihf@1.15.3': + '@swc/core-linux-arm-gnueabihf@1.15.5': optional: true - '@swc/core-linux-arm64-gnu@1.15.3': + '@swc/core-linux-arm64-gnu@1.15.5': optional: true - '@swc/core-linux-arm64-musl@1.15.3': + '@swc/core-linux-arm64-musl@1.15.5': optional: true - '@swc/core-linux-x64-gnu@1.15.3': + '@swc/core-linux-x64-gnu@1.15.5': optional: true - '@swc/core-linux-x64-musl@1.15.3': + '@swc/core-linux-x64-musl@1.15.5': optional: true - '@swc/core-win32-arm64-msvc@1.15.3': + '@swc/core-win32-arm64-msvc@1.15.5': optional: true - '@swc/core-win32-ia32-msvc@1.15.3': + '@swc/core-win32-ia32-msvc@1.15.5': optional: true - '@swc/core-win32-x64-msvc@1.15.3': + '@swc/core-win32-x64-msvc@1.15.5': optional: true - '@swc/core@1.15.3(@swc/helpers@0.5.17)': + '@swc/core@1.15.5(@swc/helpers@0.5.17)': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.25 optionalDependencies: - '@swc/core-darwin-arm64': 1.15.3 - '@swc/core-darwin-x64': 1.15.3 - '@swc/core-linux-arm-gnueabihf': 1.15.3 - '@swc/core-linux-arm64-gnu': 1.15.3 - '@swc/core-linux-arm64-musl': 1.15.3 - '@swc/core-linux-x64-gnu': 1.15.3 - '@swc/core-linux-x64-musl': 1.15.3 - '@swc/core-win32-arm64-msvc': 1.15.3 - '@swc/core-win32-ia32-msvc': 1.15.3 - '@swc/core-win32-x64-msvc': 1.15.3 + '@swc/core-darwin-arm64': 1.15.5 + '@swc/core-darwin-x64': 1.15.5 + '@swc/core-linux-arm-gnueabihf': 1.15.5 + '@swc/core-linux-arm64-gnu': 1.15.5 + '@swc/core-linux-arm64-musl': 1.15.5 + '@swc/core-linux-x64-gnu': 1.15.5 + '@swc/core-linux-x64-musl': 1.15.5 + '@swc/core-win32-arm64-msvc': 1.15.5 + '@swc/core-win32-ia32-msvc': 1.15.5 + '@swc/core-win32-x64-msvc': 1.15.5 '@swc/helpers': 0.5.17 '@swc/counter@0.1.3': {} @@ -16419,73 +16379,73 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tailwindcss/node@4.1.17': + '@tailwindcss/node@4.1.18': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.18.3 + enhanced-resolve: 5.18.4 jiti: 2.6.1 lightningcss: 1.30.2 magic-string: 0.30.21 source-map-js: 1.2.1 - tailwindcss: 4.1.17 + tailwindcss: 4.1.18 - '@tailwindcss/oxide-android-arm64@4.1.17': + '@tailwindcss/oxide-android-arm64@4.1.18': optional: true - '@tailwindcss/oxide-darwin-arm64@4.1.17': + '@tailwindcss/oxide-darwin-arm64@4.1.18': optional: true - '@tailwindcss/oxide-darwin-x64@4.1.17': + '@tailwindcss/oxide-darwin-x64@4.1.18': optional: true - '@tailwindcss/oxide-freebsd-x64@4.1.17': + '@tailwindcss/oxide-freebsd-x64@4.1.18': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.1.17': + '@tailwindcss/oxide-linux-arm64-gnu@4.1.18': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.1.17': + '@tailwindcss/oxide-linux-arm64-musl@4.1.18': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.1.17': + '@tailwindcss/oxide-linux-x64-gnu@4.1.18': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.1.17': + '@tailwindcss/oxide-linux-x64-musl@4.1.18': optional: true - '@tailwindcss/oxide-wasm32-wasi@4.1.17': + '@tailwindcss/oxide-wasm32-wasi@4.1.18': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.1.17': + '@tailwindcss/oxide-win32-arm64-msvc@4.1.18': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.1.17': + '@tailwindcss/oxide-win32-x64-msvc@4.1.18': optional: true - '@tailwindcss/oxide@4.1.17': + '@tailwindcss/oxide@4.1.18': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.1.17 - '@tailwindcss/oxide-darwin-arm64': 4.1.17 - '@tailwindcss/oxide-darwin-x64': 4.1.17 - '@tailwindcss/oxide-freebsd-x64': 4.1.17 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.17 - '@tailwindcss/oxide-linux-arm64-gnu': 4.1.17 - '@tailwindcss/oxide-linux-arm64-musl': 4.1.17 - '@tailwindcss/oxide-linux-x64-gnu': 4.1.17 - '@tailwindcss/oxide-linux-x64-musl': 4.1.17 - '@tailwindcss/oxide-wasm32-wasi': 4.1.17 - '@tailwindcss/oxide-win32-arm64-msvc': 4.1.17 - '@tailwindcss/oxide-win32-x64-msvc': 4.1.17 + '@tailwindcss/oxide-android-arm64': 4.1.18 + '@tailwindcss/oxide-darwin-arm64': 4.1.18 + '@tailwindcss/oxide-darwin-x64': 4.1.18 + '@tailwindcss/oxide-freebsd-x64': 4.1.18 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18 + '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18 + '@tailwindcss/oxide-linux-arm64-musl': 4.1.18 + '@tailwindcss/oxide-linux-x64-gnu': 4.1.18 + '@tailwindcss/oxide-linux-x64-musl': 4.1.18 + '@tailwindcss/oxide-wasm32-wasi': 4.1.18 + '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18 + '@tailwindcss/oxide-win32-x64-msvc': 4.1.18 - '@tailwindcss/vite@4.1.17(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@tailwindcss/vite@4.1.18(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: - '@tailwindcss/node': 4.1.17 - '@tailwindcss/oxide': 4.1.17 - tailwindcss: 4.1.17 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + '@tailwindcss/node': 4.1.18 + '@tailwindcss/oxide': 4.1.18 + tailwindcss: 4.1.18 + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) '@testing-library/dom@10.4.1': dependencies: @@ -16507,13 +16467,13 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/svelte@5.2.9(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@testing-library/svelte@5.2.9(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: '@testing-library/dom': 10.4.1 - svelte: 5.45.2 + svelte: 5.43.3 optionalDependencies: - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': dependencies: @@ -16534,28 +16494,28 @@ snapshots: '@trysound/sax@0.2.0': {} - '@turf/boolean-point-in-polygon@7.2.0': + '@turf/boolean-point-in-polygon@7.3.1': dependencies: - '@turf/helpers': 7.2.0 - '@turf/invariant': 7.2.0 + '@turf/helpers': 7.3.1 + '@turf/invariant': 7.3.1 '@types/geojson': 7946.0.16 point-in-polygon-hao: 1.2.4 tslib: 2.8.1 - '@turf/helpers@7.2.0': + '@turf/helpers@7.3.1': dependencies: '@types/geojson': 7946.0.16 tslib: 2.8.1 - '@turf/invariant@7.2.0': + '@turf/invariant@7.3.1': dependencies: - '@turf/helpers': 7.2.0 + '@turf/helpers': 7.3.1 '@types/geojson': 7946.0.16 tslib: 2.8.1 '@types/accepts@1.3.7': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/archiver@7.0.0': dependencies: @@ -16567,72 +16527,73 @@ snapshots: '@types/bcrypt@6.0.0': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/body-parser@1.19.6': dependencies: '@types/connect': 3.4.38 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/bonjour@3.5.13': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/braces@3.0.5': {} '@types/byte-size@8.1.2': {} - '@types/chai@5.2.2': + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 - '@types/chrome@0.0.328': + '@types/chrome@0.1.32': dependencies: '@types/filesystem': 0.0.36 '@types/har-format': 1.2.16 '@types/chromecast-caf-sender@1.0.11': dependencies: - '@types/chrome': 0.0.328 + '@types/chrome': 0.1.32 '@types/cli-progress@3.11.6': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/compression@1.8.1': dependencies: - '@types/express': 5.0.5 - '@types/node': 24.10.1 + '@types/express': 5.0.6 + '@types/node': 24.10.4 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 5.1.0 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/connect@3.4.38': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/content-disposition@0.5.9': {} - '@types/cookie-parser@1.4.10(@types/express@5.0.5)': + '@types/cookie-parser@1.4.10(@types/express@5.0.6)': dependencies: - '@types/express': 5.0.5 + '@types/express': 5.0.6 '@types/cookie@0.6.0': {} '@types/cookiejar@2.1.5': {} - '@types/cookies@0.9.1': + '@types/cookies@0.9.2': dependencies: '@types/connect': 3.4.38 - '@types/express': 5.0.5 + '@types/express': 5.0.6 '@types/keygrip': 1.0.6 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/cors@2.8.19': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/debug@4.1.12': dependencies: @@ -16642,13 +16603,13 @@ snapshots: '@types/docker-modem@3.0.6': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ssh2': 1.15.5 '@types/dockerode@3.3.47': dependencies: '@types/docker-modem': 3.0.6 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ssh2': 1.15.5 '@types/dom-to-image@2.6.7': {} @@ -16671,14 +16632,14 @@ snapshots: '@types/express-serve-static-core@4.19.7': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 '@types/express-serve-static-core@5.1.0': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/qs': 6.14.0 '@types/range-parser': 1.2.7 '@types/send': 1.2.1 @@ -16690,11 +16651,11 @@ snapshots: '@types/qs': 6.14.0 '@types/serve-static': 1.15.10 - '@types/express@5.0.5': + '@types/express@5.0.6': dependencies: '@types/body-parser': 1.19.6 '@types/express-serve-static-core': 5.1.0 - '@types/serve-static': 1.15.10 + '@types/serve-static': 2.2.0 '@types/filesystem@0.0.36': dependencies: @@ -16704,7 +16665,7 @@ snapshots: '@types/fluent-ffmpeg@2.1.28': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/geojson-vt@3.2.5': dependencies: @@ -16736,9 +16697,9 @@ snapshots: '@types/http-proxy@1.17.17': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 - '@types/inquirer@8.2.11': + '@types/inquirer@8.2.12': dependencies: '@types/through': 0.0.33 rxjs: 7.8.2 @@ -16760,26 +16721,26 @@ snapshots: '@types/jsonwebtoken@9.0.10': dependencies: '@types/ms': 2.1.0 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/justified-layout@4.1.4': {} '@types/keygrip@1.0.6': {} - '@types/koa-compose@3.2.8': + '@types/koa-compose@3.2.9': dependencies: - '@types/koa': 3.0.0 + '@types/koa': 3.0.1 - '@types/koa@3.0.0': + '@types/koa@3.0.1': dependencies: '@types/accepts': 1.3.7 '@types/content-disposition': 0.5.9 - '@types/cookies': 0.9.1 + '@types/cookies': 0.9.2 '@types/http-assert': 1.5.6 '@types/http-errors': 2.0.5 '@types/keygrip': 1.0.6 - '@types/koa-compose': 3.2.8 - '@types/node': 24.10.1 + '@types/koa-compose': 3.2.9 + '@types/node': 24.10.4 '@types/leaflet@1.9.21': dependencies: @@ -16809,17 +16770,17 @@ snapshots: '@types/mock-fs@4.13.4': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ms@2.1.0': {} '@types/multer@2.0.0': dependencies: - '@types/express': 5.0.5 + '@types/express': 5.0.6 '@types/node-forge@1.3.14': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/node@17.0.45': {} @@ -16827,36 +16788,42 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@20.19.24': + '@types/node@20.19.27': dependencies: undici-types: 6.21.0 - '@types/node@24.10.1': + '@types/node@24.10.4': dependencies: undici-types: 7.16.0 '@types/nodemailer@7.0.4': dependencies: - '@aws-sdk/client-sesv2': 3.939.0 - '@types/node': 24.10.1 + '@aws-sdk/client-sesv2': 3.952.0 + '@types/node': 24.10.4 transitivePeerDependencies: - aws-crt '@types/oidc-provider@9.5.0': dependencies: '@types/keygrip': 1.0.6 - '@types/koa': 3.0.0 - '@types/node': 24.10.1 + '@types/koa': 3.0.1 + '@types/node': 24.10.4 '@types/parse5@5.0.3': {} '@types/pg-pool@2.0.6': dependencies: - '@types/pg': 8.15.6 + '@types/pg': 8.16.0 '@types/pg@8.15.6': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 + pg-protocol: 1.10.3 + pg-types: 2.2.0 + + '@types/pg@8.16.0': + dependencies: + '@types/node': 24.10.4 pg-protocol: 1.10.3 pg-types: 2.2.0 @@ -16864,13 +16831,13 @@ snapshots: '@types/pngjs@6.0.5': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/prismjs@1.26.5': {} '@types/qrcode@1.5.6': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/qs@6.14.0': {} @@ -16899,7 +16866,7 @@ snapshots: '@types/readdir-glob@1.1.5': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/retry@0.12.2': {} @@ -16909,40 +16876,45 @@ snapshots: '@types/sax@1.2.7': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/semver@7.7.1': {} '@types/send@0.17.6': dependencies: '@types/mime': 1.3.5 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/send@1.2.1': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/serve-index@1.9.4': dependencies: - '@types/express': 5.0.5 + '@types/express': 5.0.6 '@types/serve-static@1.15.10': dependencies: '@types/http-errors': 2.0.5 - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/send': 0.17.6 + '@types/serve-static@2.2.0': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 24.10.4 + '@types/sockjs@0.3.36': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ssh2-streams@0.1.13': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ssh2@0.5.52': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ssh2-streams': 0.1.13 '@types/ssh2@1.15.5': @@ -16953,7 +16925,7 @@ snapshots: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 24.10.1 + '@types/node': 24.10.4 form-data: 4.0.5 '@types/supercluster@7.1.3': @@ -16967,7 +16939,7 @@ snapshots: '@types/through@0.0.33': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/ua-parser-js@0.7.39': {} @@ -16981,24 +16953,23 @@ snapshots: '@types/ws@8.18.1': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 '@types/yargs-parser@21.0.3': {} - '@types/yargs@17.0.34': + '@types/yargs@17.0.35': dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.48.0 - eslint: 9.39.1(jiti@2.6.1) - graphemer: 1.4.0 + '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.50.0 + '@typescript-eslint/type-utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.0 + eslint: 9.39.2(jiti@2.6.1) ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -17006,56 +16977,56 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/scope-manager': 8.50.0 + '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.50.0 debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.2(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.48.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.50.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.9.3) - '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) + '@typescript-eslint/types': 8.50.0 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.48.0': + '@typescript-eslint/scope-manager@8.50.0': dependencies: - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/visitor-keys': 8.50.0 - '@typescript-eslint/tsconfig-utils@8.48.0(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.50.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.2(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.48.0': {} + '@typescript-eslint/types@8.50.0': {} - '@typescript-eslint/typescript-estree@8.48.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.50.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.48.0(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.9.3) - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/project-service': 8.50.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.50.0(typescript@5.9.3) + '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/visitor-keys': 8.50.0 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 @@ -17065,60 +17036,60 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3)': + '@typescript-eslint/utils@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3) - eslint: 9.39.1(jiti@2.6.1) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.50.0 + '@typescript-eslint/types': 8.50.0 + '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.48.0': + '@typescript-eslint/visitor-keys@8.50.0': dependencies: - '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/types': 8.50.0 eslint-visitor-keys: 4.2.1 '@ungap/structured-clone@1.3.0': {} - '@vercel/oidc@3.0.3': {} + '@vercel/oidc@3.0.5': {} - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - ast-v8-to-istanbul: 0.3.3 + ast-v8-to-istanbul: 0.3.8 debug: 4.4.3 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 - istanbul-reports: 3.1.7 + istanbul-reports: 3.2.0 magic-string: 0.30.21 magicast: 0.3.5 std-env: 3.10.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) transitivePeerDependencies: - supports-color '@vitest/expect@3.2.4': dependencies: - '@types/chai': 5.2.2 + '@types/chai': 5.2.3 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 - chai: 5.2.0 + chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2))': + '@vitest/mocker@3.2.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -17128,7 +17099,7 @@ snapshots: dependencies: '@vitest/utils': 3.2.4 pathe: 2.0.3 - strip-literal: 3.0.0 + strip-literal: 3.1.0 '@vitest/snapshot@3.2.4': dependencies: @@ -17138,12 +17109,12 @@ snapshots: '@vitest/spy@3.2.4': dependencies: - tinyspy: 4.0.3 + tinyspy: 4.0.4 '@vitest/utils@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 - loupe: 3.1.4 + loupe: 3.2.1 tinyrainbow: 2.0.0 '@webassemblyjs/ast@1.14.1': @@ -17230,10 +17201,10 @@ snapshots: dependencies: '@namnode/store': 0.1.0 - '@zoom-image/svelte@0.3.8(svelte@5.45.2)': + '@zoom-image/svelte@0.3.8(svelte@5.43.3)': dependencies: '@zoom-image/core': 0.41.4 - svelte: 5.45.2 + svelte: 5.43.3 abab@2.0.6: optional: true @@ -17295,13 +17266,13 @@ snapshots: clean-stack: 2.2.0 indent-string: 4.0.0 - ai@5.0.82(zod@4.1.12): + ai@5.0.113(zod@4.2.1): dependencies: - '@ai-sdk/gateway': 2.0.3(zod@4.1.12) + '@ai-sdk/gateway': 2.0.21(zod@4.2.1) '@ai-sdk/provider': 2.0.0 - '@ai-sdk/provider-utils': 3.0.14(zod@4.1.12) + '@ai-sdk/provider-utils': 3.0.19(zod@4.2.1) '@opentelemetry/api': 1.9.0 - zod: 4.1.12 + zod: 4.2.1 ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: @@ -17334,27 +17305,27 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - algoliasearch-helper@3.26.0(algoliasearch@5.41.0): + algoliasearch-helper@3.26.1(algoliasearch@5.46.0): dependencies: '@algolia/events': 4.0.1 - algoliasearch: 5.41.0 + algoliasearch: 5.46.0 - algoliasearch@5.41.0: + algoliasearch@5.46.0: dependencies: - '@algolia/abtesting': 1.7.0 - '@algolia/client-abtesting': 5.41.0 - '@algolia/client-analytics': 5.41.0 - '@algolia/client-common': 5.41.0 - '@algolia/client-insights': 5.41.0 - '@algolia/client-personalization': 5.41.0 - '@algolia/client-query-suggestions': 5.41.0 - '@algolia/client-search': 5.41.0 - '@algolia/ingestion': 1.41.0 - '@algolia/monitoring': 1.41.0 - '@algolia/recommend': 5.41.0 - '@algolia/requester-browser-xhr': 5.41.0 - '@algolia/requester-fetch': 5.41.0 - '@algolia/requester-node-http': 5.41.0 + '@algolia/abtesting': 1.12.0 + '@algolia/client-abtesting': 5.46.0 + '@algolia/client-analytics': 5.46.0 + '@algolia/client-common': 5.46.0 + '@algolia/client-insights': 5.46.0 + '@algolia/client-personalization': 5.46.0 + '@algolia/client-query-suggestions': 5.46.0 + '@algolia/client-search': 5.46.0 + '@algolia/ingestion': 1.46.0 + '@algolia/monitoring': 1.46.0 + '@algolia/recommend': 5.46.0 + '@algolia/requester-browser-xhr': 5.46.0 + '@algolia/requester-fetch': 5.46.0 + '@algolia/requester-node-http': 5.46.0 ansi-align@3.0.1: dependencies: @@ -17391,7 +17362,7 @@ snapshots: append-field@1.0.0: {} - aproba@2.0.0: {} + aproba@2.1.0: {} archiver-utils@5.0.2: dependencies: @@ -17414,6 +17385,7 @@ snapshots: zip-stream: 6.0.1 transitivePeerDependencies: - bare-abort-controller + - react-native-b4a are-we-there-yet@2.0.0: dependencies: @@ -17454,7 +17426,7 @@ snapshots: dependencies: '@mdn/browser-compat-data': 5.7.6 - ast-v8-to-istanbul@0.3.3: + ast-v8-to-istanbul@0.3.8: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -17478,19 +17450,18 @@ snapshots: dependencies: immediate: 3.3.0 - autoprefixer@10.4.22(postcss@8.5.6): + autoprefixer@10.4.23(postcss@8.5.6): dependencies: - browserslist: 4.28.0 - caniuse-lite: 1.0.30001757 + browserslist: 4.28.1 + caniuse-lite: 1.0.30001760 fraction.js: 5.3.4 - normalize-range: 0.1.2 picocolors: 1.1.1 postcss: 8.5.6 postcss-value-parser: 4.2.0 axobject-query@4.1.0: {} - b4a@1.6.7: {} + b4a@1.7.3: {} babel-loader@9.2.1(@babel/core@7.28.5)(webpack@5.103.0): dependencies: @@ -17516,7 +17487,7 @@ snapshots: dependencies: '@babel/core': 7.28.5 '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) - core-js-compat: 3.46.0 + core-js-compat: 3.47.0 transitivePeerDependencies: - supports-color @@ -17544,6 +17515,7 @@ snapshots: fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller + - react-native-b4a optional: true bare-os@3.6.2: @@ -17561,6 +17533,7 @@ snapshots: bare-events: 2.8.2 transitivePeerDependencies: - bare-abort-controller + - react-native-b4a optional: true bare-url@2.3.2: @@ -17572,9 +17545,9 @@ snapshots: base64id@2.0.0: {} - baseline-browser-mapping@2.8.31: {} + baseline-browser-mapping@2.9.7: {} - batch-cluster@15.0.1: {} + batch-cluster@16.0.0: {} batch@0.6.1: {} @@ -17596,15 +17569,15 @@ snapshots: binary-extensions@2.3.0: {} - bits-ui@2.14.4(@internationalized/date@3.10.0)(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2): + bits-ui@2.14.4(@internationalized/date@3.10.0)(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3): 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.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2) - svelte: 5.45.2 - svelte-toolbelt: 0.10.6(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2) + runed: 0.35.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3) + svelte: 5.43.3 + svelte-toolbelt: 0.10.6(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3) tabbable: 6.3.0 transitivePeerDependencies: - '@sveltejs/kit' @@ -17638,7 +17611,7 @@ snapshots: content-type: 1.0.5 debug: 4.4.3 http-errors: 2.0.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.1 on-finished: 2.4.1 qs: 6.14.0 raw-body: 3.0.2 @@ -17653,7 +17626,7 @@ snapshots: boolbase@1.0.0: {} - bowser@2.13.0: {} + bowser@2.13.1: {} boxen@6.2.1: dependencies: @@ -17690,13 +17663,13 @@ snapshots: dependencies: fill-range: 7.1.1 - browserslist@4.28.0: + browserslist@4.28.1: dependencies: - baseline-browser-mapping: 2.8.31 - caniuse-lite: 1.0.30001757 - electron-to-chromium: 1.5.260 + baseline-browser-mapping: 2.9.7 + caniuse-lite: 1.0.30001760 + electron-to-chromium: 1.5.267 node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.28.0) + update-browserslist-db: 1.2.2(browserslist@4.28.1) buffer-crc32@1.0.0: {} @@ -17719,7 +17692,7 @@ snapshots: builtin-modules@5.0.0: {} - bullmq@5.65.0: + bullmq@5.66.0: dependencies: cron-parser: 4.9.0 ioredis: 5.8.2 @@ -17809,17 +17782,17 @@ snapshots: caniuse-api@3.0.0: dependencies: - browserslist: 4.28.0 - caniuse-lite: 1.0.30001757 + browserslist: 4.28.1 + caniuse-lite: 1.0.30001760 lodash.memoize: 4.1.2 lodash.uniq: 4.5.0 - caniuse-lite@1.0.30001757: {} + caniuse-lite@1.0.30001760: {} canvas@2.11.2: dependencies: '@mapbox/node-pre-gyp': 1.0.11 - nan: 2.23.1 + nan: 2.24.0 simple-get: 3.1.1 transitivePeerDependencies: - encoding @@ -17829,7 +17802,7 @@ snapshots: canvas@2.11.2(encoding@0.1.13): dependencies: '@mapbox/node-pre-gyp': 1.0.11(encoding@0.1.13) - nan: 2.23.1 + nan: 2.24.0 simple-get: 3.1.1 transitivePeerDependencies: - encoding @@ -17838,12 +17811,12 @@ snapshots: ccount@2.0.1: {} - chai@5.2.0: + chai@5.3.3: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.4 + loupe: 3.2.1 pathval: 2.0.1 chalk@4.1.2: @@ -18150,13 +18123,13 @@ snapshots: serialize-javascript: 6.0.2 webpack: 5.103.0 - core-js-compat@3.46.0: + core-js-compat@3.47.0: dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 - core-js-pure@3.46.0: {} + core-js-pure@3.47.0: {} - core-js@3.46.0: {} + core-js@3.47.0: {} core-util-is@1.0.3: {} @@ -18177,7 +18150,7 @@ snapshots: cpu-features@0.0.10: dependencies: buildcheck: 0.0.7 - nan: 2.23.1 + nan: 2.24.0 optional: true crc-32@1.2.2: {} @@ -18191,7 +18164,7 @@ snapshots: dependencies: luxon: 3.7.2 - cron@4.3.3: + cron@4.3.5: dependencies: '@types/luxon': 3.7.1 luxon: 3.7.2 @@ -18209,7 +18182,7 @@ snapshots: css-blank-pseudo@7.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 css-declaration-sorter@7.3.0(postcss@8.5.6): dependencies: @@ -18217,9 +18190,9 @@ snapshots: css-has-pseudo@7.0.3(postcss@8.5.6): dependencies: - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 css-loader@6.11.0(webpack@5.103.0): @@ -18285,14 +18258,14 @@ snapshots: csscolorparser@1.0.3: {} - cssdb@8.4.2: {} + cssdb@8.5.2: {} cssesc@3.0.0: {} cssnano-preset-advanced@6.1.2(postcss@8.5.6): dependencies: - autoprefixer: 10.4.22(postcss@8.5.6) - browserslist: 4.28.0 + autoprefixer: 10.4.23(postcss@8.5.6) + browserslist: 4.28.1 cssnano-preset-default: 6.1.2(postcss@8.5.6) postcss: 8.5.6 postcss-discard-unused: 6.0.5(postcss@8.5.6) @@ -18302,7 +18275,7 @@ snapshots: cssnano-preset-default@6.1.2(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 css-declaration-sorter: 7.3.0(postcss@8.5.6) cssnano-utils: 4.0.2(postcss@8.5.6) postcss: 8.5.6 @@ -18359,12 +18332,6 @@ snapshots: cssom: 0.3.8 optional: true - cssstyle@4.6.0: - dependencies: - '@asamuzakjp/css-color': 3.2.0 - rrweb-cssom: 0.8.0 - optional: true - csstype@3.2.3: {} d3-array@3.2.4: @@ -18387,12 +18354,6 @@ snapshots: whatwg-url: 11.0.0 optional: true - data-urls@5.0.0: - dependencies: - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - optional: true - debounce@1.2.1: {} debounce@2.2.0: {} @@ -18436,12 +18397,12 @@ snapshots: deepmerge@4.3.1: {} - default-browser-id@5.0.0: {} + default-browser-id@5.0.1: {} - default-browser@5.2.1: + default-browser@5.4.0: dependencies: bundle-name: 4.1.0 - default-browser-id: 5.0.0 + default-browser-id: 5.0.1 defaults@1.0.4: dependencies: @@ -18492,7 +18453,7 @@ snapshots: transitivePeerDependencies: - supports-color - devalue@5.5.0: {} + devalue@5.6.1: {} devlop@1.1.0: dependencies: @@ -18539,7 +18500,7 @@ snapshots: dockerode@4.0.9: dependencies: '@balena/dockerignore': 1.0.2 - '@grpc/grpc-js': 1.14.2 + '@grpc/grpc-js': 1.14.3 '@grpc/proto-loader': 0.7.15 docker-modem: 5.0.6 protobufjs: 7.5.4 @@ -18648,7 +18609,7 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.260: {} + electron-to-chromium@1.5.267: {} emoji-regex@10.6.0: {} @@ -18662,8 +18623,6 @@ snapshots: emoticon@4.1.0: {} - encodeurl@1.0.2: {} - encodeurl@2.0.0: {} encoding@0.1.13: @@ -18692,7 +18651,7 @@ snapshots: engine.io@6.6.4: dependencies: '@types/cors': 2.8.19 - '@types/node': 24.10.1 + '@types/node': 24.10.4 accepts: 1.3.8 base64id: 2.0.0 cookie: 0.7.2 @@ -18705,7 +18664,7 @@ snapshots: - supports-color - utf-8-validate - enhanced-resolve@5.18.3: + enhanced-resolve@5.18.4: dependencies: graceful-fs: 4.2.11 tapable: 2.3.0 @@ -18835,34 +18794,34 @@ snapshots: '@esbuild/win32-ia32': 0.25.12 '@esbuild/win32-x64': 0.25.12 - esbuild@0.27.0: + esbuild@0.27.1: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.0 - '@esbuild/android-arm': 0.27.0 - '@esbuild/android-arm64': 0.27.0 - '@esbuild/android-x64': 0.27.0 - '@esbuild/darwin-arm64': 0.27.0 - '@esbuild/darwin-x64': 0.27.0 - '@esbuild/freebsd-arm64': 0.27.0 - '@esbuild/freebsd-x64': 0.27.0 - '@esbuild/linux-arm': 0.27.0 - '@esbuild/linux-arm64': 0.27.0 - '@esbuild/linux-ia32': 0.27.0 - '@esbuild/linux-loong64': 0.27.0 - '@esbuild/linux-mips64el': 0.27.0 - '@esbuild/linux-ppc64': 0.27.0 - '@esbuild/linux-riscv64': 0.27.0 - '@esbuild/linux-s390x': 0.27.0 - '@esbuild/linux-x64': 0.27.0 - '@esbuild/netbsd-arm64': 0.27.0 - '@esbuild/netbsd-x64': 0.27.0 - '@esbuild/openbsd-arm64': 0.27.0 - '@esbuild/openbsd-x64': 0.27.0 - '@esbuild/openharmony-arm64': 0.27.0 - '@esbuild/sunos-x64': 0.27.0 - '@esbuild/win32-arm64': 0.27.0 - '@esbuild/win32-ia32': 0.27.0 - '@esbuild/win32-x64': 0.27.0 + '@esbuild/aix-ppc64': 0.27.1 + '@esbuild/android-arm': 0.27.1 + '@esbuild/android-arm64': 0.27.1 + '@esbuild/android-x64': 0.27.1 + '@esbuild/darwin-arm64': 0.27.1 + '@esbuild/darwin-x64': 0.27.1 + '@esbuild/freebsd-arm64': 0.27.1 + '@esbuild/freebsd-x64': 0.27.1 + '@esbuild/linux-arm': 0.27.1 + '@esbuild/linux-arm64': 0.27.1 + '@esbuild/linux-ia32': 0.27.1 + '@esbuild/linux-loong64': 0.27.1 + '@esbuild/linux-mips64el': 0.27.1 + '@esbuild/linux-ppc64': 0.27.1 + '@esbuild/linux-riscv64': 0.27.1 + '@esbuild/linux-s390x': 0.27.1 + '@esbuild/linux-x64': 0.27.1 + '@esbuild/netbsd-arm64': 0.27.1 + '@esbuild/netbsd-x64': 0.27.1 + '@esbuild/openbsd-arm64': 0.27.1 + '@esbuild/openbsd-x64': 0.27.1 + '@esbuild/openharmony-arm64': 0.27.1 + '@esbuild/sunos-x64': 0.27.1 + '@esbuild/win32-arm64': 0.27.1 + '@esbuild/win32-ia32': 0.27.1 + '@esbuild/win32-x64': 0.27.1 escalade@3.2.0: {} @@ -18885,37 +18844,37 @@ snapshots: source-map: 0.6.1 optional: true - eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)): + eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)): dependencies: - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.2(jiti@2.6.1) - eslint-plugin-compat@6.0.2(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-compat@6.0.2(eslint@9.39.2(jiti@2.6.1)): dependencies: '@mdn/browser-compat-data': 5.7.6 ast-metadata-inferer: 0.8.1 - browserslist: 4.28.0 - caniuse-lite: 1.0.30001757 - eslint: 9.39.1(jiti@2.6.1) + browserslist: 4.28.1 + caniuse-lite: 1.0.30001760 + eslint: 9.39.2(jiti@2.6.1) find-up: 5.0.0 globals: 15.15.0 lodash.memoize: 4.1.2 semver: 7.7.3 - eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.1(jiti@2.6.1)))(eslint@9.39.1(jiti@2.6.1))(prettier@3.7.1): + eslint-plugin-prettier@5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(prettier@3.7.4): dependencies: - eslint: 9.39.1(jiti@2.6.1) - prettier: 3.7.1 + eslint: 9.39.2(jiti@2.6.1) + prettier: 3.7.4 prettier-linter-helpers: 1.0.0 synckit: 0.11.11 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 10.1.8(eslint@9.39.1(jiti@2.6.1)) + eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.6.1)) - eslint-plugin-svelte@3.13.0(eslint@9.39.1(jiti@2.6.1))(svelte@5.45.2): + eslint-plugin-svelte@3.13.1(eslint@9.39.2(jiti@2.6.1))(svelte@5.43.3): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@jridgewell/sourcemap-codec': 1.5.5 - eslint: 9.39.1(jiti@2.6.1) + eslint: 9.39.2(jiti@2.6.1) esutils: 2.0.3 globals: 16.5.0 known-css-properties: 0.37.0 @@ -18923,22 +18882,22 @@ snapshots: postcss-load-config: 3.1.4(postcss@8.5.6) postcss-safe-parser: 7.0.1(postcss@8.5.6) semver: 7.7.3 - svelte-eslint-parser: 1.4.0(svelte@5.45.2) + svelte-eslint-parser: 1.4.1(svelte@5.43.3) optionalDependencies: - svelte: 5.45.2 + svelte: 5.43.3 transitivePeerDependencies: - ts-node - eslint-plugin-unicorn@62.0.0(eslint@9.39.1(jiti@2.6.1)): + eslint-plugin-unicorn@62.0.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@eslint/plugin-kit': 0.4.1 change-case: 5.4.4 ci-info: 4.3.1 clean-regexp: 1.0.0 - core-js-compat: 3.46.0 - eslint: 9.39.1(jiti@2.6.1) + core-js-compat: 3.47.0 + eslint: 9.39.2(jiti@2.6.1) esquery: 1.6.0 find-up-simple: 1.0.1 globals: 16.5.0 @@ -18965,15 +18924,15 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1(jiti@2.6.1): + eslint@9.39.2(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(jiti@2.6.1)) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.2(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.2 '@eslint/config-array': 0.21.1 '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.39.1 + '@eslint/eslintrc': 3.3.3 + '@eslint/js': 9.39.2 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.7 '@humanwhocodes/module-importer': 1.0.1 @@ -19027,7 +18986,7 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.2.0: + esrap@2.2.1: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -19082,13 +19041,13 @@ snapshots: eta@2.2.0: {} - eta@4.0.1: {} + eta@4.5.0: {} etag@1.8.1: {} eval@0.1.8: dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 require-like: 0.1.2 event-emitter@0.3.5: @@ -19122,23 +19081,23 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 - exiftool-vendored.exe@13.42.0: + exiftool-vendored.exe@13.44.0: optional: true - exiftool-vendored.pl@13.42.0: {} + exiftool-vendored.pl@13.44.0: {} - exiftool-vendored@33.5.0: + exiftool-vendored@34.1.0: dependencies: '@photostructure/tz-lookup': 11.3.0 '@types/luxon': 3.7.1 - batch-cluster: 15.0.1 - exiftool-vendored.pl: 13.42.0 + batch-cluster: 16.0.0 + exiftool-vendored.pl: 13.44.0 he: 1.2.0 luxon: 3.7.2 optionalDependencies: - exiftool-vendored.exe: 13.42.0 + exiftool-vendored.exe: 13.44.0 - expect-type@1.2.1: {} + expect-type@1.3.0: {} exponential-backoff@3.1.3: {} @@ -19168,8 +19127,8 @@ snapshots: qs: 6.14.0 range-parser: 1.2.1 safe-buffer: 5.2.1 - send: 0.19.1 - serve-static: 1.16.2 + send: 0.19.2 + serve-static: 1.16.3 setprototypeof: 1.2.0 statuses: 2.0.2 type-is: 1.6.18 @@ -19202,15 +19161,15 @@ snapshots: qs: 6.14.0 range-parser: 1.2.1 router: 2.2.0 - send: 1.2.0 - serve-static: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 statuses: 2.0.2 type-is: 2.0.1 vary: 1.1.2 transitivePeerDependencies: - supports-color - express@5.2.0: + express@5.2.1: dependencies: accepts: 2.0.0 body-parser: 2.2.1 @@ -19235,15 +19194,15 @@ snapshots: qs: 6.14.0 range-parser: 1.2.1 router: 2.2.0 - send: 1.2.0 - serve-static: 2.2.0 + send: 1.2.1 + serve-static: 2.2.1 statuses: 2.0.2 type-is: 2.0.1 vary: 1.1.2 transitivePeerDependencies: - supports-color - exsolve@1.0.7: {} + exsolve@1.0.8: {} ext@1.7.0: dependencies: @@ -19255,7 +19214,7 @@ snapshots: extend@3.0.2: {} - fabric@6.9.0: + fabric@6.9.1: optionalDependencies: canvas: 2.11.2 jsdom: 20.0.3(canvas@2.11.2) @@ -19296,7 +19255,7 @@ snapshots: fast-xml-parser@5.2.5: dependencies: - strnum: 2.1.1 + strnum: 2.1.2 fastq@1.19.1: dependencies: @@ -19417,7 +19376,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.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17))): + fork-ts-checker-webpack-plugin@9.1.0(typescript@5.9.3)(webpack@5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17))): dependencies: '@babel/code-frame': 7.27.1 chalk: 4.1.2 @@ -19432,7 +19391,7 @@ snapshots: semver: 7.7.3 tapable: 2.3.0 typescript: 5.9.3 - webpack: 5.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17)) + webpack: 5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17)) form-data-encoder@2.1.4: {} @@ -19448,7 +19407,7 @@ snapshots: formidable@3.5.4: dependencies: - '@paralleldrive/cuid2': 2.2.2 + '@paralleldrive/cuid2': 2.3.1 dezalgo: 1.0.4 once: 1.4.0 @@ -19498,7 +19457,7 @@ snapshots: gauge@3.0.2: dependencies: - aproba: 2.0.0 + aproba: 2.1.0 color-support: 1.1.3 console-control-strings: 1.1.0 has-unicode: 2.0.1 @@ -19514,8 +19473,8 @@ snapshots: geo-tz@8.1.4: dependencies: - '@turf/boolean-point-in-polygon': 7.2.0 - '@turf/helpers': 7.2.0 + '@turf/boolean-point-in-polygon': 7.3.1 + '@turf/helpers': 7.3.1 geobuf: 3.0.2 pbf: 3.3.0 @@ -19586,7 +19545,7 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@11.0.3: + glob@11.1.0: dependencies: foreground-child: 3.3.1 jackspeak: 4.1.1 @@ -19661,8 +19620,6 @@ snapshots: graceful-fs@4.2.11: {} - graphemer@1.4.0: {} - gray-matter@4.0.3: dependencies: js-yaml: 3.14.2 @@ -19687,9 +19644,9 @@ snapshots: optionalDependencies: uglify-js: 3.19.3 - happy-dom@20.0.10: + happy-dom@20.0.11: dependencies: - '@types/node': 20.19.24 + '@types/node': 20.19.27 '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.0 @@ -19749,9 +19706,9 @@ snapshots: '@types/unist': 3.0.3 '@ungap/structured-clone': 1.3.0 hast-util-from-parse5: 8.0.3 - hast-util-to-parse5: 8.0.0 + hast-util-to-parse5: 8.0.1 html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.0 + mdast-util-to-hast: 13.2.1 parse5: 7.3.0 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 @@ -19791,7 +19748,7 @@ snapshots: mdast-util-mdxjs-esm: 2.0.1 property-information: 7.1.0 space-separated-tokens: 2.0.2 - style-to-js: 1.1.18 + style-to-js: 1.1.21 unist-util-position: 5.0.0 zwitch: 2.0.4 transitivePeerDependencies: @@ -19811,18 +19768,18 @@ snapshots: mdast-util-mdxjs-esm: 2.0.1 property-information: 7.1.0 space-separated-tokens: 2.0.2 - style-to-js: 1.1.18 + style-to-js: 1.1.21 unist-util-position: 5.0.0 vfile-message: 4.0.3 transitivePeerDependencies: - supports-color - hast-util-to-parse5@8.0.0: + hast-util-to-parse5@8.0.1: dependencies: '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 devlop: 1.1.0 - property-information: 6.5.0 + property-information: 7.1.0 space-separated-tokens: 2.0.2 web-namespaces: 2.0.1 zwitch: 2.0.4 @@ -19891,11 +19848,6 @@ snapshots: whatwg-encoding: 2.0.0 optional: true - html-encoding-sniffer@4.0.0: - dependencies: - whatwg-encoding: 3.1.1 - optional: true - html-escaper@2.0.2: {} html-minifier-terser@6.1.0: @@ -19906,7 +19858,7 @@ snapshots: he: 1.2.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.44.0 + terser: 5.44.1 html-minifier-terser@7.2.0: dependencies: @@ -19916,7 +19868,7 @@ snapshots: entities: 4.5.0 param-case: 3.0.4 relateurl: 0.2.7 - terser: 5.44.0 + terser: 5.44.1 html-tags@3.3.1: {} @@ -19930,7 +19882,7 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.4(webpack@5.103.0): + html-webpack-plugin@5.6.5(webpack@5.103.0): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -19978,14 +19930,6 @@ snapshots: statuses: 1.5.0 toidentifier: 1.0.1 - http-errors@2.0.0: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - http-errors@2.0.1: dependencies: depd: 2.0.0 @@ -20068,7 +20012,7 @@ snapshots: safer-buffer: 2.1.2 optional: true - iconv-lite@0.7.0: + iconv-lite@0.7.1: dependencies: safer-buffer: 2.1.2 @@ -20123,13 +20067,11 @@ snapshots: ini@2.0.0: {} - inline-style-parser@0.2.4: {} - inline-style-parser@0.2.7: {} - inquirer@8.2.7(@types/node@24.10.1): + inquirer@8.2.7(@types/node@24.10.4): dependencies: - '@inquirer/external-editor': 1.0.3(@types/node@24.10.1) + '@inquirer/external-editor': 1.0.3(@types/node@24.10.4) ansi-escapes: 4.3.2 chalk: 4.1.2 cli-cursor: 3.1.0 @@ -20174,11 +20116,11 @@ snapshots: transitivePeerDependencies: - supports-color - ip-address@10.0.1: {} + ip-address@10.1.0: {} ipaddr.js@1.9.1: {} - ipaddr.js@2.2.0: {} + ipaddr.js@2.3.0: {} is-alphabetical@2.0.1: {} @@ -20323,7 +20265,7 @@ snapshots: transitivePeerDependencies: - supports-color - istanbul-reports@3.1.7: + istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 @@ -20343,7 +20285,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 24.10.1 + '@types/node': 24.10.4 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -20351,13 +20293,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -20378,7 +20320,7 @@ snapshots: jose@5.10.0: {} - jose@6.1.0: {} + jose@6.1.3: {} js-tokens@4.0.0: {} @@ -20393,6 +20335,42 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@20.0.3(canvas@2.11.2(encoding@0.1.13)): + dependencies: + abab: 2.0.6 + acorn: 8.15.0 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.6.0 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.5 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.18.3 + xml-name-validator: 4.0.0 + optionalDependencies: + canvas: 2.11.2(encoding@0.1.13) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + optional: true + jsdom@20.0.3(canvas@2.11.2): dependencies: abab: 2.0.6 @@ -20409,7 +20387,7 @@ snapshots: http-proxy-agent: 5.0.0 https-proxy-agent: 5.0.1 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.22 + nwsapi: 2.2.23 parse5: 7.3.0 saxes: 6.0.0 symbol-tree: 3.2.4 @@ -20429,66 +20407,6 @@ snapshots: - utf-8-validate optional: true - jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)): - dependencies: - cssstyle: 4.6.0 - data-urls: 5.0.0 - decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.22 - parse5: 7.3.0 - rrweb-cssom: 0.8.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 5.1.2 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - ws: 8.18.3 - xml-name-validator: 5.0.0 - optionalDependencies: - canvas: 2.11.2(encoding@0.1.13) - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - optional: true - - jsdom@26.1.0(canvas@2.11.2): - dependencies: - cssstyle: 4.6.0 - data-urls: 5.0.0 - decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.22 - parse5: 7.3.0 - rrweb-cssom: 0.8.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 5.1.2 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - ws: 8.18.3 - xml-name-validator: 5.0.0 - optionalDependencies: - canvas: 2.11.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - optional: true - jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -20515,9 +20433,9 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - jsonwebtoken@9.0.2: + jsonwebtoken@9.0.3: dependencies: - jws: 3.2.2 + jws: 4.0.1 lodash.includes: 4.3.0 lodash.isboolean: 3.0.3 lodash.isinteger: 4.0.4 @@ -20532,15 +20450,15 @@ snapshots: justified-layout@4.1.0: {} - jwa@1.4.2: + jwa@2.0.1: dependencies: buffer-equal-constant-time: 1.0.1 ecdsa-sig-formatter: 1.0.11 safe-buffer: 5.2.1 - jws@3.2.2: + jws@4.0.1: dependencies: - jwa: 1.4.2 + jwa: 2.0.1 safe-buffer: 5.2.1 kdbush@3.0.0: {} @@ -20754,7 +20672,7 @@ snapshots: dependencies: js-tokens: 4.0.0 - loupe@3.1.4: {} + loupe@3.2.1: {} lower-case@2.0.2: dependencies: @@ -20845,7 +20763,7 @@ snapshots: tinyqueue: 2.0.3 vt-pbf: 3.1.3 - maplibre-gl@5.13.0: + maplibre-gl@5.14.0: dependencies: '@mapbox/geojson-rewind': 0.5.2 '@mapbox/jsonlint-lines-primitives': 2.0.2 @@ -20854,9 +20772,9 @@ snapshots: '@mapbox/unitbezier': 0.0.1 '@mapbox/vector-tile': 2.0.4 '@mapbox/whoots-js': 3.1.0 - '@maplibre/maplibre-gl-style-spec': 24.3.1 - '@maplibre/mlt': 1.1.0 - '@maplibre/vt-pbf': 4.0.3 + '@maplibre/maplibre-gl-style-spec': 24.4.1 + '@maplibre/mlt': 1.1.2 + '@maplibre/vt-pbf': 4.2.0 '@types/geojson': 7946.0.16 '@types/geojson-vt': 3.2.5 '@types/supercluster': 7.1.3 @@ -20883,7 +20801,7 @@ snapshots: marked@15.0.12: {} - marked@16.4.1: {} + marked@16.4.2: {} math-intrinsics@1.1.0: {} @@ -21047,7 +20965,7 @@ snapshots: '@types/mdast': 4.0.4 unist-util-is: 6.0.1 - mdast-util-to-hast@13.2.0: + mdast-util-to-hast@13.2.1: dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 @@ -21087,7 +21005,7 @@ snapshots: dependencies: fs-monkey: 1.1.0 - memfs@4.50.0: + memfs@4.51.1: dependencies: '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) @@ -21590,7 +21508,7 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nan@2.23.1: + nan@2.24.0: optional: true nanoid@3.3.11: {} @@ -21614,16 +21532,16 @@ snapshots: neo-async@2.6.2: {} - nest-commander@3.20.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(@types/inquirer@8.2.11)(@types/node@24.10.1)(typescript@5.9.3): + nest-commander@3.20.1(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9)(@types/inquirer@8.2.12)(@types/node@24.10.4)(typescript@5.9.3): dependencies: '@fig/complete-commander': 3.2.0(commander@11.1.0) '@golevelup/nestjs-discovery': 5.0.0(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.9) '@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(@nestjs/websockets@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) - '@types/inquirer': 8.2.11 + '@types/inquirer': 8.2.12 commander: 11.1.0 cosmiconfig: 8.3.6(typescript@5.9.3) - inquirer: 8.2.7(@types/node@24.10.1) + inquirer: 8.2.7(@types/node@24.10.4) transitivePeerDependencies: - '@types/node' - typescript @@ -21648,7 +21566,7 @@ snapshots: '@nestjs/common': 11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.9(@nestjs/common@11.1.9(class-transformer@0.5.1)(class-validator@0.14.3)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.9)(@nestjs/websockets@11.1.9)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@opentelemetry/api': 1.9.0 - '@opentelemetry/host-metrics': 0.36.0(@opentelemetry/api@1.9.0) + '@opentelemetry/host-metrics': 0.36.2(@opentelemetry/api@1.9.0) response-time: 2.3.4 tslib: 2.8.1 @@ -21687,7 +21605,7 @@ snapshots: optionalDependencies: encoding: 0.1.13 - node-forge@1.3.1: {} + node-forge@1.3.3: {} node-gyp-build-optional-packages@5.2.2: dependencies: @@ -21729,8 +21647,6 @@ snapshots: normalize-path@3.0.0: {} - normalize-range@0.1.2: {} - normalize-url@8.1.0: {} not@0.1.0: {} @@ -21760,7 +21676,7 @@ snapshots: schema-utils: 3.3.0 webpack: 5.103.0 - nwsapi@2.2.22: + nwsapi@2.2.23: optional: true nypm@0.6.0: @@ -21771,7 +21687,7 @@ snapshots: pkg-types: 2.3.0 tinyexec: 0.3.2 - oauth4webapi@3.8.2: {} + oauth4webapi@3.8.3: {} object-assign@4.1.1: {} @@ -21794,13 +21710,13 @@ snapshots: obuf@1.1.2: {} - oidc-provider@9.5.2: + oidc-provider@9.6.0: dependencies: '@koa/cors': 5.0.0 - '@koa/router': 14.0.0 + '@koa/router': 15.1.0(koa@3.1.1) debug: 4.4.3 - eta: 4.0.1 - jose: 6.1.0 + eta: 4.5.0 + jose: 6.1.3 jsesc: 3.1.0 koa: 3.1.1 nanoid: 5.1.6 @@ -21829,7 +21745,7 @@ snapshots: open@10.2.0: dependencies: - default-browser: 5.2.1 + default-browser: 5.4.0 define-lazy-prop: 3.0.0 is-inside-container: 1.0.0 wsl-utils: 0.1.0 @@ -21844,8 +21760,8 @@ snapshots: openid-client@6.8.1: dependencies: - jose: 6.1.0 - oauth4webapi: 3.8.2 + jose: 6.1.3 + oauth4webapi: 3.8.3 optionator@0.9.4: dependencies: @@ -22101,7 +22017,7 @@ snapshots: pkg-types@2.3.0: dependencies: confbox: 0.2.2 - exsolve: 1.0.7 + exsolve: 1.0.8 pathe: 2.0.3 playwright-core@1.57.0: {} @@ -22134,7 +22050,7 @@ snapshots: postcss-attribute-case-insensitive@7.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-calc@9.0.1(postcss@8.5.6): dependencies: @@ -22170,7 +22086,7 @@ snapshots: postcss-colormin@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 caniuse-api: 3.0.0 colord: 2.9.3 postcss: 8.5.6 @@ -22178,7 +22094,7 @@ snapshots: postcss-convert-values@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -22205,12 +22121,12 @@ snapshots: '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-dir-pseudo-class@9.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-discard-comments@6.0.2(postcss@8.5.6): dependencies: @@ -22243,12 +22159,12 @@ snapshots: postcss-focus-visible@10.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-focus-within@9.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-font-variant@5.0.0(postcss@8.5.6): dependencies: @@ -22329,7 +22245,7 @@ snapshots: postcss-merge-rules@6.1.1(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 caniuse-api: 3.0.0 cssnano-utils: 4.0.2(postcss@8.5.6) postcss: 8.5.6 @@ -22349,7 +22265,7 @@ snapshots: postcss-minify-params@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 cssnano-utils: 4.0.2(postcss@8.5.6) postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -22367,13 +22283,13 @@ snapshots: dependencies: icss-utils: 5.1.0(postcss@8.5.6) postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 postcss-modules-scope@3.2.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-modules-values@4.0.0(postcss@8.5.6): dependencies: @@ -22387,10 +22303,10 @@ snapshots: postcss-nesting@13.0.2(postcss@8.5.6): dependencies: - '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.0) - '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) + '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-normalize-charset@6.0.2(postcss@8.5.6): dependencies: @@ -22423,7 +22339,7 @@ snapshots: postcss-normalize-unicode@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 postcss: 8.5.6 postcss-value-parser: 4.2.0 @@ -22461,7 +22377,7 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-preset-env@10.4.0(postcss@8.5.6): + postcss-preset-env@10.5.0(postcss@8.5.6): dependencies: '@csstools/postcss-alpha-function': 1.0.1(postcss@8.5.6) '@csstools/postcss-cascade-layers': 5.0.2(postcss@8.5.6) @@ -22490,21 +22406,23 @@ snapshots: '@csstools/postcss-nested-calc': 4.0.0(postcss@8.5.6) '@csstools/postcss-normalize-display-values': 4.0.0(postcss@8.5.6) '@csstools/postcss-oklab-function': 4.0.12(postcss@8.5.6) + '@csstools/postcss-position-area-property': 1.0.0(postcss@8.5.6) '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.6) '@csstools/postcss-random-function': 2.0.1(postcss@8.5.6) '@csstools/postcss-relative-color-syntax': 3.0.12(postcss@8.5.6) '@csstools/postcss-scope-pseudo-class': 4.0.1(postcss@8.5.6) '@csstools/postcss-sign-functions': 1.1.4(postcss@8.5.6) '@csstools/postcss-stepped-value-functions': 4.0.9(postcss@8.5.6) + '@csstools/postcss-system-ui-font-family': 1.0.0(postcss@8.5.6) '@csstools/postcss-text-decoration-shorthand': 4.0.3(postcss@8.5.6) '@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.6) '@csstools/postcss-unset-value': 4.0.0(postcss@8.5.6) - autoprefixer: 10.4.22(postcss@8.5.6) - browserslist: 4.28.0 + autoprefixer: 10.4.23(postcss@8.5.6) + browserslist: 4.28.1 css-blank-pseudo: 7.0.1(postcss@8.5.6) css-has-pseudo: 7.0.3(postcss@8.5.6) css-prefers-color-scheme: 10.0.0(postcss@8.5.6) - cssdb: 8.4.2 + cssdb: 8.5.2 postcss: 8.5.6 postcss-attribute-case-insensitive: 7.0.1(postcss@8.5.6) postcss-clamp: 4.1.0(postcss@8.5.6) @@ -22535,7 +22453,7 @@ snapshots: postcss-pseudo-class-any-link@10.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-reduce-idents@6.0.3(postcss@8.5.6): dependencies: @@ -22544,7 +22462,7 @@ snapshots: postcss-reduce-initial@6.1.0(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 caniuse-api: 3.0.0 postcss: 8.5.6 @@ -22568,14 +22486,14 @@ snapshots: postcss-selector-not@8.0.1(postcss@8.5.6): dependencies: postcss: 8.5.6 - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 postcss-selector-parser@6.1.2: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-selector-parser@7.1.0: + postcss-selector-parser@7.1.1: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 @@ -22630,21 +22548,21 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-organize-imports@4.3.0(prettier@3.7.1)(typescript@5.9.3): + prettier-plugin-organize-imports@4.3.0(prettier@3.7.4)(typescript@5.9.3): dependencies: - prettier: 3.7.1 + prettier: 3.7.4 typescript: 5.9.3 - prettier-plugin-sort-json@4.1.1(prettier@3.7.1): + prettier-plugin-sort-json@4.1.1(prettier@3.7.4): dependencies: - prettier: 3.7.1 + prettier: 3.7.4 - prettier-plugin-svelte@3.4.0(prettier@3.7.1)(svelte@5.45.2): + prettier-plugin-svelte@3.4.1(prettier@3.7.4)(svelte@5.43.3): dependencies: - prettier: 3.7.1 - svelte: 5.45.2 + prettier: 3.7.4 + svelte: 5.43.3 - prettier@3.7.1: {} + prettier@3.7.4: {} pretty-error@4.0.0: dependencies: @@ -22703,8 +22621,6 @@ snapshots: dependencies: xtend: 4.0.2 - property-information@6.5.0: {} - property-information@7.1.0: {} proto-list@1.2.4: {} @@ -22721,7 +22637,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 24.10.1 + '@types/node': 24.10.4 long: 5.3.2 protocol-buffers-schema@3.6.0: {} @@ -22798,7 +22714,7 @@ snapshots: dependencies: bytes: 3.1.2 http-errors: 2.0.1 - iconv-lite: 0.7.0 + iconv-lite: 0.7.1 unpipe: 1.0.0 raw-loader@4.0.2(webpack@5.103.0): @@ -22820,9 +22736,9 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 - react-dom@19.2.0(react@19.2.0): + react-dom@19.2.3(react@19.2.3): dependencies: - react: 19.2.0 + react: 19.2.3 scheduler: 0.27.0 react-email@4.3.2: @@ -22833,7 +22749,7 @@ snapshots: commander: 13.1.0 debounce: 2.2.0 esbuild: 0.25.12 - glob: 11.0.3 + glob: 11.1.0 jiti: 2.4.2 log-symbols: 7.0.1 mime-types: 3.0.2 @@ -22902,7 +22818,7 @@ snapshots: dependencies: loose-envify: 1.4.0 - react@19.2.0: {} + react@19.2.3: {} read-cache@1.0.0: dependencies: @@ -23093,7 +23009,7 @@ snapshots: dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.0 + mdast-util-to-hast: 13.2.1 unified: 11.0.5 vfile: 6.0.3 @@ -23117,7 +23033,7 @@ snapshots: require-from-string@2.0.2: {} - require-in-the-middle@8.0.0: + require-in-the-middle@8.0.1: dependencies: debug: 4.4.3 module-details-from-path: 1.0.4 @@ -23179,41 +23095,41 @@ snapshots: robust-predicates@3.0.2: {} - rollup-plugin-visualizer@6.0.5(rollup@4.53.3): + rollup-plugin-visualizer@6.0.5(rollup@4.53.4): dependencies: open: 8.4.2 picomatch: 4.0.3 source-map: 0.7.6 yargs: 17.7.2 optionalDependencies: - rollup: 4.53.3 + rollup: 4.53.4 - rollup@4.53.3: + rollup@4.53.4: dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.3 - '@rollup/rollup-android-arm64': 4.53.3 - '@rollup/rollup-darwin-arm64': 4.53.3 - '@rollup/rollup-darwin-x64': 4.53.3 - '@rollup/rollup-freebsd-arm64': 4.53.3 - '@rollup/rollup-freebsd-x64': 4.53.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 - '@rollup/rollup-linux-arm-musleabihf': 4.53.3 - '@rollup/rollup-linux-arm64-gnu': 4.53.3 - '@rollup/rollup-linux-arm64-musl': 4.53.3 - '@rollup/rollup-linux-loong64-gnu': 4.53.3 - '@rollup/rollup-linux-ppc64-gnu': 4.53.3 - '@rollup/rollup-linux-riscv64-gnu': 4.53.3 - '@rollup/rollup-linux-riscv64-musl': 4.53.3 - '@rollup/rollup-linux-s390x-gnu': 4.53.3 - '@rollup/rollup-linux-x64-gnu': 4.53.3 - '@rollup/rollup-linux-x64-musl': 4.53.3 - '@rollup/rollup-openharmony-arm64': 4.53.3 - '@rollup/rollup-win32-arm64-msvc': 4.53.3 - '@rollup/rollup-win32-ia32-msvc': 4.53.3 - '@rollup/rollup-win32-x64-gnu': 4.53.3 - '@rollup/rollup-win32-x64-msvc': 4.53.3 + '@rollup/rollup-android-arm-eabi': 4.53.4 + '@rollup/rollup-android-arm64': 4.53.4 + '@rollup/rollup-darwin-arm64': 4.53.4 + '@rollup/rollup-darwin-x64': 4.53.4 + '@rollup/rollup-freebsd-arm64': 4.53.4 + '@rollup/rollup-freebsd-x64': 4.53.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.53.4 + '@rollup/rollup-linux-arm-musleabihf': 4.53.4 + '@rollup/rollup-linux-arm64-gnu': 4.53.4 + '@rollup/rollup-linux-arm64-musl': 4.53.4 + '@rollup/rollup-linux-loong64-gnu': 4.53.4 + '@rollup/rollup-linux-ppc64-gnu': 4.53.4 + '@rollup/rollup-linux-riscv64-gnu': 4.53.4 + '@rollup/rollup-linux-riscv64-musl': 4.53.4 + '@rollup/rollup-linux-s390x-gnu': 4.53.4 + '@rollup/rollup-linux-x64-gnu': 4.53.4 + '@rollup/rollup-linux-x64-musl': 4.53.4 + '@rollup/rollup-openharmony-arm64': 4.53.4 + '@rollup/rollup-win32-arm64-msvc': 4.53.4 + '@rollup/rollup-win32-ia32-msvc': 4.53.4 + '@rollup/rollup-win32-x64-gnu': 4.53.4 + '@rollup/rollup-win32-x64-msvc': 4.53.4 fsevents: 2.3.3 router@2.2.0: @@ -23226,9 +23142,6 @@ snapshots: transitivePeerDependencies: - supports-color - rrweb-cssom@0.8.0: - optional: true - rtlcss@4.3.0: dependencies: escalade: 3.2.0 @@ -23244,14 +23157,14 @@ snapshots: dependencies: queue-microtask: 1.2.3 - runed@0.35.1(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2): + runed@0.35.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3): dependencies: dequal: 2.0.3 esm-env: 1.2.2 lz-string: 1.5.0 - svelte: 5.45.2 + svelte: 5.43.3 optionalDependencies: - '@sveltejs/kit': 2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@sveltejs/kit': 2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) rw@1.3.3: {} @@ -23286,7 +23199,7 @@ snapshots: parse-srcset: 1.0.2 postcss: 8.5.6 - sax@1.4.1: {} + sax@1.4.3: {} saxes@6.0.0: dependencies: @@ -23330,7 +23243,7 @@ snapshots: selfsigned@2.4.1: dependencies: '@types/node-forge': 1.3.14 - node-forge: 1.3.1 + node-forge: 1.3.3 semver-diff@4.0.0: dependencies: @@ -23340,25 +23253,7 @@ snapshots: semver@7.7.3: {} - send@0.19.0: - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - - send@0.19.1: + send@0.19.2: dependencies: debug: 2.6.9 depd: 2.0.0 @@ -23367,16 +23262,16 @@ snapshots: escape-html: 1.0.3 etag: 1.8.1 fresh: 0.5.2 - http-errors: 2.0.0 + http-errors: 2.0.1 mime: 1.6.0 ms: 2.1.3 on-finished: 2.4.1 range-parser: 1.2.1 - statuses: 2.0.1 + statuses: 2.0.2 transitivePeerDependencies: - supports-color - send@1.2.0: + send@1.2.1: dependencies: debug: 4.4.3 encodeurl: 2.0.0 @@ -23418,21 +23313,21 @@ snapshots: transitivePeerDependencies: - supports-color - serve-static@1.16.2: + serve-static@1.16.3: dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 0.19.0 + send: 0.19.2 transitivePeerDependencies: - supports-color - serve-static@2.2.0: + serve-static@2.2.1: dependencies: encodeurl: 2.0.0 escape-html: 1.0.3 parseurl: 1.3.3 - send: 1.2.0 + send: 1.2.1 transitivePeerDependencies: - supports-color @@ -23576,7 +23471,7 @@ snapshots: '@types/node': 17.0.45 '@types/sax': 1.2.7 arg: 5.0.2 - sax: 1.4.1 + sax: 1.4.3 skin-tone@2.0.0: dependencies: @@ -23652,7 +23547,7 @@ snapshots: socks@2.8.7: dependencies: - ip-address: 10.0.1 + ip-address: 10.1.0 smart-buffer: 4.2.0 sort-css-media-queries@2.2.0: {} @@ -23701,7 +23596,7 @@ snapshots: sprintf-js@1.0.3: {} - sql-formatter@15.6.10: + sql-formatter@15.6.12: dependencies: argparse: 2.0.1 nearley: 2.20.1 @@ -23719,7 +23614,7 @@ snapshots: bcrypt-pbkdf: 1.0.2 optionalDependencies: cpu-features: 0.0.10 - nan: 2.23.1 + nan: 2.24.0 ssri@13.0.0: dependencies: @@ -23731,8 +23626,6 @@ snapshots: statuses@1.5.0: {} - statuses@2.0.1: {} - statuses@2.0.2: {} std-env@3.10.0: {} @@ -23750,6 +23643,7 @@ snapshots: text-decoder: 1.2.3 transitivePeerDependencies: - bare-abort-controller + - react-native-b4a string-width@4.2.3: dependencies: @@ -23812,23 +23706,19 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@3.0.0: + strip-literal@3.1.0: dependencies: js-tokens: 9.0.1 - strnum@2.1.1: {} + strnum@2.1.2: {} strtok3@10.3.4: dependencies: '@tokenizer/token': 0.3.0 - style-to-js@1.1.18: + style-to-js@1.1.21: dependencies: - style-to-object: 1.0.11 - - style-to-object@1.0.11: - dependencies: - inline-style-parser: 0.2.4 + style-to-object: 1.0.14 style-to-object@1.0.14: dependencies: @@ -23836,7 +23726,7 @@ snapshots: stylehacks@6.1.1(postcss@8.5.6): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 postcss: 8.5.6 postcss-selector-parser: 6.1.2 @@ -23889,28 +23779,28 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.45.2)(typescript@5.9.3): + svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.43.3)(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.45.2 + svelte: 5.43.3 typescript: 5.9.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.4.0(svelte@5.45.2): + svelte-eslint-parser@1.4.1(svelte@5.43.3): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 postcss: 8.5.6 postcss-scss: 4.0.9(postcss@8.5.6) - postcss-selector-parser: 7.1.0 + postcss-selector-parser: 7.1.1 optionalDependencies: - svelte: 5.45.2 + svelte: 5.43.3 svelte-gestures@5.2.2: {} @@ -23918,7 +23808,7 @@ snapshots: dependencies: highlight.js: 11.11.1 - svelte-i18n@4.0.1(svelte@5.45.2): + svelte-i18n@4.0.1(svelte@5.43.3): dependencies: cli-color: 2.0.4 deepmerge: 4.3.1 @@ -23926,36 +23816,36 @@ snapshots: estree-walker: 2.0.2 intl-messageformat: 10.7.18 sade: 1.8.1 - svelte: 5.45.2 + svelte: 5.43.3 tiny-glob: 0.2.9 - svelte-maplibre@1.2.5(svelte@5.45.2): + svelte-maplibre@1.2.5(svelte@5.43.3): dependencies: d3-geo: 3.1.1 dequal: 2.0.3 just-compare: 2.3.0 - maplibre-gl: 5.13.0 + maplibre-gl: 5.14.0 pmtiles: 3.2.1 - svelte: 5.45.2 + svelte: 5.43.3 - svelte-parse-markup@0.1.5(svelte@5.45.2): + svelte-parse-markup@0.1.5(svelte@5.43.3): dependencies: - svelte: 5.45.2 + svelte: 5.43.3 - svelte-persisted-store@0.12.0(svelte@5.45.2): + svelte-persisted-store@0.12.0(svelte@5.43.3): dependencies: - svelte: 5.45.2 + svelte: 5.43.3 - svelte-toolbelt@0.10.6(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2): + svelte-toolbelt@0.10.6(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3): dependencies: clsx: 2.1.1 - runed: 0.35.1(@sveltejs/kit@2.49.0(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)))(svelte@5.45.2) + runed: 0.35.1(@sveltejs/kit@2.49.2(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@6.2.1(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)))(svelte@5.43.3) style-to-object: 1.0.14 - svelte: 5.45.2 + svelte: 5.43.3 transitivePeerDependencies: - '@sveltejs/kit' - svelte@5.45.2: + svelte@5.43.3: dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -23965,9 +23855,8 @@ snapshots: aria-query: 5.3.2 axobject-query: 4.1.0 clsx: 2.1.1 - devalue: 5.5.0 esm-env: 1.2.2 - esrap: 2.2.0 + esrap: 2.2.1 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 @@ -23989,7 +23878,7 @@ snapshots: dependencies: '@scarf/scarf': 1.4.0 - swr@2.3.6(react@18.3.1): + swr@2.3.8(react@18.3.1): dependencies: dequal: 2.0.3 react: 18.3.1 @@ -24010,27 +23899,27 @@ snapshots: tailwind-merge@3.4.0: {} - tailwind-variants@3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.17): + tailwind-variants@3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.18): dependencies: - tailwindcss: 4.1.17 + tailwindcss: 4.1.18 optionalDependencies: tailwind-merge: 3.4.0 - tailwindcss-email-variants@3.0.5(tailwindcss@3.4.18(yaml@2.8.2)): + tailwindcss-email-variants@3.0.5(tailwindcss@3.4.19(yaml@2.8.2)): dependencies: - tailwindcss: 3.4.18(yaml@2.8.2) + tailwindcss: 3.4.19(yaml@2.8.2) - tailwindcss-mso@2.0.3(tailwindcss@3.4.18(yaml@2.8.2)): + tailwindcss-mso@2.0.3(tailwindcss@3.4.19(yaml@2.8.2)): dependencies: - tailwindcss: 3.4.18(yaml@2.8.2) + tailwindcss: 3.4.19(yaml@2.8.2) - tailwindcss-preset-email@1.4.1(tailwindcss@3.4.18(yaml@2.8.2)): + tailwindcss-preset-email@1.4.1(tailwindcss@3.4.19(yaml@2.8.2)): dependencies: - tailwindcss: 3.4.18(yaml@2.8.2) - tailwindcss-email-variants: 3.0.5(tailwindcss@3.4.18(yaml@2.8.2)) - tailwindcss-mso: 2.0.3(tailwindcss@3.4.18(yaml@2.8.2)) + tailwindcss: 3.4.19(yaml@2.8.2) + tailwindcss-email-variants: 3.0.5(tailwindcss@3.4.19(yaml@2.8.2)) + tailwindcss-mso: 2.0.3(tailwindcss@3.4.19(yaml@2.8.2)) - tailwindcss@3.4.18(yaml@2.8.2): + tailwindcss@3.4.19(yaml@2.8.2): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -24058,7 +23947,7 @@ snapshots: - tsx - yaml - tailwindcss@4.1.17: {} + tailwindcss@4.1.18: {} tapable@2.3.0: {} @@ -24079,6 +23968,7 @@ snapshots: transitivePeerDependencies: - bare-abort-controller - bare-buffer + - react-native-b4a tar-stream@2.2.0: dependencies: @@ -24090,11 +23980,12 @@ snapshots: tar-stream@3.1.7: dependencies: - b4a: 1.6.7 + b4a: 1.7.3 fast-fifo: 1.3.2 streamx: 2.23.0 transitivePeerDependencies: - bare-abort-controller + - react-native-b4a tar@6.2.1: dependencies: @@ -24113,27 +24004,27 @@ snapshots: minizlib: 3.1.0 yallist: 5.0.0 - terser-webpack-plugin@5.3.14(@swc/core@1.15.3(@swc/helpers@0.5.17))(webpack@5.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17))): + terser-webpack-plugin@5.3.16(@swc/core@1.15.5(@swc/helpers@0.5.17))(webpack@5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17))): 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.0 - webpack: 5.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17)) + terser: 5.44.1 + webpack: 5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17)) optionalDependencies: - '@swc/core': 1.15.3(@swc/helpers@0.5.17) + '@swc/core': 1.15.5(@swc/helpers@0.5.17) - terser-webpack-plugin@5.3.14(webpack@5.103.0): + terser-webpack-plugin@5.3.16(webpack@5.103.0): 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.0 + terser: 5.44.1 webpack: 5.103.0 - terser@5.44.0: + terser@5.44.1: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.15.0 @@ -24146,7 +24037,7 @@ snapshots: glob: 10.5.0 minimatch: 9.0.5 - testcontainers@11.9.0: + testcontainers@11.10.0: dependencies: '@balena/dockerignore': 1.0.2 '@types/dockerode': 3.3.47 @@ -24166,11 +24057,14 @@ snapshots: transitivePeerDependencies: - bare-abort-controller - bare-buffer + - react-native-b4a - supports-color text-decoder@1.2.3: dependencies: - b4a: 1.6.7 + b4a: 1.7.3 + transitivePeerDependencies: + - react-native-b4a text-encoding@0.6.4: {} @@ -24188,7 +24082,7 @@ snapshots: three@0.179.1: {} - three@0.180.0: {} + three@0.182.0: {} throttleit@2.1.0: {} @@ -24229,15 +24123,7 @@ snapshots: tinyrainbow@2.0.0: {} - tinyspy@4.0.3: {} - - tldts-core@6.1.86: - optional: true - - tldts@6.1.86: - dependencies: - tldts-core: 6.1.86 - optional: true + tinyspy@4.0.4: {} tmp@0.2.5: {} @@ -24268,11 +24154,6 @@ snapshots: url-parse: 1.5.10 optional: true - tough-cookie@5.1.2: - dependencies: - tldts: 6.1.86 - optional: true - tr46@0.0.3: {} tr46@3.0.0: @@ -24280,11 +24161,6 @@ snapshots: punycode: 2.3.1 optional: true - tr46@5.1.1: - dependencies: - punycode: 2.3.1 - optional: true - tree-dump@1.1.0(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -24312,7 +24188,7 @@ snapshots: tsconfig-paths-webpack-plugin@4.2.0: dependencies: chalk: 4.1.2 - enhanced-resolve: 5.18.3 + enhanced-resolve: 5.18.4 tapable: 2.3.0 tsconfig-paths: 4.2.0 @@ -24357,13 +24233,13 @@ snapshots: typedarray@0.0.6: {} - typescript-eslint@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3): + typescript-eslint@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - eslint: 9.39.1(jiti@2.6.1) + '@typescript-eslint/eslint-plugin': 8.50.0(@typescript-eslint/parser@8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.50.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.50.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -24372,7 +24248,7 @@ snapshots: ua-is-frozen@0.1.2: {} - ua-parser-js@2.0.6: + ua-parser-js@2.0.7: dependencies: detect-europe-js: 0.1.2 is-standalone-pwa: 0.1.1 @@ -24497,10 +24373,10 @@ snapshots: unpipe@1.0.0: {} - unplugin-swc@1.5.9(@swc/core@1.15.3(@swc/helpers@0.5.17))(rollup@4.53.3): + unplugin-swc@1.5.9(@swc/core@1.15.5(@swc/helpers@0.5.17))(rollup@4.53.4): dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.53.3) - '@swc/core': 1.15.3(@swc/helpers@0.5.17) + '@rollup/pluginutils': 5.3.0(rollup@4.53.4) + '@swc/core': 1.15.5(@swc/helpers@0.5.17) load-tsconfig: 0.2.5 unplugin: 2.3.11 transitivePeerDependencies: @@ -24513,9 +24389,9 @@ snapshots: picomatch: 4.0.3 webpack-virtual-modules: 0.6.2 - update-browserslist-db@1.1.4(browserslist@4.28.0): + update-browserslist-db@1.2.2(browserslist@4.28.1): dependencies: - browserslist: 4.28.0 + browserslist: 4.28.1 escalade: 3.2.0 picocolors: 1.1.1 @@ -24536,6 +24412,8 @@ snapshots: semver-diff: 4.0.0 xdg-basedir: 5.1.0 + uplot@1.6.32: {} + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -24625,22 +24503,22 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-imagetools@9.0.2(rollup@4.53.3): + vite-imagetools@9.0.2(rollup@4.53.4): dependencies: - '@rollup/pluginutils': 5.3.0(rollup@4.53.3) + '@rollup/pluginutils': 5.3.0(rollup@4.53.4) imagetools-core: 9.1.0 sharp: 0.34.5 transitivePeerDependencies: - rollup - supports-color - vite-node@3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2): + vite-node@3.2.4(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(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.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) transitivePeerDependencies: - '@types/node' - jiti @@ -24655,54 +24533,54 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)): + vite-tsconfig-paths@5.1.4(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) optionalDependencies: - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) transitivePeerDependencies: - supports-color - typescript - vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2): + vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2): dependencies: - esbuild: 0.25.12 + esbuild: 0.27.1 fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 postcss: 8.5.6 - rollup: 4.53.3 + rollup: 4.53.4 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.10.4 fsevents: 2.3.3 jiti: 2.6.1 lightningcss: 1.30.2 - terser: 5.44.0 + terser: 5.44.1 yaml: 2.8.2 - vitefu@1.1.1(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)): + vitefu@1.1.1(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)): optionalDependencies: - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) - vitest-fetch-mock@0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)): + vitest-fetch-mock@0.4.5(vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)): dependencies: - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2): dependencies: - '@types/chai': 5.2.2 + '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 - chai: 5.2.0 + chai: 5.3.3 debug: 4.4.3 - expect-type: 1.2.1 + expect-type: 1.3.0 magic-string: 0.30.21 pathe: 2.0.3 picomatch: 4.0.3 @@ -24712,14 +24590,14 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 24.10.1 - happy-dom: 20.0.10 - jsdom: 26.1.0(canvas@2.11.2(encoding@0.1.13)) + '@types/node': 24.10.4 + happy-dom: 20.0.11 + jsdom: 20.0.3(canvas@2.11.2(encoding@0.1.13)) transitivePeerDependencies: - jiti - less @@ -24734,19 +24612,19 @@ snapshots: - tsx - yaml - vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@26.1.0(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2): + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.10.4)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@20.0.3(canvas@2.11.2))(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2): dependencies: - '@types/chai': 5.2.2 + '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2)) + '@vitest/mocker': 3.2.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 '@vitest/spy': 3.2.4 '@vitest/utils': 3.2.4 - chai: 5.2.0 + chai: 5.3.3 debug: 4.4.3 - expect-type: 1.2.1 + expect-type: 1.3.0 magic-string: 0.30.21 pathe: 2.0.3 picomatch: 4.0.3 @@ -24756,14 +24634,14 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) - vite-node: 3.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(yaml@2.8.2) + vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) + vite-node: 3.2.4(@types/node@24.10.4)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/debug': 4.1.12 - '@types/node': 24.10.1 - happy-dom: 20.0.10 - jsdom: 26.1.0(canvas@2.11.2) + '@types/node': 24.10.4 + happy-dom: 20.0.11 + jsdom: 20.0.3(canvas@2.11.2) transitivePeerDependencies: - jiti - less @@ -24789,11 +24667,6 @@ snapshots: xml-name-validator: 4.0.0 optional: true - w3c-xmlserializer@5.0.0: - dependencies: - xml-name-validator: 5.0.0 - optional: true - watchpack@2.4.4: dependencies: glob-to-regexp: 0.4.1 @@ -24837,7 +24710,7 @@ snapshots: webpack-dev-middleware@7.4.5(webpack@5.103.0): dependencies: colorette: 2.0.20 - memfs: 4.50.0 + memfs: 4.51.1 mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 @@ -24864,7 +24737,7 @@ snapshots: express: 4.22.1 graceful-fs: 4.2.11 http-proxy-middleware: 2.0.9(@types/express@4.17.25) - ipaddr.js: 2.2.0 + ipaddr.js: 2.3.0 launch-editor: 2.12.0 open: 10.2.0 p-retry: 6.2.1 @@ -24911,9 +24784,9 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.28.0 + browserslist: 4.28.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.3 + enhanced-resolve: 5.18.4 es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -24925,7 +24798,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.14(webpack@5.103.0) + terser-webpack-plugin: 5.3.16(webpack@5.103.0) watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: @@ -24933,7 +24806,7 @@ snapshots: - esbuild - uglify-js - webpack@5.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17)): + webpack@5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17)): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.8 @@ -24943,9 +24816,9 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.15.0 acorn-import-phases: 1.0.4(acorn@8.15.0) - browserslist: 4.28.0 + browserslist: 4.28.1 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.18.3 + enhanced-resolve: 5.18.4 es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 @@ -24957,7 +24830,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 4.3.3 tapable: 2.3.0 - terser-webpack-plugin: 5.3.14(@swc/core@1.15.3(@swc/helpers@0.5.17))(webpack@5.103.0(@swc/core@1.15.3(@swc/helpers@0.5.17))) + terser-webpack-plugin: 5.3.16(@swc/core@1.15.5(@swc/helpers@0.5.17))(webpack@5.103.0(@swc/core@1.15.5(@swc/helpers@0.5.17))) watchpack: 2.4.4 webpack-sources: 3.3.3 transitivePeerDependencies: @@ -24990,28 +24863,14 @@ snapshots: iconv-lite: 0.6.3 optional: true - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - optional: true - whatwg-mimetype@3.0.0: {} - whatwg-mimetype@4.0.0: - optional: true - whatwg-url@11.0.0: dependencies: tr46: 3.0.0 webidl-conversions: 7.0.0 optional: true - whatwg-url@14.2.0: - dependencies: - tr46: 5.1.1 - webidl-conversions: 7.0.0 - optional: true - whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -25091,14 +24950,11 @@ snapshots: xml-js@1.6.11: dependencies: - sax: 1.4.1 + sax: 1.4.3 xml-name-validator@4.0.0: optional: true - xml-name-validator@5.0.0: - optional: true - xmlchars@2.2.0: optional: true @@ -25167,7 +25023,7 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 - zod@4.1.12: {} + zod@4.2.1: {} zwitch@1.0.5: {} diff --git a/server/Dockerfile b/server/Dockerfile index 267253ccd9..918658e19f 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -50,13 +50,15 @@ RUN --mount=type=cache,id=pnpm-cli,target=/buildcache/pnpm-store \ FROM builder AS plugins +ARG TARGETPLATFORM + COPY --from=ghcr.io/jdx/mise:2025.11.3@sha256:ac26f5978c0e2783f3e68e58ce75eddb83e41b89bf8747c503bac2aa9baf22c5 /usr/local/bin/mise /usr/local/bin/mise WORKDIR /usr/src/app COPY ./plugins/mise.toml ./plugins/ ENV MISE_TRUSTED_CONFIG_PATHS=/usr/src/app/plugins/mise.toml ENV MISE_DATA_DIR=/buildcache/mise -RUN --mount=type=cache,id=mise-tools,target=/buildcache/mise \ +RUN --mount=type=cache,id=mise-tools-${TARGETPLATFORM},target=/buildcache/mise \ mise install --cd plugins COPY ./plugins ./plugins/ @@ -66,7 +68,7 @@ RUN --mount=type=cache,id=pnpm-plugins,target=/buildcache/pnpm-store \ --mount=type=bind,source=.pnpmfile.cjs,target=.pnpmfile.cjs \ --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \ --mount=type=bind,source=pnpm-workspace.yaml,target=pnpm-workspace.yaml \ - --mount=type=cache,id=mise-tools,target=/buildcache/mise \ + --mount=type=cache,id=mise-tools-${TARGETPLATFORM},target=/buildcache/mise \ cd plugins && mise run build FROM ghcr.io/immich-app/base-server-prod:202511261514@sha256:c04c1c38dd90e53455b180aedf93c3c63474c8d20ffe2c6d7a3a61a2181e6d29 diff --git a/server/package.json b/server/package.json index 915e45c116..045bc950bd 100644 --- a/server/package.json +++ b/server/package.json @@ -69,8 +69,8 @@ "compression": "^1.8.0", "cookie": "^1.0.2", "cookie-parser": "^1.4.7", - "cron": "4.3.3", - "exiftool-vendored": "^33.0.0", + "cron": "4.3.5", + "exiftool-vendored": "^34.0.0", "express": "^5.1.0", "fast-glob": "^3.3.2", "fluent-ffmpeg": "^2.1.2", @@ -134,7 +134,7 @@ "@types/luxon": "^3.6.2", "@types/mock-fs": "^4.13.1", "@types/multer": "^2.0.0", - "@types/node": "^24.10.1", + "@types/node": "^24.10.3", "@types/nodemailer": "^7.0.0", "@types/picomatch": "^4.0.0", "@types/pngjs": "^6.0.5", @@ -153,7 +153,7 @@ "mock-fs": "^5.2.0", "node-gyp": "^12.0.0", "pngjs": "^7.0.0", - "prettier": "^3.0.2", + "prettier": "^3.7.4", "prettier-plugin-organize-imports": "^4.0.0", "sql-formatter": "^15.0.0", "supertest": "^7.1.0", diff --git a/server/src/queries/asset.job.repository.sql b/server/src/queries/asset.job.repository.sql index d6dc564458..d1b4e5a72e 100644 --- a/server/src/queries/asset.job.repository.sql +++ b/server/src/queries/asset.job.repository.sql @@ -369,6 +369,7 @@ select "asset"."livePhotoVideoId", "asset"."encodedVideoPath", "asset"."originalPath", + "asset"."isOffline", to_json("asset_exif") as "exifInfo", ( select diff --git a/server/src/repositories/asset-job.repository.ts b/server/src/repositories/asset-job.repository.ts index dc6e9e2573..de994b08cd 100644 --- a/server/src/repositories/asset-job.repository.ts +++ b/server/src/repositories/asset-job.repository.ts @@ -232,6 +232,7 @@ export class AssetJobRepository { 'asset.livePhotoVideoId', 'asset.encodedVideoPath', 'asset.originalPath', + 'asset.isOffline', ]) .$call(withExif) .select(withFacesAndPeople) diff --git a/server/src/repositories/metadata.repository.ts b/server/src/repositories/metadata.repository.ts index 32882de0e0..1334d1220f 100644 --- a/server/src/repositories/metadata.repository.ts +++ b/server/src/repositories/metadata.repository.ts @@ -89,6 +89,7 @@ export class MetadataRepository { // Enable exiftool LFS to parse metadata for files larger than 2GB. readArgs: ['-api', 'largefilesupport=1'], writeArgs: ['-api', 'largefilesupport=1', '-overwrite_original'], + taskTimeoutMillis: 2 * 60 * 1000, }); constructor(private logger: LoggingRepository) { diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 8c646e45b9..878721e0a7 100755 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -585,8 +585,6 @@ describe(AssetService.name, () => { '/uploads/user-id/webp/path.ext', '/uploads/user-id/thumbs/path.jpg', '/uploads/user-id/fullsize/path.webp', - assetWithFace.encodedVideoPath, // this value is null - undefined, // no sidecar path assetWithFace.originalPath, ], }, @@ -648,8 +646,6 @@ describe(AssetService.name, () => { '/uploads/user-id/webp/path.ext', '/uploads/user-id/thumbs/path.jpg', '/uploads/user-id/fullsize/path.webp', - undefined, - undefined, 'fake_path/asset_1.jpeg', ], }, @@ -676,8 +672,6 @@ describe(AssetService.name, () => { '/uploads/user-id/webp/path.ext', '/uploads/user-id/thumbs/path.jpg', '/uploads/user-id/fullsize/path.webp', - undefined, - undefined, 'fake_path/asset_1.jpeg', ], }, diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 0a9aa7f355..32c6526394 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -363,11 +363,11 @@ export class AssetService extends BaseService { const { fullsizeFile, previewFile, thumbnailFile, sidecarFile } = getAssetFiles(asset.files ?? []); const files = [thumbnailFile?.path, previewFile?.path, fullsizeFile?.path, asset.encodedVideoPath]; - if (deleteOnDisk) { + if (deleteOnDisk && !asset.isOffline) { files.push(sidecarFile?.path, asset.originalPath); } - await this.jobRepository.queue({ name: JobName.FileDelete, data: { files } }); + await this.jobRepository.queue({ name: JobName.FileDelete, data: { files: files.filter(Boolean) } }); return JobStatus.Success; } diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index 46d6fe7abc..c0f930d3a6 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -1034,7 +1034,10 @@ describe(MetadataService.name, () => { }); it('should use Duration from exif', async () => { - mocks.assetJob.getForMetadataExtraction.mockResolvedValue(assetStub.image); + mocks.assetJob.getForMetadataExtraction.mockResolvedValue({ + ...assetStub.image, + originalPath: '/original/path.webp', + }); mockReadTags({ Duration: 123 }, {}); await sut.handleMetadataExtraction({ id: assetStub.image.id }); @@ -1046,6 +1049,7 @@ describe(MetadataService.name, () => { it('should prefer Duration from exif over sidecar', async () => { mocks.assetJob.getForMetadataExtraction.mockResolvedValue({ ...assetStub.image, + originalPath: '/original/path.webp', files: [ { id: 'some-id', @@ -1063,6 +1067,16 @@ describe(MetadataService.name, () => { expect(mocks.asset.update).toHaveBeenCalledWith(expect.objectContaining({ duration: '00:02:03.000' })); }); + it('should ignore all Duration tags for definitely static images', async () => { + mocks.assetJob.getForMetadataExtraction.mockResolvedValue(assetStub.imageDng); + mockReadTags({ Duration: 123 }, { Duration: 456 }); + + await sut.handleMetadataExtraction({ id: assetStub.imageDng.id }); + + expect(mocks.metadata.readTags).toHaveBeenCalledTimes(1); + expect(mocks.asset.update).toHaveBeenCalledWith(expect.objectContaining({ duration: null })); + }); + it('should ignore Duration from exif for videos', async () => { mocks.assetJob.getForMetadataExtraction.mockResolvedValue(assetStub.video); mockReadTags({ Duration: 123 }, {}); diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 4d6d4c190f..a1267604b2 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -32,6 +32,7 @@ import { BaseService } from 'src/services/base.service'; import { JobItem, JobOf } from 'src/types'; import { getAssetFiles } from 'src/utils/asset.util'; import { isAssetChecksumConstraint } from 'src/utils/database'; +import { mimeTypes } from 'src/utils/mime-types'; import { isFaceImportEnabled } from 'src/utils/misc'; import { upsertTags } from 'src/utils/tag'; @@ -486,7 +487,8 @@ export class MetadataService extends BaseService { } // prefer duration from video tags - if (videoTags) { + // don't save duration if asset is definitely not an animated image (see e.g. CR3 with Duration: 1s) + if (videoTags || !mimeTypes.isPossiblyAnimatedImage(asset.originalPath)) { delete mediaTags.Duration; } diff --git a/server/src/sql-tools/decorators/column.decorator.ts b/server/src/sql-tools/decorators/column.decorator.ts index adb3d0ed59..e5a0eb52f8 100644 --- a/server/src/sql-tools/decorators/column.decorator.ts +++ b/server/src/sql-tools/decorators/column.decorator.ts @@ -2,7 +2,7 @@ import { asOptions } from 'src/sql-tools/helpers'; import { register } from 'src/sql-tools/register'; import { ColumnStorage, ColumnType, DatabaseEnum } from 'src/sql-tools/types'; -export type ColumnValue = null | boolean | string | number | object | Date | (() => string); +export type ColumnValue = null | boolean | string | number | Array | object | Date | (() => string); export type ColumnBaseOptions = { name?: string; diff --git a/server/src/sql-tools/helpers.ts b/server/src/sql-tools/helpers.ts index 2ef35ce9ba..e0daf8262f 100644 --- a/server/src/sql-tools/helpers.ts +++ b/server/src/sql-tools/helpers.ts @@ -39,6 +39,10 @@ export const fromColumnValue = (columnValue?: ColumnValue) => { return `'${value.toISOString()}'`; } + if (Array.isArray(value)) { + return "'{}'"; + } + return `'${String(value)}'`; }; diff --git a/server/src/sql-tools/schema-diff.spec.ts b/server/src/sql-tools/schema-diff.spec.ts index fe249b4e29..f45fb98bd3 100644 --- a/server/src/sql-tools/schema-diff.spec.ts +++ b/server/src/sql-tools/schema-diff.spec.ts @@ -394,6 +394,20 @@ describe(schemaDiff.name, () => { expect(diff.items).toEqual([]); }); + + it('should support arrays, ignoring types', () => { + const diff = schemaDiff( + fromColumn({ name: 'column1', type: 'character varying', isArray: true, default: "'{}'" }), + fromColumn({ + name: 'column1', + type: 'character varying', + isArray: true, + default: "'{}'::character varying[]", + }), + ); + + expect(diff.items).toEqual([]); + }); }); }); diff --git a/server/src/utils/mime-types.spec.ts b/server/src/utils/mime-types.spec.ts index 12587eff37..c09f3a381b 100644 --- a/server/src/utils/mime-types.spec.ts +++ b/server/src/utils/mime-types.spec.ts @@ -152,6 +152,26 @@ describe('mimeTypes', () => { } }); + describe('animated image', () => { + for (const img of ['a.avif', 'a.gif', 'a.webp']) { + it('should identify animated image mime types as such', () => { + expect(mimeTypes.isPossiblyAnimatedImage(img)).toBeTruthy(); + }); + } + + for (const img of ['a.cr3', 'a.jpg', 'a.tiff']) { + it('should identify static image mime types as such', () => { + expect(mimeTypes.isPossiblyAnimatedImage(img)).toBeFalsy(); + }); + } + + for (const extension of Object.keys(mimeTypes.video)) { + it('should not identify video mime types as animated', () => { + expect(mimeTypes.isPossiblyAnimatedImage(extension)).toBeFalsy(); + }); + } + }); + describe('video', () => { it('should contain only lowercase mime types', () => { const keys = Object.keys(mimeTypes.video); diff --git a/server/src/utils/mime-types.ts b/server/src/utils/mime-types.ts index 6b9392146d..d15c1f078c 100644 --- a/server/src/utils/mime-types.ts +++ b/server/src/utils/mime-types.ts @@ -64,6 +64,11 @@ const image: Record = { '.tiff': ['image/tiff'], }; +const possiblyAnimatedImageExtensions = new Set(['.avif', '.gif', '.heic', '.heif', '.jxl', '.png', '.webp']); +const possiblyAnimatedImage: Record = Object.fromEntries( + Object.entries(image).filter(([key]) => possiblyAnimatedImageExtensions.has(key)), +); + const extensionOverrides: Record = { 'image/jpeg': '.jpg', }; @@ -119,6 +124,7 @@ export const mimeTypes = { isAsset: (filename: string) => isType(filename, image) || isType(filename, video), isImage: (filename: string) => isType(filename, image), isWebSupportedImage: (filename: string) => isType(filename, webSupportedImage), + isPossiblyAnimatedImage: (filename: string) => isType(filename, possiblyAnimatedImage), isProfile: (filename: string) => isType(filename, profile), isSidecar: (filename: string) => isType(filename, sidecar), isVideo: (filename: string) => isType(filename, video), diff --git a/server/test/medium/specs/services/asset.service.spec.ts b/server/test/medium/specs/services/asset.service.spec.ts index e9246c62b1..13bc1ca9a9 100644 --- a/server/test/medium/specs/services/asset.service.spec.ts +++ b/server/test/medium/specs/services/asset.service.spec.ts @@ -2,13 +2,16 @@ import { Kysely } from 'kysely'; import { AssetFileType, JobName, SharedLinkType } from 'src/enum'; import { AccessRepository } from 'src/repositories/access.repository'; import { AlbumRepository } from 'src/repositories/album.repository'; +import { AssetJobRepository } from 'src/repositories/asset-job.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 { SharedLinkAssetRepository } from 'src/repositories/shared-link-asset.repository'; import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; import { StackRepository } from 'src/repositories/stack.repository'; import { StorageRepository } from 'src/repositories/storage.repository'; +import { UserRepository } from 'src/repositories/user.repository'; import { DB } from 'src/schema'; import { AssetService } from 'src/services/asset.service'; import { newMediumService } from 'test/medium.factory'; @@ -20,8 +23,16 @@ let defaultDatabase: Kysely; const setup = (db?: Kysely) => { return newMediumService(AssetService, { database: db || defaultDatabase, - real: [AssetRepository, AlbumRepository, AccessRepository, SharedLinkAssetRepository, StackRepository], - mock: [LoggingRepository, JobRepository, StorageRepository], + real: [ + AssetRepository, + AssetJobRepository, + AlbumRepository, + AccessRepository, + SharedLinkAssetRepository, + StackRepository, + UserRepository, + ], + mock: [EventRepository, LoggingRepository, JobRepository, StorageRepository], }); }; @@ -210,4 +221,51 @@ describe(AssetService.name, () => { }); }); }); + + describe('delete', () => { + it('should delete asset', async () => { + const { sut, ctx } = setup(); + ctx.getMock(EventRepository).emit.mockResolvedValue(); + ctx.getMock(JobRepository).queue.mockResolvedValue(); + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id }); + const thumbnailPath = '/path/to/thumbnail.jpg'; + const previewPath = '/path/to/preview.jpg'; + const sidecarPath = '/path/to/sidecar.xmp'; + await Promise.all([ + ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Thumbnail, path: thumbnailPath }), + ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Preview, path: previewPath }), + ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Sidecar, path: sidecarPath }), + ]); + + await sut.handleAssetDeletion({ id: asset.id, deleteOnDisk: true }); + + expect(ctx.getMock(JobRepository).queue).toHaveBeenCalledWith({ + name: JobName.FileDelete, + data: { files: [thumbnailPath, previewPath, sidecarPath, asset.originalPath] }, + }); + }); + + it('should not delete offline assets', async () => { + const { sut, ctx } = setup(); + ctx.getMock(EventRepository).emit.mockResolvedValue(); + ctx.getMock(JobRepository).queue.mockResolvedValue(); + const { user } = await ctx.newUser(); + const { asset } = await ctx.newAsset({ ownerId: user.id, isOffline: true }); + const thumbnailPath = '/path/to/thumbnail.jpg'; + const previewPath = '/path/to/preview.jpg'; + await Promise.all([ + ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Thumbnail, path: thumbnailPath }), + ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Preview, path: previewPath }), + ctx.newAssetFile({ assetId: asset.id, type: AssetFileType.Sidecar, path: `/path/to/sidecar.xmp` }), + ]); + + await sut.handleAssetDeletion({ id: asset.id, deleteOnDisk: true }); + + expect(ctx.getMock(JobRepository).queue).toHaveBeenCalledWith({ + name: JobName.FileDelete, + data: { files: [thumbnailPath, previewPath] }, + }); + }); + }); }); diff --git a/server/test/sql-tools/column-default-array.stub.ts b/server/test/sql-tools/column-default-array.stub.ts new file mode 100644 index 0000000000..b5e9b7d04a --- /dev/null +++ b/server/test/sql-tools/column-default-array.stub.ts @@ -0,0 +1,40 @@ +import { Column, DatabaseSchema, Table } from 'src/sql-tools'; + +@Table() +export class Table1 { + @Column({ type: 'character varying', array: true, default: [] }) + column1!: string[]; +} + +export const description = 'should register a table with a column with a default value (array)'; +export const schema: DatabaseSchema = { + databaseName: 'postgres', + schemaName: 'public', + functions: [], + enums: [], + extensions: [], + parameters: [], + overrides: [], + tables: [ + { + name: 'table1', + columns: [ + { + name: 'column1', + tableName: 'table1', + type: 'character varying', + nullable: false, + isArray: true, + primary: false, + synchronize: true, + default: "'{}'", + }, + ], + indexes: [], + triggers: [], + constraints: [], + synchronize: true, + }, + ], + warnings: [], +}; diff --git a/web/package.json b/web/package.json index 72be145acb..893fdab31f 100644 --- a/web/package.json +++ b/web/package.json @@ -9,7 +9,7 @@ "build:stats": "BUILD_STATS=true vite build", "package": "svelte-kit package", "preview": "vite preview", - "check:svelte": "svelte-check --no-tsconfig --fail-on-warnings", + "check:svelte": "svelte-check --no-tsconfig --fail-on-warnings --compiler-warnings 'state_referenced_locally:ignore'", "check:typescript": "tsc --noEmit", "check:watch": "pnpm run check:svelte --watch", "check:code": "pnpm run format && pnpm run lint && pnpm run check:svelte && pnpm run check:typescript", @@ -28,7 +28,7 @@ "@formatjs/icu-messageformat-parser": "^2.9.8", "@immich/justified-layout-wasm": "^0.4.3", "@immich/sdk": "file:../open-api/typescript-sdk", - "@immich/ui": "^0.49.2", + "@immich/ui": "^0.50.1", "@mapbox/mapbox-gl-rtl-text": "0.2.3", "@mdi/js": "^7.4.47", "@photo-sphere-viewer/core": "^5.14.0", @@ -61,7 +61,8 @@ "svelte-maplibre": "^1.2.5", "svelte-persisted-store": "^0.12.0", "tabbable": "^6.2.0", - "thumbhash": "^0.1.1" + "thumbhash": "^0.1.1", + "uplot": "^1.6.32" }, "devDependencies": { "@eslint/js": "^9.36.0", @@ -92,12 +93,12 @@ "factory.ts": "^1.4.1", "globals": "^16.0.0", "happy-dom": "^20.0.0", - "prettier": "^3.4.2", + "prettier": "^3.7.4", "prettier-plugin-organize-imports": "^4.0.0", "prettier-plugin-sort-json": "^4.1.1", "prettier-plugin-svelte": "^3.3.3", "rollup-plugin-visualizer": "^6.0.0", - "svelte": "5.45.2", + "svelte": "5.43.3", "svelte-check": "^4.1.5", "svelte-eslint-parser": "^1.3.3", "tailwindcss": "^4.1.7", diff --git a/web/src/lib/components/HeaderActionButton.svelte b/web/src/lib/components/HeaderActionButton.svelte new file mode 100644 index 0000000000..542c22ba43 --- /dev/null +++ b/web/src/lib/components/HeaderActionButton.svelte @@ -0,0 +1,24 @@ + + +{#if action.$if?.() ?? true} + +{/if} diff --git a/web/src/lib/components/HeaderButton.svelte b/web/src/lib/components/HeaderButton.svelte deleted file mode 100644 index c4189c06c0..0000000000 --- a/web/src/lib/components/HeaderButton.svelte +++ /dev/null @@ -1,17 +0,0 @@ - - -{#if action.$if?.() ?? true} - -{/if} diff --git a/web/src/lib/components/jobs/JobTile.svelte b/web/src/lib/components/QueueCard.svelte similarity index 65% rename from web/src/lib/components/jobs/JobTile.svelte rename to web/src/lib/components/QueueCard.svelte index 8bdd7c169a..f57fb984a2 100644 --- a/web/src/lib/components/jobs/JobTile.svelte +++ b/web/src/lib/components/QueueCard.svelte @@ -1,11 +1,15 @@ + +
+ {#if data[0].length === 0} + + {/if} +
diff --git a/web/src/lib/components/QueuePanel.svelte b/web/src/lib/components/QueuePanel.svelte new file mode 100644 index 0000000000..177cbf33c3 --- /dev/null +++ b/web/src/lib/components/QueuePanel.svelte @@ -0,0 +1,132 @@ + + +
+ {#each queueList as [queueName, props] (queueName)} + {@const queue = queues.find(({ name }) => name === queueName)} + {#if queue} + handleCommand(queueName, command)} {...props} /> + {/if} + {/each} +
diff --git a/web/src/lib/components/jobs/StorageMigrationDescription.svelte b/web/src/lib/components/QueueStorageMigrationDescription.svelte similarity index 100% rename from web/src/lib/components/jobs/StorageMigrationDescription.svelte rename to web/src/lib/components/QueueStorageMigrationDescription.svelte diff --git a/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte b/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte index 3dbf697de1..e119e8d8b0 100644 --- a/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte +++ b/web/src/lib/components/admin-settings/StorageTemplateSettings.svelte @@ -254,7 +254,7 @@ values={{ job: $t('admin.storage_template_migration_job') }} > {#snippet children({ message })} - + {message} {/snippet} diff --git a/web/src/lib/components/album-page/album-viewer.svelte b/web/src/lib/components/album-page/album-viewer.svelte index a7c9243e64..d5fdb36822 100644 --- a/web/src/lib/components/album-page/album-viewer.svelte +++ b/web/src/lib/components/album-page/album-viewer.svelte @@ -12,12 +12,14 @@ import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { assetViewingStore } from '$lib/stores/asset-viewing.store'; import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store'; + import { mobileDevice } from '$lib/stores/mobile-device.svelte'; + import { SlideshowNavigation, SlideshowState, slideshowStore } from '$lib/stores/slideshow.store'; import { handlePromiseError } from '$lib/utils'; import { cancelMultiselect } from '$lib/utils/asset-utils'; import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader'; import type { AlbumResponseDto, SharedLinkResponseDto, UserResponseDto } from '@immich/sdk'; import { IconButton, Logo } from '@immich/ui'; - import { mdiDownload, mdiFileImagePlusOutline } from '@mdi/js'; + import { mdiDownload, mdiFileImagePlusOutline, mdiPresentationPlay } from '@mdi/js'; import { t } from 'svelte-i18n'; import ControlAppBar from '../shared-components/control-app-bar.svelte'; import ThemeButton from '../shared-components/theme-button.svelte'; @@ -32,7 +34,8 @@ const album = sharedLink.album as AlbumResponseDto; - let { isViewing: showAssetViewer } = assetViewingStore; + let { isViewing: showAssetViewer, setAssetId } = assetViewingStore; + let { slideshowState, slideshowNavigation } = slideshowStore; const options = $derived({ albumId: album.id, order: album.order }); let timelineManager = $state() as TimelineManager; @@ -45,6 +48,16 @@ dragAndDropFilesStore.set({ isDragging: false, files: [] }); } }); + + const handleStartSlideshow = async () => { + const asset = + $slideshowNavigation === SlideshowNavigation.Shuffle + ? await timelineManager.getRandomAsset() + : timelineManager.months[0]?.dayGroups[0]?.viewerAssets[0]?.asset; + if (asset) { + handlePromiseError(setAssetId(asset.id).then(() => ($slideshowState = SlideshowState.PlaySlideshow))); + } + }; {#snippet leading()} - + {/snippet} @@ -117,6 +130,14 @@ {/if} {#if album.assetCount > 0 && sharedLink.allowDownload} + goto(resolve(`${AppRoute.ALBUMS}/${album.id}`))} {oncontextmenu} > diff --git a/web/src/lib/components/asset-viewer/activity-status.svelte b/web/src/lib/components/asset-viewer/activity-status.svelte index 39c6f20b3b..dd06cf3ed0 100644 --- a/web/src/lib/components/asset-viewer/activity-status.svelte +++ b/web/src/lib/components/asset-viewer/activity-status.svelte @@ -2,7 +2,7 @@ import { locale } from '$lib/stores/preferences.store'; import type { ActivityResponseDto } from '@immich/sdk'; import { Icon } from '@immich/ui'; - import { mdiCommentOutline, mdiHeart, mdiHeartOutline } from '@mdi/js'; + import { mdiCommentOutline, mdiThumbUp, mdiThumbUpOutline } from '@mdi/js'; interface Props { isLiked: ActivityResponseDto | null; @@ -19,7 +19,7 @@
+ {/if} + {/each} + +
+ + + {/if} + {@render children?.()} - + diff --git a/web/src/lib/components/layouts/TitleLayout.svelte b/web/src/lib/components/layouts/TitleLayout.svelte deleted file mode 100644 index 2d867bab2f..0000000000 --- a/web/src/lib/components/layouts/TitleLayout.svelte +++ /dev/null @@ -1,21 +0,0 @@ - - -
-
- - {@render buttons?.()} -
- {@render children?.()} -
diff --git a/web/src/lib/components/share-page/individual-shared-viewer.svelte b/web/src/lib/components/share-page/individual-shared-viewer.svelte index b7d9e548df..eb25d102fb 100644 --- a/web/src/lib/components/share-page/individual-shared-viewer.svelte +++ b/web/src/lib/components/share-page/individual-shared-viewer.svelte @@ -9,6 +9,7 @@ import type { Viewport } from '$lib/managers/timeline-manager/types'; import { AssetInteraction } from '$lib/stores/asset-interaction.svelte'; import { dragAndDropFilesStore } from '$lib/stores/drag-and-drop-files.store'; + import { mobileDevice } from '$lib/stores/mobile-device.svelte'; import { handlePromiseError } from '$lib/utils'; import { cancelMultiselect, downloadArchive } from '$lib/utils/asset-utils'; import { fileUploadHandler, openFileUploadDialog } from '$lib/utils/file-uploader'; @@ -108,7 +109,7 @@ goto(AppRoute.PHOTOS)} backIcon={mdiArrowLeft} showBackButton={false}> {#snippet leading()} - + {/snippet} diff --git a/web/src/lib/components/shared-components/search-bar/search-bar.svelte b/web/src/lib/components/shared-components/search-bar/search-bar.svelte index ea1147fe06..2218e8bf45 100644 --- a/web/src/lib/components/shared-components/search-bar/search-bar.svelte +++ b/web/src/lib/components/shared-components/search-bar/search-bar.svelte @@ -9,9 +9,9 @@ import { generateId } from '$lib/utils/generate-id'; import { getMetadataSearchQuery } from '$lib/utils/metadata-search'; import type { MetadataSearchDto, SmartSearchDto } from '@immich/sdk'; - import { IconButton, modalManager } from '@immich/ui'; + import { Button, IconButton, modalManager } from '@immich/ui'; import { mdiClose, mdiMagnify, mdiTune } from '@mdi/js'; - import { onDestroy, tick } from 'svelte'; + import { onDestroy, onMount, tick } from 'svelte'; import { t } from 'svelte-i18n'; import SearchHistoryBox from './search-history-box.svelte'; @@ -31,6 +31,8 @@ let isSearchSuggestions = $state(false); let selectedId: string | undefined = $state(); let close: (() => Promise) | undefined; + let showSearchTypeDropdown = $state(false); + let currentSearchType = $state('smart'); const listboxId = generateId(); const searchTypeId = generateId(); @@ -70,16 +72,37 @@ const onFocusIn = () => { searchStore.isSearchEnabled = true; + getSearchType(); }; const onFocusOut = () => { searchStore.isSearchEnabled = false; }; + const buildSearchPayload = (term: string): SmartSearchDto | MetadataSearchDto => { + const searchType = getSearchType(); + switch (searchType) { + case 'smart': { + return { query: term }; + } + case 'metadata': { + return { originalFileName: term }; + } + case 'description': { + return { description: term }; + } + case 'ocr': { + return { ocr: term }; + } + default: { + return { query: term }; + } + } + }; + const onHistoryTermClick = async (searchTerm: string) => { value = searchTerm; - const searchPayload = { query: searchTerm }; - await handleSearch(searchPayload); + await handleSearch(buildSearchPayload(searchTerm)); }; const onFilterClick = async () => { @@ -98,6 +121,9 @@ const searchResult = await result.onClose; close = undefined; + // Refresh search type after modal closes + getSearchType(); + if (!searchResult) { return; } @@ -106,29 +132,7 @@ }; const onSubmit = () => { - const searchType = getSearchType(); - let payload = {} as SmartSearchDto | MetadataSearchDto; - - switch (searchType) { - case 'smart': { - payload = { query: value } as SmartSearchDto; - break; - } - case 'metadata': { - payload = { originalFileName: value } as MetadataSearchDto; - break; - } - case 'description': { - payload = { description: value } as MetadataSearchDto; - break; - } - case 'ocr': { - payload = { ocr: value } as MetadataSearchDto; - break; - } - } - - handlePromiseError(handleSearch(payload)); + handlePromiseError(handleSearch(buildSearchPayload(value))); saveSearchTerm(value); }; @@ -139,6 +143,7 @@ const onEscape = () => { closeDropdown(); + closeSearchTypeDropdown(); }; const onArrow = async (direction: 1 | -1) => { @@ -168,6 +173,20 @@ searchHistoryBox?.clearSelection(); }; + const toggleSearchTypeDropdown = () => { + showSearchTypeDropdown = !showSearchTypeDropdown; + }; + + const closeSearchTypeDropdown = () => { + showSearchTypeDropdown = false; + }; + + const selectSearchType = (type: string) => { + localStorage.setItem('searchQueryType', type); + currentSearchType = type; + showSearchTypeDropdown = false; + }; + const onsubmit = (event: Event) => { event.preventDefault(); onSubmit(); @@ -180,17 +199,18 @@ case 'metadata': case 'description': case 'ocr': { + currentSearchType = searchType; return searchType; } default: { + currentSearchType = 'smart'; return 'smart'; } } } function getSearchTypeText(): string { - const searchType = getSearchType(); - switch (searchType) { + switch (currentSearchType) { case 'smart': { return $t('context'); } @@ -203,8 +223,22 @@ case 'ocr': { return $t('ocr'); } + default: { + return $t('context'); + } } } + + onMount(() => { + getSearchType(); + }); + + const searchTypes = [ + { value: 'smart', label: () => $t('context') }, + { value: 'metadata', label: () => $t('filename') }, + { value: 'description', label: () => $t('description') }, + { value: 'ocr', label: () => $t('ocr') }, + ] as const; 0} > -

- {getSearchTypeText()} -

+
+ + + {#if showSearchTypeDropdown} +
+ {#each searchTypes as searchType (searchType.value)} + + {/each} +
+ {/if} +
{/if} diff --git a/web/src/lib/components/sharedlinks-page/shared-link-card.svelte b/web/src/lib/components/sharedlinks-page/SharedLinkCard.svelte similarity index 59% rename from web/src/lib/components/sharedlinks-page/shared-link-card.svelte rename to web/src/lib/components/sharedlinks-page/SharedLinkCard.svelte index 7187dc22ad..64cc79c08d 100644 --- a/web/src/lib/components/sharedlinks-page/shared-link-card.svelte +++ b/web/src/lib/components/sharedlinks-page/SharedLinkCard.svelte @@ -5,7 +5,7 @@ import { getSharedLinkActions } from '$lib/services/shared-link.service'; import { locale } from '$lib/stores/preferences.store'; import { SharedLinkType, type SharedLinkResponseDto } from '@immich/sdk'; - import { Badge, ContextMenuButton, MenuItemType, Text } from '@immich/ui'; + import { ContextMenuButton, MenuItemType, Text } from '@immich/ui'; import { DateTime, type ToRelativeUnit } from 'luxon'; import { t } from 'svelte-i18n'; @@ -32,6 +32,28 @@ }; const { Edit, Copy, Delete } = $derived(getSharedLinkActions($t, sharedLink)); + + const capabilities = $derived.by(() => { + const items = []; + + if (sharedLink.allowUpload) { + items.push($t('upload')); + } + + if (sharedLink.allowDownload) { + items.push($t('download')); + } + + if (sharedLink.showMetadata) { + items.push($t('exif')); + } + + if (sharedLink.password) { + items.push($t('password')); + } + + return items; + });
-
- - {#if sharedLink.type === SharedLinkType.Album} - {sharedLink.album?.albumName} - {:else if sharedLink.type === SharedLinkType.Individual} - {$t('individual_share')} - {/if} - - -
- {#if isExpired} - {$t('expired')} - {:else if expiresAt} - +
+
+ + {#if isExpired} + {$t('expired')} + {:else if expiresAt} {$t('expires_date', { values: { date: getCountDownExpirationDate(expiresAt, now) } })} - - {:else} - {$t('expires_date', { values: { date: '∞' } })} - {/if} + {:else} + {$t('expires_date', { values: { date: '∞' } })} + {/if} + - {#if sharedLink.slug} - {$t('custom_url')} - {/if} + + {#if sharedLink.type === SharedLinkType.Album} + {sharedLink.album?.albumName} + {:else if sharedLink.type === SharedLinkType.Individual} + {$t('individual_share')} + {/if} + - {#if sharedLink.allowUpload} - {$t('upload')} - {/if} - - {#if sharedLink.showMetadata && sharedLink.allowDownload} - {$t('download')} - {/if} - - {#if sharedLink.showMetadata} - {$t('exif')} - {/if} - - {#if sharedLink.password} - {$t('password')} + {#if sharedLink.description} + {sharedLink.description} {/if}
- {#if sharedLink.description} - {sharedLink.description} - {/if} +
+ {#each capabilities as capability, index (index)} + + {capability} + + {#if index < capabilities.length - 1} + + {/if} + {/each} +
diff --git a/web/src/lib/components/timeline/Timeline.svelte b/web/src/lib/components/timeline/Timeline.svelte index ba9cf37bff..6e21479acc 100644 --- a/web/src/lib/components/timeline/Timeline.svelte +++ b/web/src/lib/components/timeline/Timeline.svelte @@ -188,7 +188,7 @@ // the performance benefits of deferred layouts while still supporting deep linking // to assets at the end of the timeline. timelineManager.isScrollingOnLoad = true; - const monthGroup = await timelineManager.findMonthGroupForAsset(assetId); + const monthGroup = await timelineManager.findMonthGroupForAsset({ id: assetId }); if (!monthGroup) { return false; } diff --git a/web/src/lib/constants.ts b/web/src/lib/constants.ts index 9cb00de003..a9b6991769 100644 --- a/web/src/lib/constants.ts +++ b/web/src/lib/constants.ts @@ -24,7 +24,7 @@ export enum AppRoute { ADMIN_SETTINGS = '/admin/system-settings', ADMIN_MAINTENANCE = '/admin/maintenance', ADMIN_STATS = '/admin/server-status', - ADMIN_JOBS = '/admin/jobs-status', + ADMIN_QUEUES = '/admin/queues', ADMIN_REPAIR = '/admin/repair', ALBUMS = '/albums', diff --git a/web/src/lib/managers/event-manager.svelte.ts b/web/src/lib/managers/event-manager.svelte.ts index effc5325ed..66a2db8787 100644 --- a/web/src/lib/managers/event-manager.svelte.ts +++ b/web/src/lib/managers/event-manager.svelte.ts @@ -4,6 +4,7 @@ import type { AlbumResponseDto, LibraryResponseDto, LoginResponseDto, + QueueResponseDto, SharedLinkResponseDto, SystemConfigDto, UserAdminResponseDto, @@ -21,6 +22,8 @@ export type Events = { AlbumDelete: [AlbumResponseDto]; + QueueUpdate: [QueueResponseDto]; + SharedLinkCreate: [SharedLinkResponseDto]; SharedLinkUpdate: [SharedLinkResponseDto]; SharedLinkDelete: [SharedLinkResponseDto]; diff --git a/web/src/lib/managers/queue-manager.svelte.ts b/web/src/lib/managers/queue-manager.svelte.ts new file mode 100644 index 0000000000..a7950e455a --- /dev/null +++ b/web/src/lib/managers/queue-manager.svelte.ts @@ -0,0 +1,45 @@ +import { eventManager } from '$lib/managers/event-manager.svelte'; +import type { QueueSnapshot } from '$lib/types'; +import { getQueues, type QueueResponseDto } from '@immich/sdk'; +import { DateTime } from 'luxon'; + +export class QueueManager { + #snapshots = $state([]); + #queues: QueueResponseDto[] = $derived(this.#snapshots.at(-1)?.snapshot ?? []); + + #interval?: ReturnType; + #listenerCount = 0; + + get snapshots() { + return this.#snapshots; + } + + get queues() { + return this.#queues; + } + + constructor() { + eventManager.on('QueueUpdate', () => void this.refresh()); + } + + listen() { + if (!this.#interval) { + this.#interval = setInterval(() => void this.refresh(true), 3000); + } + + this.#listenerCount++; + void this.refresh(); + + return () => this.#listenerCount--; + } + + async refresh(tick = false) { + this.#snapshots.push({ + timestamp: DateTime.now().toMillis(), + snapshot: this.#listenerCount > 0 || !tick ? await getQueues().catch(() => undefined) : undefined, + }); + this.#snapshots = this.#snapshots.slice(-30); + } +} + +export const queueManager = new QueueManager(); diff --git a/web/src/lib/managers/timeline-manager/internal/search-support.svelte.ts b/web/src/lib/managers/timeline-manager/internal/search-support.svelte.ts index f889456c20..7082673700 100644 --- a/web/src/lib/managers/timeline-manager/internal/search-support.svelte.ts +++ b/web/src/lib/managers/timeline-manager/internal/search-support.svelte.ts @@ -1,5 +1,5 @@ import { plainDateTimeCompare, type TimelineYearMonth } from '$lib/utils/timeline-util'; -import { AssetOrder } from '@immich/sdk'; +import { AssetOrder, type AssetResponseDto } from '@immich/sdk'; import { DateTime } from 'luxon'; import type { MonthGroup } from '../month-group.svelte'; import { TimelineManager } from '../timeline-manager.svelte'; @@ -7,12 +7,16 @@ import type { AssetDescriptor, Direction, TimelineAsset } from '../types'; export async function getAssetWithOffset( timelineManager: TimelineManager, - assetDescriptor: AssetDescriptor, + assetDescriptor: AssetDescriptor | AssetResponseDto, interval: 'asset' | 'day' | 'month' | 'year' = 'asset', direction: Direction, ): Promise { - const { asset, monthGroup } = findMonthGroupForAsset(timelineManager, assetDescriptor.id) ?? {}; - if (!monthGroup || !asset) { + const monthGroup = await timelineManager.findMonthGroupForAsset(assetDescriptor); + if (!monthGroup) { + return; + } + const asset = monthGroup.findAssetById(assetDescriptor); + if (!asset) { return; } diff --git a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts index bb58704214..8e31f28138 100644 --- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts +++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.spec.ts @@ -524,6 +524,7 @@ describe('TimelineManager', () => { { count: 3, timeBucket: '2024-01-01T00:00:00.000Z' }, ]); sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssetsResponse[timeBucket])); + sdkMock.getAssetInfo.mockRejectedValue(new Error('Asset not found')); await timelineManager.updateViewport({ width: 1588, height: 1000 }); }); diff --git a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts index feba73a0f8..b6c43480ef 100644 --- a/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts +++ b/web/src/lib/managers/timeline-manager/timeline-manager.svelte.ts @@ -16,12 +16,13 @@ import { WebsocketSupport } from '$lib/managers/timeline-manager/internal/websoc import { CancellableTask } from '$lib/utils/cancellable-task'; import { PersistedLocalStorage } from '$lib/utils/persisted'; import { + isAssetResponseDto, setDifference, toTimelineAsset, type TimelineDateTime, type TimelineYearMonth, } from '$lib/utils/timeline-util'; -import { AssetOrder, getAssetInfo, getTimeBuckets } from '@immich/sdk'; +import { AssetOrder, getAssetInfo, getTimeBuckets, type AssetResponseDto } from '@immich/sdk'; import { clamp, isEqual } from 'lodash-es'; import { SvelteDate, SvelteSet } from 'svelte/reactivity'; import { DayGroup } from './day-group.svelte'; @@ -343,27 +344,30 @@ export class TimelineManager extends VirtualScrollManager { this.addAssetsUpsertSegments([...notExcluded]); } - async findMonthGroupForAsset(id: string) { + async findMonthGroupForAsset(asset: AssetDescriptor | AssetResponseDto) { if (!this.isInitialized) { await this.initTask.waitUntilCompletion(); } + const { id } = asset; let { monthGroup } = findMonthGroupForAssetUtil(this, id) ?? {}; if (monthGroup) { return monthGroup; } - const response = await getAssetInfo({ ...authManager.params, id }).catch(() => null); + const response = isAssetResponseDto(asset) + ? asset + : await getAssetInfo({ ...authManager.params, id }).catch(() => null); if (!response) { return; } - const asset = toTimelineAsset(response); - if (!asset || this.isExcluded(asset)) { + const timelineAsset = toTimelineAsset(response); + if (this.isExcluded(timelineAsset)) { return; } - monthGroup = await this.#loadMonthGroupAtTime(asset.localDateTime, { cancelable: false }); + monthGroup = await this.#loadMonthGroupAtTime(timelineAsset.localDateTime, { cancelable: false }); if (monthGroup?.findAssetById({ id })) { return monthGroup; } @@ -532,14 +536,14 @@ export class TimelineManager extends VirtualScrollManager { } async getLaterAsset( - assetDescriptor: AssetDescriptor, + assetDescriptor: AssetDescriptor | AssetResponseDto, interval: 'asset' | 'day' | 'month' | 'year' = 'asset', ): Promise { return await getAssetWithOffset(this, assetDescriptor, interval, 'later'); } async getEarlierAsset( - assetDescriptor: AssetDescriptor, + assetDescriptor: AssetDescriptor | AssetResponseDto, interval: 'asset' | 'day' | 'month' | 'year' = 'asset', ): Promise { return await getAssetWithOffset(this, assetDescriptor, interval, 'earlier'); diff --git a/web/src/lib/modals/UserEditModal.svelte b/web/src/lib/modals/UserEditModal.svelte index 84e4edc32a..4b4878e46d 100644 --- a/web/src/lib/modals/UserEditModal.svelte +++ b/web/src/lib/modals/UserEditModal.svelte @@ -89,7 +89,7 @@ {$t('admin.note_apply_storage_label_previous_assets')} - + {$t('admin.storage_template_migration_job')} diff --git a/web/src/lib/services/library.service.ts b/web/src/lib/services/library.service.ts index 8b4d35a5f6..d20eae6af6 100644 --- a/web/src/lib/services/library.service.ts +++ b/web/src/lib/services/library.service.ts @@ -28,7 +28,7 @@ export const getLibrariesActions = ($t: MessageFormatter, libraries: LibraryResp title: $t('scan_all_libraries'), type: $t('command'), icon: mdiSync, - onAction: () => void handleScanAllLibraries(), + onAction: () => handleScanAllLibraries(), shortcuts: { shift: true, key: 'r' }, $if: () => libraries.length > 0, }; @@ -37,7 +37,7 @@ export const getLibrariesActions = ($t: MessageFormatter, libraries: LibraryResp title: $t('create_library'), type: $t('command'), icon: mdiPlusBoxOutline, - onAction: () => void handleCreateLibrary(), + onAction: () => handleCreateLibrary(), shortcuts: { shift: true, key: 'n' }, }; @@ -49,7 +49,7 @@ export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponse icon: mdiPencilOutline, type: $t('command'), title: $t('rename'), - onAction: () => void modalManager.show(LibraryRenameModal, { library }), + onAction: () => modalManager.show(LibraryRenameModal, { library }), shortcuts: { key: 'r' }, }; @@ -58,7 +58,7 @@ export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponse type: $t('command'), title: $t('delete'), color: 'danger', - onAction: () => void handleDeleteLibrary(library), + onAction: () => handleDeleteLibrary(library), shortcuts: { key: 'Backspace' }, }; @@ -66,21 +66,21 @@ export const getLibraryActions = ($t: MessageFormatter, library: LibraryResponse icon: mdiPlusBoxOutline, type: $t('command'), title: $t('add'), - onAction: () => void modalManager.show(LibraryFolderAddModal, { library }), + onAction: () => modalManager.show(LibraryFolderAddModal, { library }), }; const AddExclusionPattern: ActionItem = { icon: mdiPlusBoxOutline, type: $t('command'), title: $t('add'), - onAction: () => void modalManager.show(LibraryExclusionPatternAddModal, { library }), + onAction: () => modalManager.show(LibraryExclusionPatternAddModal, { library }), }; const Scan: ActionItem = { icon: mdiSync, type: $t('command'), title: $t('scan_library'), - onAction: () => void handleScanLibrary(library), + onAction: () => handleScanLibrary(library), shortcuts: { shift: true, key: 'r' }, }; @@ -92,14 +92,14 @@ export const getLibraryFolderActions = ($t: MessageFormatter, library: LibraryRe icon: mdiPencilOutline, type: $t('command'), title: $t('edit'), - onAction: () => void modalManager.show(LibraryFolderEditModal, { folder, library }), + onAction: () => modalManager.show(LibraryFolderEditModal, { folder, library }), }; const Delete: ActionItem = { icon: mdiTrashCanOutline, type: $t('command'), title: $t('delete'), - onAction: () => void handleDeleteLibraryFolder(library, folder), + onAction: () => handleDeleteLibraryFolder(library, folder), }; return { Edit, Delete }; @@ -114,14 +114,14 @@ export const getLibraryExclusionPatternActions = ( icon: mdiPencilOutline, type: $t('command'), title: $t('edit'), - onAction: () => void modalManager.show(LibraryExclusionPatternEditModal, { exclusionPattern, library }), + onAction: () => modalManager.show(LibraryExclusionPatternEditModal, { exclusionPattern, library }), }; const Delete: ActionItem = { icon: mdiTrashCanOutline, type: $t('command'), title: $t('delete'), - onAction: () => void handleDeleteExclusionPattern(library, exclusionPattern), + onAction: () => handleDeleteExclusionPattern(library, exclusionPattern), }; return { Edit, Delete }; @@ -273,7 +273,7 @@ const handleDeleteLibraryFolder = async (library: LibraryResponseDto, folder: st }); if (!confirmed) { - return false; + return; } try { @@ -285,10 +285,7 @@ const handleDeleteLibraryFolder = async (library: LibraryResponseDto, folder: st toastManager.success($t('admin.library_updated')); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); - return false; } - - return true; }; export const handleAddLibraryExclusionPattern = async (library: LibraryResponseDto, exclusionPattern: string) => { @@ -345,9 +342,8 @@ const handleDeleteExclusionPattern = async (library: LibraryResponseDto, exclusi const $t = await getFormatter(); const confirmed = await modalManager.showDialog({ prompt: $t('admin.library_remove_exclusion_pattern_prompt') }); - if (!confirmed) { - return false; + return; } try { @@ -361,8 +357,5 @@ const handleDeleteExclusionPattern = async (library: LibraryResponseDto, exclusi toastManager.success($t('admin.library_updated')); } catch (error) { handleError(error, $t('errors.unable_to_update_library')); - return false; } - - return true; }; diff --git a/web/src/lib/services/queue.service.ts b/web/src/lib/services/queue.service.ts new file mode 100644 index 0000000000..46219ef22a --- /dev/null +++ b/web/src/lib/services/queue.service.ts @@ -0,0 +1,268 @@ +import { goto } from '$app/navigation'; +import { AppRoute } from '$lib/constants'; +import { eventManager } from '$lib/managers/event-manager.svelte'; +import { queueManager } from '$lib/managers/queue-manager.svelte'; +import JobCreateModal from '$lib/modals/JobCreateModal.svelte'; +import type { HeaderButtonActionItem } from '$lib/types'; +import { handleError } from '$lib/utils/handle-error'; +import { getFormatter } from '$lib/utils/i18n'; +import { + emptyQueue, + getQueue, + QueueCommand, + QueueName, + runQueueCommandLegacy, + updateQueue, + type QueueResponseDto, +} from '@immich/sdk'; +import { modalManager, toastManager, type ActionItem, type IconLike } from '@immich/ui'; +import { + mdiClose, + mdiCog, + mdiContentDuplicate, + mdiDatabaseOutline, + mdiFaceRecognition, + mdiFileJpgBox, + mdiFileXmlBox, + mdiFolderMove, + mdiImageSearch, + mdiLibraryShelves, + mdiOcr, + mdiPause, + mdiPlay, + mdiPlus, + mdiStateMachine, + mdiTable, + mdiTagFaces, + mdiTrashCanOutline, + mdiTrayFull, + mdiVideo, +} from '@mdi/js'; +import type { MessageFormatter } from 'svelte-i18n'; + +type QueueItem = { + icon: IconLike; + title: string; + subtitle?: string; +}; + +export const getQueuesActions = ($t: MessageFormatter, queues: QueueResponseDto[] | undefined) => { + const pausedQueues = (queues ?? []).filter(({ isPaused }) => isPaused).map(({ name }) => name); + + const ResumePaused: HeaderButtonActionItem = { + title: $t('resume_paused_jobs', { values: { count: pausedQueues.length } }), + $if: () => pausedQueues.length > 0, + icon: mdiPlay, + onAction: () => handleResumePausedJobs(pausedQueues), + data: { + title: pausedQueues.join(', '), + }, + }; + + const CreateJob: ActionItem = { + icon: mdiPlus, + title: $t('admin.create_job'), + type: $t('command'), + shortcuts: { shift: true, key: 'n' }, + onAction: async () => { + await modalManager.show(JobCreateModal, {}); + }, + }; + + const ManageConcurrency: ActionItem = { + icon: mdiCog, + title: $t('admin.manage_concurrency'), + description: $t('admin.manage_concurrency_description'), + type: $t('page'), + onAction: () => goto(`${AppRoute.ADMIN_SETTINGS}?isOpen=job`), + }; + + return { ResumePaused, ManageConcurrency, CreateJob }; +}; + +export const getQueueActions = ($t: MessageFormatter, queue: QueueResponseDto) => { + const Pause: ActionItem = { + icon: mdiPause, + title: $t('pause'), + $if: () => !queue.isPaused, + onAction: () => handlePauseQueue(queue), + }; + + const Resume: ActionItem = { + icon: mdiPlay, + title: $t('resume'), + $if: () => queue.isPaused, + onAction: () => handleResumeQueue(queue), + }; + + const Empty: ActionItem = { + icon: mdiClose, + title: $t('clear'), + onAction: () => handleEmptyQueue(queue), + }; + + const RemoveFailedJobs: ActionItem = { + icon: mdiTrashCanOutline, + color: 'danger', + title: $t('admin.remove_failed_jobs'), + onAction: () => handleRemoveFailedJobs(queue), + }; + + return { Pause, Resume, Empty, RemoveFailedJobs }; +}; + +export const handlePauseQueue = async (queue: QueueResponseDto) => { + const response = await updateQueue({ name: queue.name, queueUpdateDto: { isPaused: true } }); + eventManager.emit('QueueUpdate', response); +}; + +export const handleResumeQueue = async (queue: QueueResponseDto) => { + const response = await updateQueue({ name: queue.name, queueUpdateDto: { isPaused: false } }); + eventManager.emit('QueueUpdate', response); +}; + +export const handleEmptyQueue = async (queue: QueueResponseDto) => { + const $t = await getFormatter(); + const item = asQueueItem($t, queue); + + try { + await emptyQueue({ name: queue.name, queueDeleteDto: { failed: false } }); + const response = await getQueue({ name: queue.name }); + eventManager.emit('QueueUpdate', response); + toastManager.success($t('admin.cleared_jobs', { values: { job: item.title } })); + } catch (error) { + handleError(error, $t('errors.something_went_wrong')); + } +}; + +const handleResumePausedJobs = async (queues: QueueName[]) => { + const $t = await getFormatter(); + + try { + for (const name of queues) { + await runQueueCommandLegacy({ name, queueCommandDto: { command: QueueCommand.Resume, force: false } }); + } + await queueManager.refresh(); + } catch (error) { + handleError(error, $t('admin.failed_job_command', { values: { command: 'resume', job: 'paused jobs' } })); + } +}; + +const handleRemoveFailedJobs = async (queue: QueueResponseDto) => { + const $t = await getFormatter(); + + try { + await emptyQueue({ name: queue.name, queueDeleteDto: { failed: true } }); + const response = await getQueue({ name: queue.name }); + eventManager.emit('QueueUpdate', response); + toastManager.success(); + } catch (error) { + handleError(error, $t('errors.something_went_wrong')); + } +}; + +export const asQueueItem = ($t: MessageFormatter, queue: { name: QueueName }): QueueItem => { + // TODO merge this mapping with data from QueuePanel.svelte + const items: Record = { + [QueueName.ThumbnailGeneration]: { + icon: mdiFileJpgBox, + title: $t('admin.thumbnail_generation_job'), + subtitle: $t('admin.thumbnail_generation_job_description'), + }, + [QueueName.MetadataExtraction]: { + icon: mdiTable, + title: $t('admin.metadata_extraction_job'), + subtitle: $t('admin.metadata_extraction_job_description'), + }, + [QueueName.Library]: { + icon: mdiLibraryShelves, + title: $t('external_libraries'), + subtitle: $t('admin.library_tasks_description'), + }, + [QueueName.Sidecar]: { + title: $t('admin.sidecar_job'), + icon: mdiFileXmlBox, + subtitle: $t('admin.sidecar_job_description'), + }, + [QueueName.SmartSearch]: { + icon: mdiImageSearch, + title: $t('admin.machine_learning_smart_search'), + subtitle: $t('admin.smart_search_job_description'), + }, + [QueueName.DuplicateDetection]: { + icon: mdiContentDuplicate, + title: $t('admin.machine_learning_duplicate_detection'), + subtitle: $t('admin.duplicate_detection_job_description'), + }, + [QueueName.FaceDetection]: { + icon: mdiFaceRecognition, + title: $t('admin.face_detection'), + subtitle: $t('admin.face_detection_description'), + }, + [QueueName.FacialRecognition]: { + icon: mdiTagFaces, + title: $t('admin.machine_learning_facial_recognition'), + subtitle: $t('admin.facial_recognition_job_description'), + }, + [QueueName.Ocr]: { + icon: mdiOcr, + title: $t('admin.machine_learning_ocr'), + subtitle: $t('admin.ocr_job_description'), + }, + [QueueName.VideoConversion]: { + icon: mdiVideo, + title: $t('admin.video_conversion_job'), + subtitle: $t('admin.video_conversion_job_description'), + }, + [QueueName.StorageTemplateMigration]: { + icon: mdiFolderMove, + title: $t('admin.storage_template_migration'), + }, + [QueueName.Migration]: { + icon: mdiFolderMove, + title: $t('admin.migration_job'), + subtitle: $t('admin.migration_job_description'), + }, + [QueueName.BackgroundTask]: { + icon: mdiTrayFull, + title: $t('admin.background_task_job'), + }, + [QueueName.Search]: { + icon: '', + title: $t('search'), + }, + [QueueName.Notifications]: { + icon: '', + title: $t('notifications'), + }, + [QueueName.BackupDatabase]: { + icon: mdiDatabaseOutline, + title: $t('admin.backup_database'), + }, + [QueueName.Workflow]: { + icon: mdiStateMachine, + title: $t('workflow'), + }, + }; + + return items[queue.name]; +}; + +export const asQueueSlug = (name: QueueName) => { + return name.replaceAll(/[A-Z]/g, (m) => '-' + m.toLowerCase()); +}; + +export const fromQueueSlug = (slug: string): QueueName | undefined => { + const name = slug.replaceAll(/-([a-z])/g, (_, c) => c.toUpperCase()); + if (Object.values(QueueName).includes(name as QueueName)) { + return name as QueueName; + } +}; + +export const getQueueDetailUrl = (queue: QueueResponseDto) => { + return `${AppRoute.ADMIN_QUEUES}/${asQueueSlug(queue.name)}`; +}; + +export const handleViewQueue = (queue: QueueResponseDto) => { + return goto(getQueueDetailUrl(queue)); +}; diff --git a/web/src/lib/services/shared-link.service.ts b/web/src/lib/services/shared-link.service.ts index 4e6a942682..cbea6ddd9d 100644 --- a/web/src/lib/services/shared-link.service.ts +++ b/web/src/lib/services/shared-link.service.ts @@ -24,26 +24,26 @@ export const getSharedLinkActions = ($t: MessageFormatter, sharedLink: SharedLin const Edit: ActionItem = { title: $t('edit_link'), icon: mdiPencilOutline, - onAction: () => void goto(`${AppRoute.SHARED_LINKS}/${sharedLink.id}`), + onAction: () => goto(`${AppRoute.SHARED_LINKS}/${sharedLink.id}`), }; const Delete: ActionItem = { title: $t('delete_link'), icon: mdiTrashCanOutline, color: 'danger', - onAction: () => void handleDeleteSharedLink(sharedLink), + onAction: () => handleDeleteSharedLink(sharedLink), }; const Copy: ActionItem = { title: $t('copy_link'), icon: mdiContentCopy, - onAction: () => void copyToClipboard(asUrl(sharedLink)), + onAction: () => copyToClipboard(asUrl(sharedLink)), }; const ViewQrCode: ActionItem = { title: $t('view_qr_code'), icon: mdiQrcode, - onAction: () => void handleShowSharedLinkQrCode(sharedLink), + onAction: () => handleShowSharedLinkQrCode(sharedLink), }; return { Edit, Delete, Copy, ViewQrCode }; @@ -88,7 +88,7 @@ export const handleUpdateSharedLink = async (sharedLink: SharedLinkResponseDto, } }; -export const handleDeleteSharedLink = async (sharedLink: SharedLinkResponseDto): Promise => { +const handleDeleteSharedLink = async (sharedLink: SharedLinkResponseDto) => { const $t = await getFormatter(); const success = await modalManager.showDialog({ title: $t('delete_shared_link'), @@ -96,17 +96,15 @@ export const handleDeleteSharedLink = async (sharedLink: SharedLinkResponseDto): confirmText: $t('delete'), }); if (!success) { - return false; + return; } try { await removeSharedLink({ id: sharedLink.id }); eventManager.emit('SharedLinkDelete', sharedLink); toastManager.success($t('deleted_shared_link')); - return true; } catch (error) { handleError(error, $t('errors.unable_to_delete_shared_link')); - return false; } }; diff --git a/web/src/lib/services/system-config.service.ts b/web/src/lib/services/system-config.service.ts index ffd0094c72..b8c7716d47 100644 --- a/web/src/lib/services/system-config.service.ts +++ b/web/src/lib/services/system-config.service.ts @@ -20,7 +20,7 @@ export const getSystemConfigActions = ( description: $t('admin.copy_config_to_clipboard_description'), type: $t('command'), icon: mdiContentCopy, - onAction: () => void handleCopyToClipboard(config), + onAction: () => handleCopyToClipboard(config), shortcuts: { shift: true, key: 'c' }, }; diff --git a/web/src/lib/services/user-admin.service.ts b/web/src/lib/services/user-admin.service.ts index 7a49f2fbe3..997a43fc7f 100644 --- a/web/src/lib/services/user-admin.service.ts +++ b/web/src/lib/services/user-admin.service.ts @@ -1,11 +1,13 @@ import { goto } from '$app/navigation'; import { eventManager } from '$lib/managers/event-manager.svelte'; +import { serverConfigManager } from '$lib/managers/server-config-manager.svelte'; import PasswordResetSuccessModal from '$lib/modals/PasswordResetSuccessModal.svelte'; import UserCreateModal from '$lib/modals/UserCreateModal.svelte'; import UserDeleteConfirmModal from '$lib/modals/UserDeleteConfirmModal.svelte'; import UserEditModal from '$lib/modals/UserEditModal.svelte'; import UserRestoreConfirmModal from '$lib/modals/UserRestoreConfirmModal.svelte'; import { user as authUser } from '$lib/stores/user.store'; +import type { HeaderButtonActionItem } from '$lib/types'; import { handleError } from '$lib/utils/handle-error'; import { getFormatter } from '$lib/utils/i18n'; import { @@ -28,6 +30,7 @@ import { mdiPlusBoxOutline, mdiTrashCanOutline, } from '@mdi/js'; +import { DateTime } from 'luxon'; import type { MessageFormatter } from 'svelte-i18n'; import { get } from 'svelte/store'; @@ -36,7 +39,7 @@ export const getUserAdminsActions = ($t: MessageFormatter) => { title: $t('create_user'), type: $t('command'), icon: mdiPlusBoxOutline, - onAction: () => void modalManager.show(UserCreateModal, {}), + onAction: () => modalManager.show(UserCreateModal, {}), shortcuts: { shift: true, key: 'n' }, }; @@ -60,11 +63,17 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons shortcuts: { key: 'Backspace' }, }; - const Restore: ActionItem = { + const getDeleteDate = (deletedAt: string): Date => + DateTime.fromISO(deletedAt).plus({ days: serverConfigManager.value.userDeleteDelay }).toJSDate(); + + const Restore: HeaderButtonActionItem = { icon: mdiDeleteRestore, title: $t('restore'), type: $t('command'), color: 'primary', + data: { + title: $t('admin.user_restore_scheduled_removal', { values: { date: getDeleteDate(user.deletedAt!) } }), + }, $if: () => !!user.deletedAt && user.status === UserStatus.Deleted, onAction: () => modalManager.show(UserRestoreConfirmModal, { user }), }; @@ -74,14 +83,14 @@ export const getUserAdminActions = ($t: MessageFormatter, user: UserAdminRespons title: $t('reset_password'), type: $t('command'), $if: () => get(authUser).id !== user.id, - onAction: () => void handleResetPasswordUserAdmin(user), + onAction: () => handleResetPasswordUserAdmin(user), }; const ResetPinCode: ActionItem = { icon: mdiLockSmart, type: $t('command'), title: $t('reset_pin_code'), - onAction: () => void handleResetPinCodeUserAdmin(user), + onAction: () => handleResetPinCodeUserAdmin(user), }; return { Update, Delete, Restore, ResetPassword, ResetPinCode }; @@ -162,12 +171,12 @@ const generatePassword = (length: number = 16) => { return generatedPassword; }; -export const handleResetPasswordUserAdmin = async (user: UserAdminResponseDto) => { +const handleResetPasswordUserAdmin = async (user: UserAdminResponseDto) => { const $t = await getFormatter(); const prompt = $t('admin.confirm_user_password_reset', { values: { user: user.name } }); const success = await modalManager.showDialog({ prompt }); if (!success) { - return false; + return; } try { @@ -176,28 +185,24 @@ export const handleResetPasswordUserAdmin = async (user: UserAdminResponseDto) = eventManager.emit('UserAdminUpdate', response); toastManager.success(); await modalManager.show(PasswordResetSuccessModal, { newPassword: dto.password }); - return true; } catch (error) { handleError(error, $t('errors.unable_to_reset_password')); - return false; } }; -export const handleResetPinCodeUserAdmin = async (user: UserAdminResponseDto) => { +const handleResetPinCodeUserAdmin = async (user: UserAdminResponseDto) => { const $t = await getFormatter(); const prompt = $t('admin.confirm_user_pin_code_reset', { values: { user: user.name } }); const success = await modalManager.showDialog({ prompt }); if (!success) { - return false; + return; } try { const response = await updateUserAdmin({ id: user.id, userAdminUpdateDto: { pinCode: null } }); eventManager.emit('UserAdminUpdate', response); toastManager.success($t('pin_code_reset_successfully')); - return true; } catch (error) { handleError(error, $t('errors.unable_to_reset_pin_code')); - return false; } }; diff --git a/web/src/lib/sidebars/AdminSidebar.svelte b/web/src/lib/sidebars/AdminSidebar.svelte index 052af87df1..f873f4c28c 100644 --- a/web/src/lib/sidebars/AdminSidebar.svelte +++ b/web/src/lib/sidebars/AdminSidebar.svelte @@ -2,17 +2,17 @@ import BottomInfo from '$lib/components/shared-components/side-bar/bottom-info.svelte'; import { AppRoute } from '$lib/constants'; import { NavbarItem } from '@immich/ui'; - import { mdiAccountMultipleOutline, mdiBookshelf, mdiCog, mdiServer, mdiSync, mdiWrench } from '@mdi/js'; + import { mdiAccountMultipleOutline, mdiBookshelf, mdiCog, mdiServer, mdiTrayFull, mdiWrench } from '@mdi/js'; import { t } from 'svelte-i18n';
- + + -
diff --git a/web/src/lib/stores/ocr.svelte.spec.ts b/web/src/lib/stores/ocr.svelte.spec.ts new file mode 100644 index 0000000000..516e9f9f92 --- /dev/null +++ b/web/src/lib/stores/ocr.svelte.spec.ts @@ -0,0 +1,225 @@ +import { ocrManager, type OcrBoundingBox } from '$lib/stores/ocr.svelte'; +import { getAssetOcr } from '@immich/sdk'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +// Mock the SDK +vi.mock('@immich/sdk', () => ({ + getAssetOcr: vi.fn(), +})); + +const createMockOcrData = (overrides?: Partial): OcrBoundingBox[] => [ + { + id: '1', + assetId: 'asset-123', + x1: 0, + y1: 0, + x2: 100, + y2: 0, + x3: 100, + y3: 50, + x4: 0, + y4: 50, + boxScore: 0.95, + textScore: 0.98, + text: 'Hello World', + ...overrides, + }, +]; + +describe('OcrManager', () => { + beforeEach(() => { + // Reset the singleton state before each test + ocrManager.clear(); + vi.clearAllMocks(); + }); + + describe('initial state', () => { + it('should initialize with empty data', () => { + expect(ocrManager.data).toEqual([]); + }); + + it('should initialize with showOverlay as false', () => { + expect(ocrManager.showOverlay).toBe(false); + }); + + it('should initialize with hasOcrData as false', () => { + expect(ocrManager.hasOcrData).toBe(false); + }); + }); + + describe('getAssetOcr', () => { + it('should load OCR data for an asset', async () => { + const mockData = createMockOcrData(); + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + + await ocrManager.getAssetOcr('asset-123'); + + expect(getAssetOcr).toHaveBeenCalledWith({ id: 'asset-123' }); + expect(ocrManager.data).toEqual(mockData); + expect(ocrManager.hasOcrData).toBe(true); + }); + + it('should handle empty OCR data', async () => { + vi.mocked(getAssetOcr).mockResolvedValue([]); + + await ocrManager.getAssetOcr('asset-456'); + + expect(ocrManager.data).toEqual([]); + expect(ocrManager.hasOcrData).toBe(false); + }); + + it('should reset the loader when previously cleared', async () => { + const mockData = createMockOcrData(); + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + + // First clear + ocrManager.clear(); + expect(ocrManager.data).toEqual([]); + + // Then load new data + await ocrManager.getAssetOcr('asset-789'); + + expect(ocrManager.data).toEqual(mockData); + expect(ocrManager.hasOcrData).toBe(true); + }); + + it('should handle concurrent requests safely', async () => { + const firstData = createMockOcrData({ id: '1', text: 'First' }); + const secondData = createMockOcrData({ id: '2', text: 'Second' }); + + vi.mocked(getAssetOcr) + .mockImplementationOnce( + () => + new Promise((resolve) => { + setTimeout(() => resolve(firstData), 100); + }), + ) + .mockResolvedValueOnce(secondData); + + // Start first request + const promise1 = ocrManager.getAssetOcr('asset-1'); + // Start second request immediately (should wait for first to complete) + const promise2 = ocrManager.getAssetOcr('asset-2'); + + await Promise.all([promise1, promise2]); + + // CancellableTask waits for first request, so second request is ignored + // The data should be from the first request that completed + expect(ocrManager.data).toEqual(firstData); + }); + + it('should handle errors gracefully', async () => { + const error = new Error('Network error'); + vi.mocked(getAssetOcr).mockRejectedValue(error); + + // The error should be handled by CancellableTask + await expect(ocrManager.getAssetOcr('asset-error')).resolves.not.toThrow(); + }); + }); + + describe('clear', () => { + it('should clear OCR data', async () => { + const mockData = createMockOcrData({ text: 'Test' }); + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + await ocrManager.getAssetOcr('asset-123'); + + ocrManager.clear(); + + expect(ocrManager.data).toEqual([]); + expect(ocrManager.hasOcrData).toBe(false); + }); + + it('should reset showOverlay to false', () => { + ocrManager.showOverlay = true; + + ocrManager.clear(); + + expect(ocrManager.showOverlay).toBe(false); + }); + + it('should mark as cleared for next load', async () => { + const mockData = createMockOcrData({ text: 'Test' }); + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + + ocrManager.clear(); + await ocrManager.getAssetOcr('asset-123'); + + // Should successfully load after clear + expect(ocrManager.data).toEqual(mockData); + }); + }); + + describe('toggleOcrBoundingBox', () => { + it('should toggle showOverlay from false to true', () => { + expect(ocrManager.showOverlay).toBe(false); + + ocrManager.toggleOcrBoundingBox(); + + expect(ocrManager.showOverlay).toBe(true); + }); + + it('should toggle showOverlay from true to false', () => { + ocrManager.showOverlay = true; + + ocrManager.toggleOcrBoundingBox(); + + expect(ocrManager.showOverlay).toBe(false); + }); + + it('should toggle multiple times', () => { + ocrManager.toggleOcrBoundingBox(); + expect(ocrManager.showOverlay).toBe(true); + + ocrManager.toggleOcrBoundingBox(); + expect(ocrManager.showOverlay).toBe(false); + + ocrManager.toggleOcrBoundingBox(); + expect(ocrManager.showOverlay).toBe(true); + }); + }); + + describe('hasOcrData derived state', () => { + it('should be false when data is empty', () => { + expect(ocrManager.hasOcrData).toBe(false); + }); + + it('should be true when data is present', async () => { + const mockData = createMockOcrData({ text: 'Test' }); + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + await ocrManager.getAssetOcr('asset-123'); + + expect(ocrManager.hasOcrData).toBe(true); + }); + + it('should update when data is cleared', async () => { + const mockData = createMockOcrData({ text: 'Test' }); + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + await ocrManager.getAssetOcr('asset-123'); + expect(ocrManager.hasOcrData).toBe(true); + + ocrManager.clear(); + expect(ocrManager.hasOcrData).toBe(false); + }); + }); + + describe('data immutability', () => { + it('should return the same reference when data does not change', () => { + const firstReference = ocrManager.data; + const secondReference = ocrManager.data; + + expect(firstReference).toBe(secondReference); + }); + + it('should return a new reference when data changes', async () => { + const firstReference = ocrManager.data; + const mockData = createMockOcrData({ text: 'Test' }); + + vi.mocked(getAssetOcr).mockResolvedValue(mockData); + await ocrManager.getAssetOcr('asset-123'); + + const secondReference = ocrManager.data; + + expect(firstReference).not.toBe(secondReference); + }); + }); +}); diff --git a/web/src/lib/stores/ocr.svelte.ts b/web/src/lib/stores/ocr.svelte.ts index f9862b1edc..f68e550851 100644 --- a/web/src/lib/stores/ocr.svelte.ts +++ b/web/src/lib/stores/ocr.svelte.ts @@ -1,3 +1,4 @@ +import { CancellableTask } from '$lib/utils/cancellable-task'; import { getAssetOcr } from '@immich/sdk'; export type OcrBoundingBox = { @@ -20,6 +21,8 @@ class OcrManager { #data = $state([]); showOverlay = $state(false); #hasOcrData = $derived(this.#data.length > 0); + #ocrLoader = new CancellableTask(); + #cleared = false; get data() { return this.#data; @@ -30,10 +33,17 @@ class OcrManager { } async getAssetOcr(id: string) { - this.#data = await getAssetOcr({ id }); + if (this.#cleared) { + await this.#ocrLoader.reset(); + this.#cleared = false; + } + await this.#ocrLoader.execute(async () => { + this.#data = await getAssetOcr({ id }); + }, false); } clear() { + this.#cleared = true; this.#data = []; this.showOverlay = false; } diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts index d95e7b7cf2..dbe3c851a0 100644 --- a/web/src/lib/types.ts +++ b/web/src/lib/types.ts @@ -1,4 +1,5 @@ -import type { ServerVersionResponseDto } from '@immich/sdk'; +import type { QueueResponseDto, ServerVersionResponseDto } from '@immich/sdk'; +import type { ActionItem } from '@immich/ui'; export interface ReleaseEvent { isAvailable: boolean; @@ -7,3 +8,7 @@ export interface ReleaseEvent { serverVersion: ServerVersionResponseDto; releaseVersion: ServerVersionResponseDto; } + +export type QueueSnapshot = { timestamp: number; snapshot?: QueueResponseDto[] }; + +export type HeaderButtonActionItem = ActionItem & { data?: { title?: string } }; diff --git a/web/src/lib/utils/timeline-util.ts b/web/src/lib/utils/timeline-util.ts index 3326676f3c..f8fb49b61f 100644 --- a/web/src/lib/utils/timeline-util.ts +++ b/web/src/lib/utils/timeline-util.ts @@ -1,4 +1,4 @@ -import type { TimelineAsset, ViewportTopMonth } from '$lib/managers/timeline-manager/types'; +import type { AssetDescriptor, TimelineAsset, ViewportTopMonth } from '$lib/managers/timeline-manager/types'; import { locale } from '$lib/stores/preferences.store'; import { getAssetRatio } from '$lib/utils/asset-utils'; import { AssetTypeEnum, type AssetResponseDto } from '@immich/sdk'; @@ -192,8 +192,13 @@ export const toTimelineAsset = (unknownAsset: AssetResponseDto | TimelineAsset): }; }; -export const isTimelineAsset = (unknownAsset: AssetResponseDto | TimelineAsset): unknownAsset is TimelineAsset => - (unknownAsset as TimelineAsset).ratio !== undefined; +export const isTimelineAsset = ( + unknownAsset: AssetDescriptor | AssetResponseDto | TimelineAsset, +): unknownAsset is TimelineAsset => (unknownAsset as TimelineAsset).ratio !== undefined; + +export const isAssetResponseDto = ( + unknownAsset: AssetDescriptor | AssetResponseDto | TimelineAsset, +): unknownAsset is AssetResponseDto => (unknownAsset as AssetResponseDto).type !== undefined; export const isTimelineAssets = (assets: AssetResponseDto[] | TimelineAsset[]): assets is TimelineAsset[] => assets.length === 0 || 'ratio' in assets[0]; diff --git a/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte b/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte index d8b35204dc..cc9afd4f64 100644 --- a/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte +++ b/web/src/routes/(user)/shared-links/[[id=id]]/+page.svelte @@ -3,7 +3,7 @@ import { page } from '$app/state'; import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte'; import OnEvents from '$lib/components/OnEvents.svelte'; - import SharedLinkCard from '$lib/components/sharedlinks-page/shared-link-card.svelte'; + import SharedLinkCard from '$lib/components/sharedlinks-page/SharedLinkCard.svelte'; import { AppRoute } from '$lib/constants'; import GroupTab from '$lib/elements/GroupTab.svelte'; import SharedLinkUpdateModal from '$lib/modals/SharedLinkUpdateModal.svelte'; diff --git a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte index 442d3cef6c..7f873aa918 100644 --- a/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte +++ b/web/src/routes/(user)/tags/[[photos=photos]]/[[assetId=id]]/+page.svelte @@ -15,9 +15,24 @@ import { joinPaths, TreeNode } from '$lib/utils/tree-utils'; import { deleteTag, getAllTags, type TagResponseDto } from '@immich/sdk'; import { Button, HStack, modalManager, Text } from '@immich/ui'; - import { mdiPencil, mdiPlus, mdiTag, mdiTagMultiple, mdiTrashCanOutline } from '@mdi/js'; + import { mdiDotsVertical, mdiPencil, mdiPlus, mdiTag, mdiTagMultiple, mdiTrashCanOutline } from '@mdi/js'; import { t } from 'svelte-i18n'; import type { PageData } from './$types'; + import AssetSelectControlBar from '$lib/components/timeline/AssetSelectControlBar.svelte'; + import AddToAlbum from '$lib/components/timeline/actions/AddToAlbumAction.svelte'; + import ArchiveAction from '$lib/components/timeline/actions/ArchiveAction.svelte'; + import ChangeDate from '$lib/components/timeline/actions/ChangeDateAction.svelte'; + import ChangeDescription from '$lib/components/timeline/actions/ChangeDescriptionAction.svelte'; + import ChangeLocation from '$lib/components/timeline/actions/ChangeLocationAction.svelte'; + import CreateSharedLink from '$lib/components/timeline/actions/CreateSharedLinkAction.svelte'; + import DeleteAssets from '$lib/components/timeline/actions/DeleteAssetsAction.svelte'; + import DownloadAction from '$lib/components/timeline/actions/DownloadAction.svelte'; + import FavoriteAction from '$lib/components/timeline/actions/FavoriteAction.svelte'; + import SelectAllAssets from '$lib/components/timeline/actions/SelectAllAction.svelte'; + import SetVisibilityAction from '$lib/components/timeline/actions/SetVisibilityAction.svelte'; + import TagAction from '$lib/components/timeline/actions/TagAction.svelte'; + import ButtonContextMenu from '$lib/components/shared-components/context-menu/button-context-menu.svelte'; + import { preferences, user } from '$lib/stores/user.store'; interface Props { data: PageData; @@ -79,6 +94,11 @@ // navigate to parent await navigateToView(tag.parent ? tag.parent.path : ''); }; + + const handleSetVisibility = (assetIds: string[]) => { + timelineManager.removeAssets(assetIds); + assetInteraction.clearMultiselect(); + }; @@ -131,3 +151,45 @@ {/if} + +
+ {#if assetInteraction.selectionActive} +
+ assetInteraction.clearMultiselect()} + > + + + + + + + timelineManager.update(ids, (asset) => (asset.isFavorite = isFavorite))} + > + + + + + + timelineManager.update(ids, (asset) => (asset.visibility = visibility))} + /> + {#if $preferences.tags.enabled} + + {/if} + timelineManager.removeAssets(assetIds)} + onUndoDelete={(assets) => timelineManager.upsertAssets(assets)} + /> + + + +
+ {/if} +
diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index 7089aff673..60cb3897b2 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -14,13 +14,14 @@ import { themeManager } from '$lib/managers/theme-manager.svelte'; import ServerRestartingModal from '$lib/modals/ServerRestartingModal.svelte'; import VersionAnnouncementModal from '$lib/modals/VersionAnnouncementModal.svelte'; + import { sidebarStore } from '$lib/stores/sidebar.svelte'; import { user } from '$lib/stores/user.store'; import { closeWebsocketConnection, openWebsocketConnection, websocketStore } from '$lib/stores/websocket'; import type { ReleaseEvent } from '$lib/types'; import { copyToClipboard, getReleaseType, semverToName } from '$lib/utils'; import { maintenanceShouldRedirect } from '$lib/utils/maintenance'; import { isAssetViewerRoute } from '$lib/utils/navigation'; - import { CommandPaletteContext, modalManager, setTranslations, type ActionItem } from '@immich/ui'; + import { CommandPaletteContext, modalManager, setTranslations, toastManager, type ActionItem } from '@immich/ui'; import { mdiAccountMultipleOutline, mdiBookshelf, mdiCog, mdiServer, mdiSync, mdiThemeLightDark } from '@mdi/js'; import { onMount, type Snippet } from 'svelte'; import { t } from 'svelte-i18n'; @@ -52,6 +53,8 @@ return new URL(page.url.pathname + page.url.search, 'https://my.immich.app'); }; + toastManager.setOptions({ class: 'top-16' }); + onMount(() => { const element = document.querySelector('#stencil'); element?.remove(); @@ -61,6 +64,10 @@ eventManager.emit('AppInit'); beforeNavigate(({ from, to }) => { + if (sidebarStore.isOpen) { + sidebarStore.reset(); + } + if (isAssetViewerRoute(from) && isAssetViewerRoute(to)) { return; } @@ -142,18 +149,19 @@ icon: mdiAccountMultipleOutline, onAction: () => goto(AppRoute.ADMIN_USERS), }, - { - title: $t('jobs'), - description: $t('admin.jobs_page_description'), - icon: mdiSync, - onAction: () => goto(AppRoute.ADMIN_JOBS), - }, { title: $t('settings'), - description: $t('admin.jobs_page_description'), + description: $t('admin.settings_page_description'), icon: mdiCog, onAction: () => goto(AppRoute.ADMIN_SETTINGS), }, + { + title: $t('admin.queues'), + description: $t('admin.queues_page_description'), + icon: mdiSync, + type: $t('page'), + onAction: () => goto(AppRoute.ADMIN_QUEUES), + }, { title: $t('external_libraries'), description: $t('admin.external_libraries_page_description'), diff --git a/web/src/routes/admin/jobs-status/+page.svelte b/web/src/routes/admin/jobs-status/+page.svelte deleted file mode 100644 index 1a61ea6b23..0000000000 --- a/web/src/routes/admin/jobs-status/+page.svelte +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - {#snippet buttons()} - - {#if pausedJobs.length > 0} - - {/if} - - - - {/snippet} -
-
- {#if jobs} - - {/if} -
-
-
diff --git a/web/src/routes/admin/jobs-status/+page.ts b/web/src/routes/admin/jobs-status/+page.ts index 90057ff969..92971ccd9a 100644 --- a/web/src/routes/admin/jobs-status/+page.ts +++ b/web/src/routes/admin/jobs-status/+page.ts @@ -1,18 +1,5 @@ -import { authenticate } from '$lib/utils/auth'; -import { getFormatter } from '$lib/utils/i18n'; -import { getQueuesLegacy } from '@immich/sdk'; +import { AppRoute } from '$lib/constants'; +import { redirect } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -export const load = (async ({ url }) => { - await authenticate(url, { admin: true }); - - const jobs = await getQueuesLegacy(); - const $t = await getFormatter(); - - return { - jobs, - meta: { - title: $t('admin.job_status'), - }, - }; -}) satisfies PageLoad; +export const load = (() => redirect(307, AppRoute.ADMIN_QUEUES)) satisfies PageLoad; diff --git a/web/src/routes/admin/library-management/+page.svelte b/web/src/routes/admin/library-management/+page.svelte index aef8447d00..9aa5af6481 100644 --- a/web/src/routes/admin/library-management/+page.svelte +++ b/web/src/routes/admin/library-management/+page.svelte @@ -1,6 +1,5 @@ + + + + + + +
+
+ {#if queues} + + {/if} +
+
+
diff --git a/web/src/routes/admin/queues/+page.ts b/web/src/routes/admin/queues/+page.ts new file mode 100644 index 0000000000..59aded520a --- /dev/null +++ b/web/src/routes/admin/queues/+page.ts @@ -0,0 +1,18 @@ +import { authenticate } from '$lib/utils/auth'; +import { getFormatter } from '$lib/utils/i18n'; +import { getQueues } from '@immich/sdk'; +import type { PageLoad } from './$types'; + +export const load = (async ({ url }) => { + await authenticate(url, { admin: true }); + + const queues = await getQueues(); + const $t = await getFormatter(); + + return { + queues, + meta: { + title: $t('admin.queues'), + }, + }; +}) satisfies PageLoad; diff --git a/web/src/routes/admin/queues/[name]/+page.svelte b/web/src/routes/admin/queues/[name]/+page.svelte new file mode 100644 index 0000000000..4eb84bef09 --- /dev/null +++ b/web/src/routes/admin/queues/[name]/+page.svelte @@ -0,0 +1,87 @@ + + + + + +
+ +
+ {item.title} + {#if queue.isPaused} + + {$t('paused')} + + {/if} +
+ {item.subtitle} + +
+ {$t('active_count', { values: { count: queue.statistics.active } })} + {$t('waiting_count', { values: { count: queue.statistics.waiting } })} + {#if queue.statistics.failed > 0} + {$t('failed_count', { values: { count: queue.statistics.failed } })} + {/if} +
+ +
+ + +
+ + {$t('admin.jobs_over_time')} +
+
+ + + +
+
+
+
+
diff --git a/web/src/routes/admin/queues/[name]/+page.ts b/web/src/routes/admin/queues/[name]/+page.ts new file mode 100644 index 0000000000..3c111abf7c --- /dev/null +++ b/web/src/routes/admin/queues/[name]/+page.ts @@ -0,0 +1,31 @@ +import { AppRoute } from '$lib/constants'; +import { fromQueueSlug } from '$lib/services/queue.service'; +import { authenticate, requestServerInfo } from '$lib/utils/auth'; +import { getFormatter } from '$lib/utils/i18n'; +import { getQueue, getQueueJobs, QueueJobStatus } from '@immich/sdk'; +import { redirect } from '@sveltejs/kit'; +import type { PageLoad } from './$types'; + +export const load = (async ({ params, url }) => { + await authenticate(url, { admin: true }); + await requestServerInfo(); + + const name = fromQueueSlug(params.name); + if (!name) { + redirect(302, AppRoute.ADMIN_QUEUES); + } + + const [queue, failedJobs] = await Promise.all([ + getQueue({ name }), + getQueueJobs({ name, status: [QueueJobStatus.Failed, QueueJobStatus.Paused] }), + ]); + const $t = await getFormatter(); + + return { + queue, + failedJobs, + meta: { + title: $t('admin.queue_details'), + }, + }; +}) satisfies PageLoad; diff --git a/web/src/routes/admin/system-settings/+page.svelte b/web/src/routes/admin/system-settings/+page.svelte index 53a0ca2e6a..f0beb082a8 100644 --- a/web/src/routes/admin/system-settings/+page.svelte +++ b/web/src/routes/admin/system-settings/+page.svelte @@ -17,7 +17,6 @@ import ThemeSettings from '$lib/components/admin-settings/ThemeSettings.svelte'; import TrashSettings from '$lib/components/admin-settings/TrashSettings.svelte'; import UserSettings from '$lib/components/admin-settings/UserSettings.svelte'; - import HeaderButton from '$lib/components/HeaderButton.svelte'; import AdminPageLayout from '$lib/components/layouts/AdminPageLayout.svelte'; import SettingAccordionState from '$lib/components/shared-components/settings/setting-accordion-state.svelte'; import SettingAccordion from '$lib/components/shared-components/settings/setting-accordion.svelte'; @@ -26,7 +25,7 @@ import { featureFlagsManager } from '$lib/managers/feature-flags-manager.svelte'; import { systemConfigManager } from '$lib/managers/system-config-manager.svelte'; import { getSystemConfigActions } from '$lib/services/system-config.service'; - import { Alert, CommandPaletteContext, HStack } from '@immich/ui'; + import { Alert, CommandPaletteContext } from '@immich/ui'; import { mdiAccountOutline, mdiBackupRestore, @@ -208,24 +207,13 @@ - - {#snippet buttons()} - - - - - - - {/snippet} - -
+ +
{#if featureFlagsManager.value.configFile} {/if} -
+
diff --git a/web/src/routes/admin/users/+page.svelte b/web/src/routes/admin/users/+page.svelte index de2c1ef85a..53d810ba21 100644 --- a/web/src/routes/admin/users/+page.svelte +++ b/web/src/routes/admin/users/+page.svelte @@ -1,12 +1,11 @@ - {#snippet buttons()} - - - - - - - - {/snippet}
{#if user.deletedAt}