diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 862b7ef45..73a4883e6 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -12,16 +12,31 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 20 + - name: Install pnpm uses: pnpm/action-setup@v4 + - name: Install dependencies run: pnpm install --frozen-lockfile + + - name: Cache Playwright browsers + uses: actions/cache@v4 + id: playwright-cache + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-playwright- + - name: Install Playwright Browsers + if: steps.playwright-cache.outputs.cache-hit != 'true' run: pnpm exec playwright install --with-deps chromium + - name: E2E Tests run: pnpm run e2e - uses: actions/upload-artifact@v4 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2a19d6fbe..b492a6b80 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -83,7 +83,7 @@ jobs: "PUBLIC_CONSOLE_MODE=cloud" "PUBLIC_CONSOLE_FEATURE_FLAGS=" "PUBLIC_APPWRITE_MULTI_REGION=true" - "PUBLIC_CONSOLE_EMAIL_VERIFICATION=true" + "PUBLIC_CONSOLE_EMAIL_VERIFICATION=false" "PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS=false" "PUBLIC_GROWTH_ENDPOINT=${{ secrets.PUBLIC_GROWTH_ENDPOINT }}" "PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY_STAGE }}" @@ -162,7 +162,7 @@ jobs: build-args: | "PUBLIC_CONSOLE_MODE=cloud" "PUBLIC_APPWRITE_MULTI_REGION=false" - "PUBLIC_CONSOLE_EMAIL_VERIFICATION=true" + "PUBLIC_CONSOLE_EMAIL_VERIFICATION=false" "PUBLIC_CONSOLE_MOCK_AI_SUGGESTIONS=false" "PUBLIC_CONSOLE_FEATURE_FLAGS=" "PUBLIC_STRIPE_KEY=${{ secrets.PUBLIC_STRIPE_KEY_STAGE }}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e322e42f4..51925b85f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,21 +17,29 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: Use Node.js uses: actions/setup-node@v3 with: node-version: 20 + - name: Install pnpm uses: pnpm/action-setup@v4 + - name: Audit dependencies run: pnpm audit --audit-level high + - name: Install dependencies run: pnpm install --frozen-lockfile + - name: Svelte Diagnostics run: pnpm run check + - name: Linter run: pnpm run lint + - name: Unit Tests run: pnpm run test + - name: Build Console run: pnpm run build diff --git a/AGENTS.md b/AGENTS.md index 82bcb13c7..38c3f89e3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -101,4 +101,23 @@ src/ 5. Before commit: `pnpm run check && pnpm run format && pnpm run lint && pnpm run test && pnpm run build` 6. **Take screenshots**: For any UI changes, capture screenshots and include them in the PR description or comments before finalizing +## Required Pre-Completion Checklist + +**CRITICAL**: Before finishing any work or marking a task complete, agents MUST run the following commands in order and ensure all pass: + +1. **`pnpm run format`** - Auto-fix all formatting issues +2. **`pnpm run check`** - Verify TypeScript/Svelte types (must show 0 errors, 0 warnings) +3. **`pnpm run lint`** - Check code style (ignore pre-existing issues in files you didn't modify) +4. **`pnpm run test`** - Run all unit tests (all tests must pass) +5. **`pnpm run build`** - Ensure production build succeeds + +If any command fails: + +- **Format/Lint**: Run `pnpm run format` to auto-fix, then re-check +- **Type errors**: Fix all TypeScript errors in files you modified +- **Test failures**: Fix failing tests or ensure failures are unrelated to your changes +- **Build failures**: Debug and resolve build issues before proceeding + +**Never skip these checks** - they are mandatory quality gates before any work is considered complete. + **Trust these instructions** - only search if incomplete/incorrect. See CONTRIBUTING.md for PR conventions. Use `--frozen-lockfile` always. Docker builds: multi-stage, final image is nginx serving static files from `/console` path. diff --git a/package.json b/package.json index d63a61808..9985734be 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "clean": "rm -rf node_modules && rm -rf .svelte_kit", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-check --tsconfig ./tsconfig.json --watch", - "format": "prettier --cache --write --cache .", + "format": "prettier --write --cache .", "lint": "prettier --check . && eslint .", "test": "TZ=EST vitest run", "test:ui": "TZ=EST vitest --ui", @@ -22,11 +22,11 @@ }, "dependencies": { "@ai-sdk/svelte": "^1.1.24", - "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7", + "@appwrite.io/console": "https://pkg.vc/-/@appwrite/@appwrite.io/console@406d8be", "@appwrite.io/pink-icons": "0.25.0", - "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@5b26bb8", + "@appwrite.io/pink-icons-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc", "@appwrite.io/pink-legacy": "^1.0.3", - "@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@33845eb", + "@appwrite.io/pink-svelte": "https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@865e2fc", "@faker-js/faker": "^9.9.0", "@popperjs/core": "^2.11.8", "@sentry/sveltekit": "^10.25.0", diff --git a/playwright.config.ts b/playwright.config.ts index 741c0788f..b0c31406f 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,7 +1,7 @@ import { type PlaywrightTestConfig } from '@playwright/test'; const config: PlaywrightTestConfig = { - timeout: 120000, + timeout: 240000, reportSlowTests: null, reporter: [['html', { open: 'never' }]], retries: 3, @@ -11,10 +11,11 @@ const config: PlaywrightTestConfig = { trace: 'on-first-retry' }, webServer: { - timeout: 120000, + timeout: 240000, env: { - PUBLIC_CONSOLE_PROFILE: '', - PUBLIC_AI_SERVICE_BASE_URL: '', + NODE_OPTIONS: '--max_old_space_size=8192', + PUBLIC_CONSOLE_PROFILE: 'console', + PUBLIC_AI_SERVICE_BASE_URL: 'http://appwrite.test/v1', PUBLIC_APPWRITE_ENDPOINT: 'https://stage.cloud.appwrite.io/v1', PUBLIC_CONSOLE_MODE: 'cloud', PUBLIC_APPWRITE_MULTI_REGION: 'true', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 68c2de5b1..3eb32415f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,22 +10,22 @@ importers: dependencies: '@ai-sdk/svelte': specifier: ^1.1.24 - version: 1.1.24(svelte@5.43.6)(zod@3.24.3) + version: 1.1.24(svelte@5.43.12)(zod@3.24.3) '@appwrite.io/console': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7 - version: https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7 + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/console@406d8be + version: https://pkg.vc/-/@appwrite/@appwrite.io/console@406d8be '@appwrite.io/pink-icons': specifier: 0.25.0 version: 0.25.0 '@appwrite.io/pink-icons-svelte': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@5b26bb8 - version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@5b26bb8(svelte@5.43.6) + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc + version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc(svelte@5.43.12) '@appwrite.io/pink-legacy': specifier: ^1.0.3 version: 1.0.3 '@appwrite.io/pink-svelte': - specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@33845eb - version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@33845eb(svelte@5.43.6) + specifier: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@865e2fc + version: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@865e2fc(svelte@5.43.12) '@faker-js/faker': specifier: ^9.9.0 version: 9.9.0 @@ -34,13 +34,13 @@ importers: version: 2.11.8 '@sentry/sveltekit': specifier: ^10.25.0 - version: 10.25.0(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + version: 10.26.0(@sveltejs/kit@2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) '@stripe/stripe-js': specifier: ^3.5.0 version: 3.5.0 ai: specifier: ^2.2.37 - version: 2.2.37(react@19.2.0)(solid-js@1.9.5)(svelte@5.43.6)(vue@3.5.13(typescript@5.9.3)) + version: 2.2.37(react@19.2.0)(solid-js@1.9.5)(svelte@5.43.12)(vue@3.5.13(typescript@5.9.3)) analytics: specifier: ^0.8.19 version: 0.8.19(@types/dlv@1.1.5) @@ -85,10 +85,10 @@ importers: version: 2.0.1 svelte-confetti: specifier: ^1.4.0 - version: 1.4.0(svelte@5.43.6) + version: 1.4.0(svelte@5.43.12) svelte-reparent: specifier: ^0.0.1 - version: 0.0.1(svelte@5.43.6) + version: 0.0.1(svelte@5.43.12) tippy.js: specifier: ^6.3.7 version: 6.3.7 @@ -104,22 +104,22 @@ importers: version: 0.0.139(react-dom@19.2.0(react@19.2.0))(react@19.2.0) '@melt-ui/pp': specifier: ^0.3.2 - version: 0.3.2(@melt-ui/svelte@0.86.6(svelte@5.43.6))(svelte@5.43.6) + version: 0.3.2(@melt-ui/svelte@0.86.6(svelte@5.43.12))(svelte@5.43.12) '@melt-ui/svelte': specifier: ^0.86.6 - version: 0.86.6(svelte@5.43.6) + version: 0.86.6(svelte@5.43.12) '@playwright/test': specifier: ^1.56.0 version: 1.56.1 '@sveltejs/adapter-static': specifier: ^3.0.10 - version: 3.0.10(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))) + version: 3.0.10(@sveltejs/kit@2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))) '@sveltejs/kit': specifier: ^2.46.2 - version: 2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + version: 2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) '@sveltejs/vite-plugin-svelte': specifier: ^5.1.1 - version: 5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + version: 5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) '@testing-library/dom': specifier: ^10.4.1 version: 10.4.1 @@ -128,7 +128,7 @@ importers: version: 6.9.1 '@testing-library/svelte': specifier: ^5.2.8 - version: 5.2.8(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))(vitest@3.2.4) + version: 5.2.8(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))(vitest@3.2.4) '@testing-library/user-event': specifier: ^14.6.1 version: 14.6.1(@testing-library/dom@10.4.1) @@ -143,16 +143,16 @@ importers: version: 2.0.8 '@typescript-eslint/eslint-plugin': specifier: ^8.46.0 - version: 8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + version: 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) '@typescript-eslint/parser': specifier: ^8.46.0 - version: 8.46.4(eslint@9.39.1)(typescript@5.9.3) + version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) '@vitest/ui': specifier: ^3.2.4 version: 3.2.4(vitest@3.2.4) color: specifier: ^5.0.2 - version: 5.0.2 + version: 5.0.3 eslint: specifier: ^9.37.0 version: 9.39.1 @@ -161,7 +161,7 @@ importers: version: 10.1.8(eslint@9.39.1) eslint-plugin-svelte: specifier: ^3.12.4 - version: 3.13.0(eslint@9.39.1)(svelte@5.43.6) + version: 3.13.0(eslint@9.39.1)(svelte@5.43.12) globals: specifier: ^16.4.0 version: 16.5.0 @@ -176,25 +176,25 @@ importers: version: 3.6.2 prettier-plugin-svelte: specifier: ^3.4.0 - version: 3.4.0(prettier@3.6.2)(svelte@5.43.6) + version: 3.4.0(prettier@3.6.2)(svelte@5.43.12) sass: specifier: ^1.93.2 - version: 1.94.0 + version: 1.94.2 svelte: specifier: ^5.39.10 - version: 5.43.6 + version: 5.43.12 svelte-check: specifier: ^4.3.2 - version: 4.3.4(picomatch@4.0.3)(svelte@5.43.6)(typescript@5.9.3) + version: 4.3.4(picomatch@4.0.3)(svelte@5.43.12)(typescript@5.9.3) svelte-preprocess: specifier: ^6.0.3 - version: 6.0.3(@babel/core@7.26.10)(postcss-load-config@3.1.4(postcss@8.5.6))(postcss@8.5.6)(sass@1.94.0)(svelte@5.43.6)(typescript@5.9.3) + version: 6.0.3(@babel/core@7.26.10)(postcss-load-config@3.1.4(postcss@8.5.6))(postcss@8.5.6)(sass@1.94.2)(svelte@5.43.12)(typescript@5.9.3) svelte-sequential-preprocessor: specifier: ^2.0.2 version: 2.0.2 tldts: specifier: ^7.0.16 - version: 7.0.17 + version: 7.0.18 tslib: specifier: ^2.8.1 version: 2.8.1 @@ -203,13 +203,13 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.46.0 - version: 8.46.4(eslint@9.39.1)(typescript@5.9.3) + version: 8.47.0(eslint@9.39.1)(typescript@5.9.3) vite: specifier: ^7.1.9 - version: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + version: 7.2.4(@types/node@22.13.14)(sass@1.94.2) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.0) + version: 3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.2) packages: @@ -278,8 +278,8 @@ packages: '@apm-js-collab/tracing-hooks@0.3.1': resolution: {integrity: sha512-Vu1CbmPURlN5fTboVuKMoJjbO5qcq9fA5YXpskx3dXe/zTBvjODFoerw+69rVBlRLrJpwPqSDqEuJDEKIrTldw==} - '@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7} + '@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@406d8be': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/console@406d8be} version: 1.10.0 '@appwrite.io/pink-icons-svelte@2.0.0-RC.1': @@ -287,8 +287,8 @@ packages: peerDependencies: svelte: ^4.0.0 - '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@5b26bb8': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@5b26bb8} + '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc} version: 2.0.0-RC.1 peerDependencies: svelte: ^4.0.0 @@ -302,8 +302,8 @@ packages: '@appwrite.io/pink-legacy@1.0.3': resolution: {integrity: sha512-GGde5fmPhs+s6/3aFeMPc/kKADG/gTFkYQSy6oBN8pK0y0XNCLrZZgBv+EBbdhwdtqVEWXa0X85Mv9w7jcIlwQ==} - '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@33845eb': - resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@33845eb} + '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@865e2fc': + resolution: {tarball: https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@865e2fc} version: 2.0.0-RC.2 peerDependencies: svelte: ^4.0.0 @@ -1095,28 +1095,28 @@ packages: cpu: [x64] os: [win32] - '@sentry-internal/browser-utils@10.25.0': - resolution: {integrity: sha512-wzg1ITZxrRtQouHPCgpt3tl1GiNAWFVy2RYK2KstFEhpYBAOUn9BAdP7KU9UyHBFKqbAvV4oGtAT8H2/Y4+leA==} + '@sentry-internal/browser-utils@10.26.0': + resolution: {integrity: sha512-rPg1+JZlfp912pZONQAWZzbSaZ9L6R2VrMcCEa+2e2Gqk9um4b+LqF5RQWZsbt5Z0n0azSy/KQ6zAe/zTPXSOg==} engines: {node: '>=18'} - '@sentry-internal/feedback@10.25.0': - resolution: {integrity: sha512-qlbT4tOd+WRyKpLdsbi26rkynGBoVabnY8/9rFnTxZ0WIUG5EFhJFqEeRLMyv+uk0uRFF3H0I9+u+qP/BKxIcQ==} + '@sentry-internal/feedback@10.26.0': + resolution: {integrity: sha512-0vk9eQP0CXD7Y2WkcCIWHaAqnXOAi18/GupgWLnbB2kuQVYVtStWxtW+OWRe8W/XwSnZ5m6JBTVeokuk/O16DQ==} engines: {node: '>=18'} - '@sentry-internal/replay-canvas@10.25.0': - resolution: {integrity: sha512-zuj5jVNswZ/aA1nPPbU+VIFkQG0695lbyIfS1Skq+5o2FdRIS3MGnBXw1abI9h4pft8GLQWcKiBxISM7UpSz6w==} + '@sentry-internal/replay-canvas@10.26.0': + resolution: {integrity: sha512-vs7d/P+8M1L1JVAhhJx2wo15QDhqAipnEQvuRZ6PV7LUcS1un9/Vx49FMxpIkx6JcKADJVwtXrS1sX2hoNT/kw==} engines: {node: '>=18'} - '@sentry-internal/replay@10.25.0': - resolution: {integrity: sha512-V/kKQn9T46HBTiP0bIThmpVr94K4vXwYM3/EHVpGSq4P9RynX06cgps8GLHq94+A0kX/DbK9igEMZmIuzS1q3A==} + '@sentry-internal/replay@10.26.0': + resolution: {integrity: sha512-FMySQnY2/p0dVtFUBgUO+aMdK2ovqnd7Q/AkvMQUsN/5ulyj6KZx3JX3CqOqRtAr1izoCe4Kh2pi5t//sQmvsg==} engines: {node: '>=18'} '@sentry/babel-plugin-component-annotate@4.6.0': resolution: {integrity: sha512-3soTX50JPQQ51FSbb4qvNBf4z/yP7jTdn43vMTp9E4IxvJ9HKJR7OEuKkCMszrZmWsVABXl02msqO7QisePdiQ==} engines: {node: '>= 14'} - '@sentry/browser@10.25.0': - resolution: {integrity: sha512-UgSVT3RTM3vsK914TPuHVJQsjq5ooXVmjMtsWP3Ep+6f7N+1UVX4ZXsyyj5lDOcWdc79FgproD+MrEf9Cj6uBg==} + '@sentry/browser@10.26.0': + resolution: {integrity: sha512-uvV4hnkt8bh8yP0disJ0fszy8FdnkyGtzyIVKdeQZbNUefwbDhd3H0KJrAHhJ5ocULMH3B+dipdPmw2QXbEflg==} engines: {node: '>=18'} '@sentry/bundler-plugin-core@4.6.0': @@ -1175,8 +1175,8 @@ packages: engines: {node: '>= 10'} hasBin: true - '@sentry/cloudflare@10.25.0': - resolution: {integrity: sha512-oafTyQ1CBTOK3GJhSoxdzAQVlr/l0v5WspwkMIa1bUXqLlOHwmcyZZ1CyoaLoA4gJ1wYL2kONjNwtoNM0utJsw==} + '@sentry/cloudflare@10.26.0': + resolution: {integrity: sha512-iBFFEuzin3rpFEOIQ/y3QYPBOAJmHHyAtdEicNFp2R4FvRZJ+Ut3nHV5gSMbwsiArCyfFFKz101/CNdSj569wQ==} engines: {node: '>=18'} peerDependencies: '@cloudflare/workers-types': ^4.x @@ -1184,12 +1184,12 @@ packages: '@cloudflare/workers-types': optional: true - '@sentry/core@10.25.0': - resolution: {integrity: sha512-mGi4BYIPwZjWdOXHrPoXz1AW4/cQbFoiuW/m+OOATmtSoGTDnWYwP+qZU7VLlL+v8ZEzxfPi2C1NPfJtPj7QWA==} + '@sentry/core@10.26.0': + resolution: {integrity: sha512-TjDe5QI37SLuV0q3nMOH8JcPZhv2e85FALaQMIhRILH9Ce6G7xW5GSjmH91NUVq8yc3XtiqYlz/EenEZActc4Q==} engines: {node: '>=18'} - '@sentry/node-core@10.25.0': - resolution: {integrity: sha512-Hk0s7r9pkotZ1yfUc9+XX0ALDQ/bjaYsWF23O2q8Yfc4m8NcQio54ztAmdI+Yf+YiHLpt0x9Hlgwpl3AaRvwIA==} + '@sentry/node-core@10.26.0': + resolution: {integrity: sha512-7OrHVn8XAsq9mMVMlpL18XTKQEVcLOJSo0n2M7QGKfFk/OfVtSFMcUWGqN1qhYtT9aMTr2bjtR5+BI33djnNTQ==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 @@ -1200,12 +1200,12 @@ packages: '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 '@opentelemetry/semantic-conventions': ^1.37.0 - '@sentry/node@10.25.0': - resolution: {integrity: sha512-++mugiYF8X7CLtpymGN3N4J40SvQVIsVa6K7pURhooT4eX1QXYOBJSaOqvOXk5GN4qed5wETHNBkZuXSO0RARQ==} + '@sentry/node@10.26.0': + resolution: {integrity: sha512-VUwNoKYhRpnHQSj9lty1TgooO+1wcpS1V0K87HU8sZEas5gx3Ujiouk5ocPjlgbKreoYOApgOnEEIq5W/hfQcQ==} engines: {node: '>=18'} - '@sentry/opentelemetry@10.25.0': - resolution: {integrity: sha512-AWCRzUIzvI+0RHXTmGvVx+MUtyyjwmC6F6d6XCnWhBKWGO52I+ucz1X8INIZxCrK05dpviFpeLZy+pzfgw892g==} + '@sentry/opentelemetry@10.26.0': + resolution: {integrity: sha512-ASJdOwn6NwMH2ZeBrnGJI+l/xkJp1AOiQ5FWkvTqLc/vHX+r3PDMO7c+koecY+LiZxSzZF4IV8sALXfOh6UnwA==} engines: {node: '>=18'} peerDependencies: '@opentelemetry/api': ^1.9.0 @@ -1214,14 +1214,14 @@ packages: '@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0 '@opentelemetry/semantic-conventions': ^1.37.0 - '@sentry/svelte@10.25.0': - resolution: {integrity: sha512-JZ4HmPG6MKmuwZcV+q4XysitQbfvsHRiCsuiNKoXY5SYVII5/At2xBK28BcM7pS33SWPQShBT4UfXTeyuicYZA==} + '@sentry/svelte@10.26.0': + resolution: {integrity: sha512-dvSPx6E6Q9ggNaAmQARKcJ9tQEosUenX2l8MrZ1yCPdrRsimGGCA8VEMtfd9JPuZhEBaretrCk30QwpOsEH7kQ==} engines: {node: '>=18'} peerDependencies: svelte: 3.x || 4.x || 5.x - '@sentry/sveltekit@10.25.0': - resolution: {integrity: sha512-Ikf9GJzmH3rLKmkJGg66Lk5z9awXpG5/5MKptNnXLaRbPb7w/OZJXxlUb4OkW4gD2sWP23XoIMtRCmibPHRODw==} + '@sentry/sveltekit@10.26.0': + resolution: {integrity: sha512-ZbhuiIp8jpTveCYP4sk7lCFVXAL1rqZSO+fu8VNPYxD/gzHqaRaj3NX5xnpynxsg9JeNCI8HqX8gNH5SRRYHbg==} engines: {node: '>=18'} peerDependencies: '@sveltejs/kit': 2.x @@ -1272,8 +1272,8 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 - '@sveltejs/kit@2.48.4': - resolution: {integrity: sha512-TGFX1pZUt9qqY20Cv5NyYvy0iLWHf2jXi8s+eCGsig7jQMdwZWKUFMR6TbvFNhfDSUpc1sH/Y5EHv20g3HHA3g==} + '@sveltejs/kit@2.48.5': + resolution: {integrity: sha512-/rnwfSWS3qwUSzvHynUTORF9xSJi7PCR9yXkxUOnRrNqyKmCmh3FPHH+E9BbgqxXfTevGXBqgnlh9kMb+9T5XA==} engines: {node: '>=18.13'} hasBin: true peerDependencies: @@ -1407,63 +1407,63 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@typescript-eslint/eslint-plugin@8.46.4': - resolution: {integrity: sha512-R48VhmTJqplNyDxCyqqVkFSZIx1qX6PzwqgcXn1olLrzxcSBDlOsbtcnQuQhNtnNiJ4Xe5gREI1foajYaYU2Vg==} + '@typescript-eslint/eslint-plugin@8.47.0': + resolution: {integrity: sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.46.4 + '@typescript-eslint/parser': ^8.47.0 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.46.4': - resolution: {integrity: sha512-tK3GPFWbirvNgsNKto+UmB/cRtn6TZfyw0D6IKrW55n6Vbs7KJoZtI//kpTKzE/DUmmnAFD8/Ca46s7Obs92/w==} + '@typescript-eslint/parser@8.47.0': + resolution: {integrity: sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==} 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.46.4': - resolution: {integrity: sha512-nPiRSKuvtTN+no/2N1kt2tUh/HoFzeEgOm9fQ6XQk4/ApGqjx0zFIIaLJ6wooR1HIoozvj2j6vTi/1fgAz7UYQ==} + '@typescript-eslint/project-service@8.47.0': + resolution: {integrity: sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/scope-manager@8.46.4': - resolution: {integrity: sha512-tMDbLGXb1wC+McN1M6QeDx7P7c0UWO5z9CXqp7J8E+xGcJuUuevWKxuG8j41FoweS3+L41SkyKKkia16jpX7CA==} + '@typescript-eslint/scope-manager@8.47.0': + resolution: {integrity: sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.46.4': - resolution: {integrity: sha512-+/XqaZPIAk6Cjg7NWgSGe27X4zMGqrFqZ8atJsX3CWxH/jACqWnrWI68h7nHQld0y+k9eTTjb9r+KU4twLoo9A==} + '@typescript-eslint/tsconfig-utils@8.47.0': + resolution: {integrity: sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/type-utils@8.46.4': - resolution: {integrity: sha512-V4QC8h3fdT5Wro6vANk6eojqfbv5bpwHuMsBcJUJkqs2z5XnYhJzyz9Y02eUmF9u3PgXEUiOt4w4KHR3P+z0PQ==} + '@typescript-eslint/type-utils@8.47.0': + resolution: {integrity: sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==} 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.46.4': - resolution: {integrity: sha512-USjyxm3gQEePdUwJBFjjGNG18xY9A2grDVGuk7/9AkjIF1L+ZrVnwR5VAU5JXtUnBL/Nwt3H31KlRDaksnM7/w==} + '@typescript-eslint/types@8.47.0': + resolution: {integrity: sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.46.4': - resolution: {integrity: sha512-7oV2qEOr1d4NWNmpXLR35LvCfOkTNymY9oyW+lUHkmCno7aOmIf/hMaydnJBUTBMRCOGZh8YjkFOc8dadEoNGA==} + '@typescript-eslint/typescript-estree@8.47.0': + resolution: {integrity: sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/utils@8.46.4': - resolution: {integrity: sha512-AbSv11fklGXV6T28dp2Me04Uw90R2iJ30g2bgLz529Koehrmkbs1r7paFqr1vPCZi7hHwYxYtxfyQMRC8QaVSg==} + '@typescript-eslint/utils@8.47.0': + resolution: {integrity: sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==} 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.46.4': - resolution: {integrity: sha512-/++5CYLQqsO9HFGLI7APrxBJYo+5OCMpViuhV8q5/Qa3o5mMrF//eQHks+PXcsAVaLdn817fMuS7zqoXNNZGaw==} + '@typescript-eslint/visitor-keys@8.47.0': + resolution: {integrity: sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.3.0': @@ -1542,6 +1542,11 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -1727,8 +1732,8 @@ packages: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} - color-convert@3.1.0: - resolution: {integrity: sha512-TVoqAq8ZDIpK5lsQY874DDnu65CSsc9vzq0wLpNQ6UMBq81GSZocVazPiBbYGzngzBOIRahpkTzCLVe2at4MfA==} + color-convert@3.1.3: + resolution: {integrity: sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==} engines: {node: '>=14.6'} color-name@1.1.4: @@ -1738,12 +1743,12 @@ packages: resolution: {integrity: sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==} engines: {node: '>=12.20'} - color-string@2.0.1: - resolution: {integrity: sha512-5z9FbYTZPAo8iKsNEqRNv+OlpBbDcoE+SY9GjLfDUHEfcNNV7tS9eSAlFHEaub/r5tBL9LtskAeq1l9SaoZ5tQ==} + color-string@2.1.4: + resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==} engines: {node: '>=18'} - color@5.0.2: - resolution: {integrity: sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA==} + color@5.0.3: + resolution: {integrity: sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==} engines: {node: '>=18'} comma-separated-tokens@2.0.3: @@ -2101,8 +2106,8 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - esrap@2.1.2: - resolution: {integrity: sha512-DgvlIQeowRNyvLPWW4PT7Gu13WznY288Du086E751mwwbsgr29ytBiYeLzAGIo0qk3Ujob0SDk8TiSaM5WQzNg==} + esrap@2.1.3: + resolution: {integrity: sha512-T/Dhhv/QH+yYmiaLz9SA3PW+YyenlnRKDNdtlYJrSOBmNsH4nvPux+mTwx7p+wAedlJrGoZtXNI0a0MjQ2QkVg==} esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} @@ -2974,8 +2979,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - sass@1.94.0: - resolution: {integrity: sha512-Dqh7SiYcaFtdv5Wvku6QgS5IGPm281L+ZtVD1U2FJa7Q0EFRlq8Z3sjYtz6gYObsYThUOz9ArwFqPZx+1azILQ==} + sass@1.94.2: + resolution: {integrity: sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==} engines: {node: '>=14.0.0'} hasBin: true @@ -3206,8 +3211,8 @@ packages: resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} engines: {node: '>=16'} - svelte@5.43.6: - resolution: {integrity: sha512-RnyO9VXI85Bmsf4b8AuQFBKFYL3LKUl+ZrifOjvlrQoboAROj5IITVLK1yOXBjwUWUn2BI5cfmurktgCzuZ5QA==} + svelte@5.43.12: + resolution: {integrity: sha512-d1R+3pFa39LXoHCsxHmV//D2pSFZlEMlnxCVQ54TlrQv+4o5pewJO0/Pc5MUp+j71PJrOrPJHTvREZJHn+ymDQ==} engines: {node: '>=18'} swr-store@0.10.6: @@ -3274,15 +3279,15 @@ packages: tldts-core@6.1.85: resolution: {integrity: sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==} - tldts-core@7.0.17: - resolution: {integrity: sha512-DieYoGrP78PWKsrXr8MZwtQ7GLCUeLxihtjC1jZsW1DnvSMdKPitJSe8OSYDM2u5H6g3kWJZpePqkp43TfLh0g==} + tldts-core@7.0.18: + resolution: {integrity: sha512-jqJC13oP4FFAahv4JT/0WTDrCF9Okv7lpKtOZUGPLiAnNbACcSg8Y8T+Z9xthOmRBqi/Sob4yi0TE0miRCvF7Q==} tldts@6.1.85: resolution: {integrity: sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==} hasBin: true - tldts@7.0.17: - resolution: {integrity: sha512-Y1KQBgDd/NUc+LfOtKS6mNsC9CCaH+m2P1RoIZy7RAPo3C3/t8X45+zgut31cRZtZ3xKPjfn3TkGTrctC2TQIQ==} + tldts@7.0.18: + resolution: {integrity: sha512-lCcgTAgMxQ1JKOWrVGo6E69Ukbnx4Gc1wiYLRf6J5NN4HRYJtCby1rPF8rkQ4a6qqoFBK5dvjJ1zJ0F7VfDSvw==} hasBin: true to-regex-range@5.0.1: @@ -3329,8 +3334,8 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typescript-eslint@8.46.4: - resolution: {integrity: sha512-KALyxkpYV5Ix7UhvjTwJXZv76VWsHG+NjNlt/z+a17SOQSiOcBdUXdbJdyXi7RPxrBFECtFOiPwUJQusJuCqrg==} + typescript-eslint@8.47.0: + resolution: {integrity: sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3390,8 +3395,8 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@7.2.2: - resolution: {integrity: sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==} + vite@7.2.4: + resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -3601,12 +3606,12 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/svelte@1.1.24(svelte@5.43.6)(zod@3.24.3)': + '@ai-sdk/svelte@1.1.24(svelte@5.43.12)(zod@3.24.3)': dependencies: '@ai-sdk/provider-utils': 2.1.13(zod@3.24.3) '@ai-sdk/ui-utils': 1.1.19(zod@3.24.3) optionalDependencies: - svelte: 5.43.6 + svelte: 5.43.12 transitivePeerDependencies: - zod @@ -3667,15 +3672,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@5ce6dc7': {} + '@appwrite.io/console@https://pkg.vc/-/@appwrite/@appwrite.io/console@406d8be': {} - '@appwrite.io/pink-icons-svelte@2.0.0-RC.1(svelte@5.43.6)': + '@appwrite.io/pink-icons-svelte@2.0.0-RC.1(svelte@5.43.12)': dependencies: - svelte: 5.43.6 + svelte: 5.43.12 - '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@5b26bb8(svelte@5.43.6)': + '@appwrite.io/pink-icons-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-icons-svelte@865e2fc(svelte@5.43.12)': dependencies: - svelte: 5.43.6 + svelte: 5.43.12 '@appwrite.io/pink-icons@0.25.0': {} @@ -3686,21 +3691,21 @@ snapshots: '@appwrite.io/pink-icons': 1.0.0 the-new-css-reset: 1.11.3 - '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@33845eb(svelte@5.43.6)': + '@appwrite.io/pink-svelte@https://pkg.vc/-/@appwrite/@appwrite.io/pink-svelte@865e2fc(svelte@5.43.12)': dependencies: - '@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.43.6) + '@appwrite.io/pink-icons-svelte': 2.0.0-RC.1(svelte@5.43.12) '@floating-ui/dom': 1.6.13 - '@melt-ui/pp': 0.3.2(@melt-ui/svelte@0.86.6(svelte@5.43.6))(svelte@5.43.6) - '@melt-ui/svelte': 0.86.6(svelte@5.43.6) - '@tanstack/svelte-virtual': 3.13.12(svelte@5.43.6) + '@melt-ui/pp': 0.3.2(@melt-ui/svelte@0.86.6(svelte@5.43.12))(svelte@5.43.12) + '@melt-ui/svelte': 0.86.6(svelte@5.43.12) + '@tanstack/svelte-virtual': 3.13.12(svelte@5.43.12) ansicolor: 2.0.3 d3: 7.9.0 fuse.js: 7.1.0 pretty-bytes: 6.1.1 shiki: 1.29.2 - svelte: 5.43.6 - svelte-motion: 0.12.2(svelte@5.43.6) - svelte-sonner: 0.3.28(svelte@5.43.6) + svelte: 5.43.12 + svelte-motion: 0.12.2(svelte@5.43.12) + svelte-sonner: 0.3.28(svelte@5.43.12) '@asamuzakjp/css-color@3.1.1': dependencies: @@ -4022,14 +4027,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@melt-ui/pp@0.3.2(@melt-ui/svelte@0.86.6(svelte@5.43.6))(svelte@5.43.6)': + '@melt-ui/pp@0.3.2(@melt-ui/svelte@0.86.6(svelte@5.43.12))(svelte@5.43.12)': dependencies: - '@melt-ui/svelte': 0.86.6(svelte@5.43.6) + '@melt-ui/svelte': 0.86.6(svelte@5.43.12) estree-walker: 3.0.3 magic-string: 0.30.17 - svelte: 5.43.6 + svelte: 5.43.12 - '@melt-ui/svelte@0.86.6(svelte@5.43.6)': + '@melt-ui/svelte@0.86.6(svelte@5.43.12)': dependencies: '@floating-ui/core': 1.6.9 '@floating-ui/dom': 1.6.13 @@ -4037,7 +4042,7 @@ snapshots: dequal: 2.0.3 focus-trap: 7.6.4 nanoid: 5.1.6 - svelte: 5.43.6 + svelte: 5.43.12 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -4444,33 +4449,33 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.46.2': optional: true - '@sentry-internal/browser-utils@10.25.0': + '@sentry-internal/browser-utils@10.26.0': dependencies: - '@sentry/core': 10.25.0 + '@sentry/core': 10.26.0 - '@sentry-internal/feedback@10.25.0': + '@sentry-internal/feedback@10.26.0': dependencies: - '@sentry/core': 10.25.0 + '@sentry/core': 10.26.0 - '@sentry-internal/replay-canvas@10.25.0': + '@sentry-internal/replay-canvas@10.26.0': dependencies: - '@sentry-internal/replay': 10.25.0 - '@sentry/core': 10.25.0 + '@sentry-internal/replay': 10.26.0 + '@sentry/core': 10.26.0 - '@sentry-internal/replay@10.25.0': + '@sentry-internal/replay@10.26.0': dependencies: - '@sentry-internal/browser-utils': 10.25.0 - '@sentry/core': 10.25.0 + '@sentry-internal/browser-utils': 10.26.0 + '@sentry/core': 10.26.0 '@sentry/babel-plugin-component-annotate@4.6.0': {} - '@sentry/browser@10.25.0': + '@sentry/browser@10.26.0': dependencies: - '@sentry-internal/browser-utils': 10.25.0 - '@sentry-internal/feedback': 10.25.0 - '@sentry-internal/replay': 10.25.0 - '@sentry-internal/replay-canvas': 10.25.0 - '@sentry/core': 10.25.0 + '@sentry-internal/browser-utils': 10.26.0 + '@sentry-internal/feedback': 10.26.0 + '@sentry-internal/replay': 10.26.0 + '@sentry-internal/replay-canvas': 10.26.0 + '@sentry/core': 10.26.0 '@sentry/bundler-plugin-core@4.6.0': dependencies: @@ -4530,14 +4535,14 @@ snapshots: - encoding - supports-color - '@sentry/cloudflare@10.25.0': + '@sentry/cloudflare@10.26.0': dependencies: '@opentelemetry/api': 1.9.0 - '@sentry/core': 10.25.0 + '@sentry/core': 10.26.0 - '@sentry/core@10.25.0': {} + '@sentry/core@10.26.0': {} - '@sentry/node-core@10.25.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.204.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)': + '@sentry/node-core@10.26.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.204.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)': dependencies: '@apm-js-collab/tracing-hooks': 0.3.1 '@opentelemetry/api': 1.9.0 @@ -4547,13 +4552,13 @@ snapshots: '@opentelemetry/resources': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.38.0 - '@sentry/core': 10.25.0 - '@sentry/opentelemetry': 10.25.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) + '@sentry/core': 10.26.0 + '@sentry/opentelemetry': 10.26.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) import-in-the-middle: 1.15.0 transitivePeerDependencies: - supports-color - '@sentry/node@10.25.0': + '@sentry/node@10.26.0': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 2.2.0(@opentelemetry/api@1.9.0) @@ -4585,44 +4590,44 @@ snapshots: '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.38.0 '@prisma/instrumentation': 6.15.0(@opentelemetry/api@1.9.0) - '@sentry/core': 10.25.0 - '@sentry/node-core': 10.25.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.204.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) - '@sentry/opentelemetry': 10.25.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) + '@sentry/core': 10.26.0 + '@sentry/node-core': 10.26.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.204.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) + '@sentry/opentelemetry': 10.26.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0) import-in-the-middle: 1.15.0 minimatch: 9.0.5 transitivePeerDependencies: - supports-color - '@sentry/opentelemetry@10.25.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)': + '@sentry/opentelemetry@10.26.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.2.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.38.0)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/context-async-hooks': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/core': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 2.2.0(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.38.0 - '@sentry/core': 10.25.0 + '@sentry/core': 10.26.0 - '@sentry/svelte@10.25.0(svelte@5.43.6)': + '@sentry/svelte@10.26.0(svelte@5.43.12)': dependencies: - '@sentry/browser': 10.25.0 - '@sentry/core': 10.25.0 + '@sentry/browser': 10.26.0 + '@sentry/core': 10.26.0 magic-string: 0.30.21 - svelte: 5.43.6 + svelte: 5.43.12 - '@sentry/sveltekit@10.25.0(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))': + '@sentry/sveltekit@10.26.0(@sveltejs/kit@2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))': dependencies: '@babel/parser': 7.26.9 - '@sentry/cloudflare': 10.25.0 - '@sentry/core': 10.25.0 - '@sentry/node': 10.25.0 - '@sentry/svelte': 10.25.0(svelte@5.43.6) + '@sentry/cloudflare': 10.26.0 + '@sentry/core': 10.26.0 + '@sentry/node': 10.26.0 + '@sentry/svelte': 10.26.0(svelte@5.43.12) '@sentry/vite-plugin': 4.6.0 - '@sveltejs/kit': 2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + '@sveltejs/kit': 2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) magic-string: 0.30.7 recast: 0.23.11 sorcery: 1.0.0 optionalDependencies: - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) transitivePeerDependencies: - '@cloudflare/workers-types' - encoding @@ -4680,15 +4685,15 @@ snapshots: dependencies: acorn: 8.15.0 - '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))': + '@sveltejs/adapter-static@3.0.10(@sveltejs/kit@2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))': dependencies: - '@sveltejs/kit': 2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + '@sveltejs/kit': 2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) - '@sveltejs/kit@2.48.4(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))': + '@sveltejs/kit@2.48.5(@opentelemetry/api@1.9.0)(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))': dependencies: '@standard-schema/spec': 1.0.0 '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0) - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) '@types/cookie': 0.6.0 acorn: 8.15.0 cookie: 0.6.0 @@ -4700,30 +4705,30 @@ snapshots: sade: 1.8.1 set-cookie-parser: 2.7.1 sirv: 3.0.1 - svelte: 5.43.6 - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + svelte: 5.43.12 + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) optionalDependencies: '@opentelemetry/api': 1.9.0 - '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))': + '@sveltejs/vite-plugin-svelte-inspector@4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))': dependencies: - '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + '@sveltejs/vite-plugin-svelte': 5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) debug: 4.4.1 - svelte: 5.43.6 - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + svelte: 5.43.12 + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) transitivePeerDependencies: - supports-color - '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))': + '@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))': dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)))(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + '@sveltejs/vite-plugin-svelte-inspector': 4.0.1(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)))(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) debug: 4.4.1 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.21 - svelte: 5.43.6 - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) - vitefu: 1.0.6(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + svelte: 5.43.12 + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) + vitefu: 1.0.6(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) transitivePeerDependencies: - supports-color @@ -4731,10 +4736,10 @@ snapshots: dependencies: tslib: 2.8.1 - '@tanstack/svelte-virtual@3.13.12(svelte@5.43.6)': + '@tanstack/svelte-virtual@3.13.12(svelte@5.43.12)': dependencies: '@tanstack/virtual-core': 3.13.12 - svelte: 5.43.6 + svelte: 5.43.12 '@tanstack/virtual-core@3.13.12': {} @@ -4758,13 +4763,13 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/svelte@5.2.8(svelte@5.43.6)(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))(vitest@3.2.4)': + '@testing-library/svelte@5.2.8(svelte@5.43.12)(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))(vitest@3.2.4)': dependencies: '@testing-library/dom': 10.4.1 - svelte: 5.43.6 + svelte: 5.43.12 optionalDependencies: - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) - vitest: 3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.0) + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) + vitest: 3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.2) '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': dependencies: @@ -4839,14 +4844,14 @@ snapshots: '@types/unist@3.0.3': {} - '@typescript-eslint/eslint-plugin@8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/scope-manager': 8.46.4 - '@typescript-eslint/type-utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/type-utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.47.0 eslint: 9.39.1 graphemer: 1.4.0 ignore: 7.0.5 @@ -4856,41 +4861,41 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.46.4 - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.47.0 debug: 4.4.1 eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.46.4(typescript@5.9.3)': + '@typescript-eslint/project-service@8.47.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3) - '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 debug: 4.4.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.46.4': + '@typescript-eslint/scope-manager@8.47.0': dependencies: - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/visitor-keys': 8.47.0 - '@typescript-eslint/tsconfig-utils@8.46.4(typescript@5.9.3)': + '@typescript-eslint/tsconfig-utils@8.47.0(typescript@5.9.3)': dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.4(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) debug: 4.4.1 eslint: 9.39.1 ts-api-utils: 2.1.0(typescript@5.9.3) @@ -4898,14 +4903,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.46.4': {} + '@typescript-eslint/types@8.47.0': {} - '@typescript-eslint/typescript-estree@8.46.4(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.47.0(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.46.4(typescript@5.9.3) - '@typescript-eslint/tsconfig-utils': 8.46.4(typescript@5.9.3) - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/visitor-keys': 8.46.4 + '@typescript-eslint/project-service': 8.47.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.47.0(typescript@5.9.3) + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/visitor-keys': 8.47.0 debug: 4.4.1 fast-glob: 3.3.3 is-glob: 4.0.3 @@ -4916,20 +4921,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.4(eslint@9.39.1)(typescript@5.9.3)': + '@typescript-eslint/utils@8.47.0(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) - '@typescript-eslint/scope-manager': 8.46.4 - '@typescript-eslint/types': 8.46.4 - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.47.0 + '@typescript-eslint/types': 8.47.0 + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.46.4': + '@typescript-eslint/visitor-keys@8.47.0': dependencies: - '@typescript-eslint/types': 8.46.4 + '@typescript-eslint/types': 8.47.0 eslint-visitor-keys: 4.2.1 '@ungap/structured-clone@1.3.0': {} @@ -4942,13 +4947,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0))': + '@vitest/mocker@3.2.4(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) '@vitest/pretty-format@3.2.4': dependencies: @@ -4979,7 +4984,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.0) + vitest: 3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.2) '@vitest/utils@3.2.4': dependencies: @@ -5049,6 +5054,8 @@ snapshots: dependencies: acorn: 8.15.0 + acorn@8.14.1: {} + acorn@8.15.0: {} agent-base@6.0.2: @@ -5059,19 +5066,19 @@ snapshots: agent-base@7.1.3: {} - ai@2.2.37(react@19.2.0)(solid-js@1.9.5)(svelte@5.43.6)(vue@3.5.13(typescript@5.9.3)): + ai@2.2.37(react@19.2.0)(solid-js@1.9.5)(svelte@5.43.12)(vue@3.5.13(typescript@5.9.3)): dependencies: eventsource-parser: 1.0.0 nanoid: 3.3.6 solid-swr-store: 0.10.7(solid-js@1.9.5)(swr-store@0.10.6) - sswr: 2.0.0(svelte@5.43.6) + sswr: 2.0.0(svelte@5.43.12) swr: 2.2.0(react@19.2.0) swr-store: 0.10.6 swrv: 1.0.4(vue@3.5.13(typescript@5.9.3)) optionalDependencies: react: 19.2.0 solid-js: 1.9.5 - svelte: 5.43.6 + svelte: 5.43.12 vue: 3.5.13(typescript@5.9.3) ajv@6.12.6: @@ -5242,7 +5249,7 @@ snapshots: dependencies: color-name: 1.1.4 - color-convert@3.1.0: + color-convert@3.1.3: dependencies: color-name: 2.0.0 @@ -5250,14 +5257,14 @@ snapshots: color-name@2.0.0: {} - color-string@2.0.1: + color-string@2.1.4: dependencies: color-name: 2.0.0 - color@5.0.2: + color@5.0.3: dependencies: - color-convert: 3.1.0 - color-string: 2.0.1 + color-convert: 3.1.3 + color-string: 2.1.4 comma-separated-tokens@2.0.3: {} @@ -5601,7 +5608,7 @@ snapshots: dependencies: eslint: 9.39.1 - eslint-plugin-svelte@3.13.0(eslint@9.39.1)(svelte@5.43.6): + eslint-plugin-svelte@3.13.0(eslint@9.39.1)(svelte@5.43.12): dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1) '@jridgewell/sourcemap-codec': 1.5.5 @@ -5613,9 +5620,9 @@ snapshots: postcss-load-config: 3.1.4(postcss@8.5.6) postcss-safe-parser: 7.0.1(postcss@8.5.6) semver: 7.7.1 - svelte-eslint-parser: 1.4.0(svelte@5.43.6) + svelte-eslint-parser: 1.4.0(svelte@5.43.12) optionalDependencies: - svelte: 5.43.6 + svelte: 5.43.12 transitivePeerDependencies: - ts-node @@ -5681,7 +5688,7 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@2.1.2: + esrap@2.1.3: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -6364,10 +6371,10 @@ snapshots: prelude-ls@1.2.1: {} - prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.6): + prettier-plugin-svelte@3.4.0(prettier@3.6.2)(svelte@5.43.12): dependencies: prettier: 3.6.2 - svelte: 5.43.6 + svelte: 5.43.12 prettier@3.6.2: {} @@ -6512,7 +6519,7 @@ snapshots: safer-buffer@2.1.2: {} - sass@1.94.0: + sass@1.94.2: dependencies: chokidar: 4.0.3 immutable: 5.1.1 @@ -6636,9 +6643,9 @@ snapshots: sprintf-js@1.0.3: {} - sswr@2.0.0(svelte@5.43.6): + sswr@2.0.0(svelte@5.43.12): dependencies: - svelte: 5.43.6 + svelte: 5.43.12 swrev: 4.0.0 stackback@0.0.2: {} @@ -6676,23 +6683,23 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.43.6)(typescript@5.9.3): + svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.43.12)(typescript@5.9.3): dependencies: '@jridgewell/trace-mapping': 0.3.25 chokidar: 4.0.3 fdir: 6.4.6(picomatch@4.0.3) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.43.6 + svelte: 5.43.12 typescript: 5.9.3 transitivePeerDependencies: - picomatch - svelte-confetti@1.4.0(svelte@5.43.6): + svelte-confetti@1.4.0(svelte@5.43.12): dependencies: - svelte: 5.43.6 + svelte: 5.43.12 - svelte-eslint-parser@1.4.0(svelte@5.43.6): + svelte-eslint-parser@1.4.0(svelte@5.43.12): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -6701,47 +6708,47 @@ snapshots: postcss-scss: 4.0.9(postcss@8.5.6) postcss-selector-parser: 7.1.0 optionalDependencies: - svelte: 5.43.6 + svelte: 5.43.12 - svelte-motion@0.12.2(svelte@5.43.6): + svelte-motion@0.12.2(svelte@5.43.12): dependencies: '@types/react': 18.3.23 framesync: 6.1.2 popmotion: 11.0.5 style-value-types: 5.1.2 - svelte: 5.43.6 + svelte: 5.43.12 tslib: 2.8.1 - svelte-preprocess@6.0.3(@babel/core@7.26.10)(postcss-load-config@3.1.4(postcss@8.5.6))(postcss@8.5.6)(sass@1.94.0)(svelte@5.43.6)(typescript@5.9.3): + svelte-preprocess@6.0.3(@babel/core@7.26.10)(postcss-load-config@3.1.4(postcss@8.5.6))(postcss@8.5.6)(sass@1.94.2)(svelte@5.43.12)(typescript@5.9.3): dependencies: - svelte: 5.43.6 + svelte: 5.43.12 optionalDependencies: '@babel/core': 7.26.10 postcss: 8.5.6 postcss-load-config: 3.1.4(postcss@8.5.6) - sass: 1.94.0 + sass: 1.94.2 typescript: 5.9.3 - svelte-reparent@0.0.1(svelte@5.43.6): + svelte-reparent@0.0.1(svelte@5.43.12): dependencies: - svelte: 5.43.6 + svelte: 5.43.12 svelte-sequential-preprocessor@2.0.2: dependencies: svelte: 4.2.19 tslib: 2.7.0 - svelte-sonner@0.3.28(svelte@5.43.6): + svelte-sonner@0.3.28(svelte@5.43.12): dependencies: - svelte: 5.43.6 + svelte: 5.43.12 svelte@4.2.19: dependencies: '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 '@types/estree': 1.0.7 - acorn: 8.15.0 + acorn: 8.14.1 aria-query: 5.3.2 axobject-query: 4.1.0 code-red: 1.0.4 @@ -6752,7 +6759,7 @@ snapshots: magic-string: 0.30.21 periscopic: 3.1.0 - svelte@5.43.6: + svelte@5.43.12: dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -6763,7 +6770,7 @@ snapshots: axobject-query: 4.1.0 clsx: 2.1.1 esm-env: 1.2.2 - esrap: 2.1.2 + esrap: 2.1.3 is-reference: 3.0.3 locate-character: 3.0.0 magic-string: 0.30.21 @@ -6823,15 +6830,15 @@ snapshots: tldts-core@6.1.85: {} - tldts-core@7.0.17: {} + tldts-core@7.0.18: {} tldts@6.1.85: dependencies: tldts-core: 6.1.85 - tldts@7.0.17: + tldts@7.0.18: dependencies: - tldts-core: 7.0.17 + tldts-core: 7.0.18 to-regex-range@5.0.1: dependencies: @@ -6867,12 +6874,12 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.46.4(eslint@9.39.1)(typescript@5.9.3): + typescript-eslint@8.47.0(eslint@9.39.1)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.46.4(@typescript-eslint/parser@8.46.4(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.4(eslint@9.39.1)(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.46.4(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.4(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.47.0(@typescript-eslint/parser@8.47.0(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.47.0(eslint@9.39.1)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.47.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.47.0(eslint@9.39.1)(typescript@5.9.3) eslint: 9.39.1 typescript: 5.9.3 transitivePeerDependencies: @@ -6938,13 +6945,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-node@3.2.4(@types/node@22.13.14)(sass@1.94.0): + vite-node@3.2.4(@types/node@22.13.14)(sass@1.94.2): dependencies: cac: 6.7.14 debug: 4.4.1 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) transitivePeerDependencies: - '@types/node' - jiti @@ -6959,7 +6966,7 @@ snapshots: - tsx - yaml - vite@7.2.2(@types/node@22.13.14)(sass@1.94.0): + vite@7.2.4(@types/node@22.13.14)(sass@1.94.2): dependencies: esbuild: 0.25.1 fdir: 6.5.0(picomatch@4.0.3) @@ -6970,17 +6977,17 @@ snapshots: optionalDependencies: '@types/node': 22.13.14 fsevents: 2.3.3 - sass: 1.94.0 + sass: 1.94.2 - vitefu@1.0.6(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)): + vitefu@1.0.6(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)): optionalDependencies: - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) - vitest@3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.0): + vitest@3.2.4(@types/node@22.13.14)(@vitest/ui@3.2.4)(jsdom@26.1.0)(sass@1.94.2): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.2.2(@types/node@22.13.14)(sass@1.94.0)) + '@vitest/mocker': 3.2.4(vite@7.2.4(@types/node@22.13.14)(sass@1.94.2)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -6998,8 +7005,8 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.2.2(@types/node@22.13.14)(sass@1.94.0) - vite-node: 3.2.4(@types/node@22.13.14)(sass@1.94.0) + vite: 7.2.4(@types/node@22.13.14)(sass@1.94.2) + vite-node: 3.2.4(@types/node@22.13.14)(sass@1.94.2) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.13.14 diff --git a/src/lib/actions/analytics.ts b/src/lib/actions/analytics.ts index b511e59c8..6880f1c2f 100644 --- a/src/lib/actions/analytics.ts +++ b/src/lib/actions/analytics.ts @@ -195,7 +195,10 @@ export enum Click { VariablesCreateClick = 'click_variable_create', VariablesUpdateClick = 'click_variable_update', VariablesImportClick = 'click_variable_import', - WebsiteOpenClick = 'click_open_website' + WebsiteOpenClick = 'click_open_website', + CopyPromptStarterKitClick = 'click_copy_prompt_starter_kit', + OpenInCursorClick = 'click_open_in_cursor', + OpenInLovableClick = 'click_open_in_lovable' } export enum Submit { @@ -357,6 +360,7 @@ export enum Submit { BucketUpdateSize = 'submit_bucket_update_size', BucketUpdateCompression = 'submit_bucket_update_compression', BucketUpdateExtensions = 'submit_bucket_update_extensions', + BucketUpdateTransformations = 'submit_bucket_update_transformations', FileCreate = 'submit_file_create', FileDelete = 'submit_file_delete', FileUpdatePermissions = 'submit_file_update_permissions', diff --git a/src/lib/commandCenter/commandCenter.svelte b/src/lib/commandCenter/commandCenter.svelte index fb3c6709b..284e5817e 100644 --- a/src/lib/commandCenter/commandCenter.svelte +++ b/src/lib/commandCenter/commandCenter.svelte @@ -32,12 +32,17 @@ @@ -31,6 +32,7 @@ {fullWidth} {wrapperFullWidth} {fixed} + {portal} on:blur> diff --git a/src/lib/components/emptyCardImageCloud.svelte b/src/lib/components/emptyCardImageCloud.svelte index b6c29c2e6..0f4c23450 100644 --- a/src/lib/components/emptyCardImageCloud.svelte +++ b/src/lib/components/emptyCardImageCloud.svelte @@ -1,13 +1,20 @@ - - + {#if $$slots?.image}
diff --git a/src/lib/components/expirationInput.svelte b/src/lib/components/expirationInput.svelte index 343d2444e..9782dfae5 100644 --- a/src/lib/components/expirationInput.svelte +++ b/src/lib/components/expirationInput.svelte @@ -6,8 +6,8 @@ - - - + +
+ +
+
+ POWERED BY + {#if $app.themeInUse === 'dark'} + Appwrite Logo + {:else} + Appwrite Logo + {/if} +
+
+ + diff --git a/src/routes/(authenticated)/git/authorize-contributor/+page.svelte b/src/routes/(authenticated)/git/authorize-contributor/+page.svelte index 9d1bbae8e..c8cebcfc4 100644 --- a/src/routes/(authenticated)/git/authorize-contributor/+page.svelte +++ b/src/routes/(authenticated)/git/authorize-contributor/+page.svelte @@ -1,31 +1,21 @@ -
-
-
-

Authorize External Deployment

- The deployment for pull request #{providerPullRequestId} is awaiting approval. When authorized, deployments - will be started. - - -
- -
- - {#if error} -

{error}

- {/if} - - {#if success} -

{success}

- {/if} -
- -
-
+ + {#if success} + + {:else if error} + + {/if} + + The deployment for pull request #{data.providerPullRequestId} + is awaiting approval. When authorized, deployments will be started. + + + diff --git a/src/routes/(console)/account/organizations/+page.svelte b/src/routes/(console)/account/organizations/+page.svelte index fd3e1a92b..389113c7b 100644 --- a/src/routes/(console)/account/organizations/+page.svelte +++ b/src/routes/(console)/account/organizations/+page.svelte @@ -13,10 +13,10 @@ import { sdk } from '$lib/stores/sdk'; import type { PageData } from './$types'; import { isCloud } from '$lib/system'; - import { Badge } from '@appwrite.io/pink-svelte'; + import { Badge, Skeleton } from '@appwrite.io/pink-svelte'; import type { Models } from '@appwrite.io/console'; import type { Organization } from '$lib/stores/organization'; - import { daysLeftInTrial, plansInfo, tierToPlan } from '$lib/stores/billing'; + import { daysLeftInTrial, plansInfo, tierToPlan, type Tier } from '$lib/stores/billing'; import { toLocaleDate } from '$lib/helpers/date'; import { BillingPlan } from '$lib/constants'; import { goto } from '$app/navigation'; @@ -37,6 +37,27 @@ return memberships.memberships.map((team) => team.userName || team.userEmail); } + async function getPlanName(billingPlan: string | undefined): Promise { + if (!billingPlan) return 'Unknown'; + + // For known plans, use tierToPlan + const tierData = tierToPlan(billingPlan as Tier); + + // If it's not a custom plan or we got a non-custom result, return the name + if (tierData.name !== 'Custom') { + return tierData.name; + } + + // For custom plans, fetch from API + try { + const plan = await sdk.forConsole.billing.getPlan(billingPlan); + return plan.name; + } catch (error) { + // Fallback to 'Custom' if fetch fails + return 'Custom'; + } + } + function isOrganizationOnTrial(organization: Organization): boolean { if (!organization?.billingTrialStartDate) return false; if ($daysLeftInTrial <= 0) return false; @@ -93,6 +114,9 @@ {#each data.organizations.teams as organization} {@const avatarList = getMemberships(organization.$id)} {@const payingOrg = isPayingOrganization(organization)} + {@const planName = isCloudOrg(organization) + ? getPlanName(organization.billingPlan) + : null} @@ -105,16 +129,19 @@ {#if isCloudOrg(organization)} {#if isNonPayingOrganization(organization)} - - + {#if planName} + {#await planName} + + {:then name} + + - - You are limited to 1 free organization per account - - + + You are limited to 1 free organization per account + + + {/await} + {/if} {/if} {#if isOrganizationOnTrial(organization)} @@ -133,16 +160,20 @@ {/if} {#if payingOrg} - + {#await planName} + + {:then name} + + {/await} {/if} {/if} {#await avatarList} - + {:then avatars} {/await} diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte index b8bc37a60..3d422d198 100644 --- a/src/routes/(console)/apply-credit/+page.svelte +++ b/src/routes/(console)/apply-credit/+page.svelte @@ -136,7 +136,7 @@ billingPlan, paymentMethodId, resolvedProfile.organizationPlatform, - null, + undefined, couponData.code ? couponData.code : null, collaborators, billingBudget, @@ -150,7 +150,7 @@ selectedOrg.$id, billingPlan, paymentMethodId, - null, + undefined, couponData.code ? couponData.code : null, collaborators ); diff --git a/src/routes/(console)/bottomAlerts.ts b/src/routes/(console)/bottomAlerts.ts index 6e732786d..5a8f6e353 100644 --- a/src/routes/(console)/bottomAlerts.ts +++ b/src/routes/(console)/bottomAlerts.ts @@ -1,33 +1,33 @@ import { isCloud } from '$lib/system'; import { isSameDay } from '$lib/helpers/date'; import { type BottomModalAlertItem, showBottomModalAlert } from '$lib/stores/bottom-alerts'; -import DbOperatorsDark from '$lib/images/promos/db-operators-dark.png'; -import DbOperatorsLight from '$lib/images/promos/db-operators-light.png'; +import AiSuggestionsDark from '$lib/images/promos/ai-suggestions-dark.png'; +import AiSuggestionsLight from '$lib/images/promos/ai-suggestions-light.png'; import { ProfileMode, resolvedProfile } from '$lib/profiles/index.svelte'; const listOfPromotions: BottomModalAlertItem[] = []; if (isCloud) { - const dbOperatorsPromo: BottomModalAlertItem = { - id: 'modal:db_operators_announcement', + const aiSuggestionsPromo: BottomModalAlertItem = { + id: 'modal:database_ai_suggestions_announcement', src: { - dark: DbOperatorsDark, - light: DbOperatorsLight + dark: AiSuggestionsDark, + light: AiSuggestionsLight }, - title: 'Announcing DB operators', - message: 'Update multiple fields without fetching the entire row.', + title: 'Announcing Database AI suggestions', + message: 'From table name to schema in one click.', plan: 'free', importance: 8, scope: 'project', cta: { text: 'Read announcement', - link: () => 'https://appwrite.io/blog/post/announcing-db-operators', + link: () => 'https://appwrite.io/blog/post/announcing-database-ai-suggestions', external: true, hideOnClick: true }, show: true }; - listOfPromotions.push(dbOperatorsPromo); + listOfPromotions.push(aiSuggestionsPromo); } export function addBottomModalAlerts() { diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte index d6466a9a2..6cdf01cf5 100644 --- a/src/routes/(console)/create-organization/+page.svelte +++ b/src/routes/(console)/create-organization/+page.svelte @@ -115,8 +115,7 @@ name, resolvedProfile.freeTier, null, - resolvedProfile.organizationPlatform, - null + resolvedProfile.organizationPlatform ); } else { org = await sdk.forConsole.billing.createOrganization( @@ -125,7 +124,7 @@ selectedPlan, paymentMethodId, resolvedProfile.organizationPlatform, - null, + undefined, selectedCoupon?.code, collaborators, billingBudget, diff --git a/src/routes/(console)/onboarding/create-organization/+page.svelte b/src/routes/(console)/onboarding/create-organization/+page.svelte index 83bfa2bc6..cdf4b5414 100644 --- a/src/routes/(console)/onboarding/create-organization/+page.svelte +++ b/src/routes/(console)/onboarding/create-organization/+page.svelte @@ -27,8 +27,7 @@ organizationName, resolvedProfile.freeTier, null, - resolvedProfile.organizationPlatform, - null + resolvedProfile.organizationPlatform ); trackEvent(Submit.OrganizationCreate, { diff --git a/src/routes/(console)/onboarding/create-project/+page.ts b/src/routes/(console)/onboarding/create-project/+page.ts index 9daa4d01f..40aad4419 100644 --- a/src/routes/(console)/onboarding/create-project/+page.ts +++ b/src/routes/(console)/onboarding/create-project/+page.ts @@ -46,8 +46,7 @@ export const load: PageLoad = async ({ parent }) => { 'Personal projects', resolvedProfile.freeTier, null, - resolvedProfile.organizationPlatform, - null + resolvedProfile.organizationPlatform ); trackEvent(Submit.OrganizationCreate, { plan: tierToPlan(BillingPlan.FREE)?.name, diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte index 3eb667690..99729b8e9 100644 --- a/src/routes/(console)/organization-[organization]/billing/+page.svelte +++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte @@ -135,7 +135,9 @@ availableCredit={data?.availableCredit} currentPlan={data?.currentPlan} nextPlan={data?.nextPlan} - currentAggregation={data?.billingAggregation} /> + currentAggregation={data?.billingAggregation} + limit={data?.limit} + offset={data?.offset} /> {:else} { +import { getLimit, getPage, pageToOffset } from '$lib/helpers/load'; + +export const load: PageLoad = async ({ parent, depends, url, route }) => { const { organization, scopes, currentPlan, countryList, locale } = await parent(); if (!scopes.includes('billing.read')) { @@ -20,6 +22,8 @@ export const load: PageLoad = async ({ parent, depends }) => { depends(Dependencies.CREDIT); depends(Dependencies.INVOICES); depends(Dependencies.ADDRESS); + //aggregation reloads on page param changes + depends(Dependencies.BILLING_AGGREGATION); const billingAddressId = (organization as Organization)?.billingAddressId; const billingAddressPromise: Promise
= billingAddressId @@ -35,9 +39,14 @@ export const load: PageLoad = async ({ parent, depends }) => { */ let billingAggregation = null; try { + const currentPage = getPage(url) || 1; + const limit = getLimit(url, route, DEFAULT_BILLING_PROJECTS_LIMIT); + const offset = pageToOffset(currentPage, limit); billingAggregation = await sdk.forConsole.billing.getAggregation( organization.$id, - (organization as Organization)?.billingAggregationId + (organization as Organization)?.billingAggregationId, + limit, + offset ); } catch (e) { // ignore error @@ -85,6 +94,11 @@ export const load: PageLoad = async ({ parent, depends }) => { areCreditsSupported, countryList, locale, - nextPlan: billingPlanDowngrade + nextPlan: billingPlanDowngrade, + limit: getLimit(url, route, DEFAULT_BILLING_PROJECTS_LIMIT), + offset: pageToOffset( + getPage(url) || 1, + getLimit(url, route, DEFAULT_BILLING_PROJECTS_LIMIT) + ) }; }; diff --git a/src/routes/(console)/organization-[organization]/billing/billingAddress.svelte b/src/routes/(console)/organization-[organization]/billing/billingAddress.svelte index 66f915f69..d9ce805b3 100644 --- a/src/routes/(console)/organization-[organization]/billing/billingAddress.svelte +++ b/src/routes/(console)/organization-[organization]/billing/billingAddress.svelte @@ -152,7 +152,7 @@ bind:selectedAddress={billingAddress} /> {/if} {#if showReplace} - + {/if} {#if showRemove} diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte index 2f1928fa5..5410d5b40 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte @@ -1,20 +1,21 @@ {#if $organization} - - {currentPlan.name} plan + {#key aggregationKey} + + {currentPlan.name} plan - {#if totalAmount > 0} - - Next payment of {formatCurrency(totalAmount)} - will occur on - {toLocaleDate($organization?.billingNextInvoiceDate)}. - - {/if} - -
- - Current billing cycle ({new Date( - $organization?.billingCurrentInvoiceDate - ).toLocaleDateString('en', { day: 'numeric', month: 'short' })}-{new Date( - $organization?.billingNextInvoiceDate - ).toLocaleDateString('en', { day: 'numeric', month: 'short' })}) - - - Estimate, subject to change based on usage. - -
- -
- - {#each billingData as row} - - {#each columns as col} - - {#if col.id === 'item'} -
+ {#if totalAmount > 0} + + Next payment of {formatCurrency(totalAmount)} + will occur on + {toLocaleDate($organization?.billingNextInvoiceDate)}. + + {/if} + +
+ + Current billing cycle ({new Date( + $organization?.billingCurrentInvoiceDate + ).toLocaleDateString('en', { day: 'numeric', month: 'short' })}-{new Date( + $organization?.billingNextInvoiceDate + ).toLocaleDateString('en', { day: 'numeric', month: 'short' })}) + + + Estimate, subject to change based on usage. + +
+ +
+ + {#each billingData as row} + + {#each columns as col} + + {#if col.id === 'item'} +
+ {#if row.badge} + + + {row.cells?.[col.id] ?? ''} + + + + {:else} + + {row.cells?.[col.id] ?? ''} + + {/if} +
+ {:else} {row.cells?.[col.id] ?? ''} -
- {:else} - - {row.cells?.[col.id] ?? ''} - - {/if} - - {/each} + {/if} + + {/each} - - {#if row.children} - {#each row.children as child (child.id)} - - {/each} -
- {/each} - {/if} - -
- {/each} - {#if availableCredit > 0} - - - - - - Credits - - - - - - - - - -{formatCurrency(creditsApplied)} - - - - {/if} - - - - - Total - - - - - - - - - {formatCurrency(totalAmount)} - - - -
-
- - -
- {#if isFreePlan($organization?.billingPlan) || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION} -
- {#if !currentPlan?.usagePerProject} - + + +
+
+ {#if child.progressData && child.progressData.length > 0 && child.maxValue} + + {/if} +
+
+ {#if child.cells?.usage?.includes(' / ')} + {@const usageParts = ( + child.cells?.usage ?? '' + ).split(' / ')} + + {usageParts[0]} + + + {' / '} + + + {usageParts[1]} + + {:else} + + {child.cells?.usage ?? ''} + + {/if} +
+
+
+ + + {child.cells?.price ?? ''} + + + + {/each} + {/if} + + + {/each} + {#if totalProjects > projectsLimit && hasProjectBreakdown} + + +
+ +
+
+ + +
{/if} - -
- {:else} -
- {#if $organization?.billingPlanDowngrade !== null} - - {:else} + {#if availableCredit > 0} + + + + + + Credits + + + + + + + + + -{formatCurrency(creditsApplied)} + + + + {/if} + + + + + Total + + + + + + + + + {formatCurrency(totalAmount)} + + + + +
+ + +
+ {#if isFreePlan($organization?.billingPlan) || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION} + + {#if !currentPlan?.usagePerProject} + + {/if} - {/if} - {#if !currentPlan?.usagePerProject} - - {/if} -
- {/if} -
-
+ + {:else} + + {#if $organization?.billingPlanDowngrade !== null} + + {:else} + + {/if} + {#if !currentPlan?.usagePerProject} + + {/if} + + {/if} +
+ + {/key} {/if} @@ -669,50 +767,7 @@ flex-shrink: 0; } - /* mobile table wrapper for horizontal scroll */ - .table-wrapper.is-mobile { - overflow-x: auto; - -webkit-overflow-scrolling: touch; - margin: 0 -1rem; - padding: 0 1rem; - } - - /* reset mobile overrides - use desktop layout in scrollable container */ - .table-wrapper.is-mobile :global(.child-row) { - grid-template-columns: var(--original-grid-template) !important; - min-width: 600px; /* ensure minimum width for proper layout */ - } - - .table-wrapper.is-mobile :global(.usage-cell-content) { - flex-direction: row !important; - align-items: center !important; - gap: 0.75rem !important; - padding-left: 1rem !important; - min-height: 2rem !important; - } - - .table-wrapper.is-mobile :global(.usage-progress-section) { - width: 200px !important; - flex-shrink: 0 !important; - } - - .table-wrapper.is-mobile :global(.usage-progress-section .progressbar__container) { - width: 200px !important; - max-width: 200px !important; - } - @media (max-width: 768px) { - .actions-mobile { - justify-content: flex-start !important; - gap: 8px !important; - } - - .actions-mobile :global(a), - .actions-mobile :global(button) { - padding: 6px 12px !important; - font-size: 14px !important; - border-radius: 8px !important; - } .billing-cycle-header { flex-direction: column; gap: 8px; @@ -734,4 +789,11 @@ background: unset !important; } } + + /* reducing size of paginator */ + .pagination-left { + display: inline-block; + transform: scale(0.95); + transform-origin: left center; + } diff --git a/src/routes/(console)/organization-[organization]/billing/planSummaryOld.svelte b/src/routes/(console)/organization-[organization]/billing/planSummaryOld.svelte index 0d17419ec..e9f4c88dd 100644 --- a/src/routes/(console)/organization-[organization]/billing/planSummaryOld.svelte +++ b/src/routes/(console)/organization-[organization]/billing/planSummaryOld.svelte @@ -200,7 +200,7 @@ disabled={$organization?.markedForDeletion} href={$upgradeURL} on:click={() => - trackEvent('click_organization_plan_update', { + trackEvent(Click.OrganizationClickUpgrade, { from: 'button', source: 'billing_tab' })}> diff --git a/src/routes/(console)/organization-[organization]/billing/replaceAddress.svelte b/src/routes/(console)/organization-[organization]/billing/replaceAddress.svelte index 4d5fa0577..5ef49d026 100644 --- a/src/routes/(console)/organization-[organization]/billing/replaceAddress.svelte +++ b/src/routes/(console)/organization-[organization]/billing/replaceAddress.svelte @@ -11,9 +11,11 @@ import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { base } from '$app/paths'; import { Alert, Badge, Card, Layout, Skeleton } from '@appwrite.io/pink-svelte'; - import { page } from '$app/state'; + import type { Models } from '@appwrite.io/console'; export let show = false; + export let locale: Models.Locale; + export let countryList: Models.CountryList; let loading = true; let addresses: AddressesList; let selectedAddress: string; @@ -44,13 +46,9 @@ : null : null; - const locale = await sdk.forProject(page.params.region, page.params.project).locale.get(); if (locale?.countryCode) { country = locale.countryCode; } - const countryList = await sdk - .forProject(page.params.region, page.params.project) - .locale.listCountries(); options = countryList.countries.map((country) => { return { value: country.code, diff --git a/src/routes/(console)/organization-[organization]/billing/store.ts b/src/routes/(console)/organization-[organization]/billing/store.ts index 30d9b1c3c..a8f05930a 100644 --- a/src/routes/(console)/organization-[organization]/billing/store.ts +++ b/src/routes/(console)/organization-[organization]/billing/store.ts @@ -1,7 +1,7 @@ import { page } from '$app/stores'; -import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte'; -import type { AggregationList, Invoice } from '$lib/sdk/billing'; import { derived, writable } from 'svelte/store'; +import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte'; +import type { AggregationList, Invoice, InvoiceUsage } from '$lib/sdk/billing'; export const aggregationList = derived( page, @@ -16,3 +16,31 @@ export const addCreditWizardStore = writable<{ coupon: string; paymentMethodId: export const selectedInvoice = writable(null); export const showRetryModal = writable(false); + +export type RowFactoryOptions = { + id: string; + label: string; + resource?: InvoiceUsage; + planLimit?: number | null; + includeProgress?: boolean; + formatValue?: (value: number | null | undefined) => string; + usageFormatter?: (options: { + value: number; + planLimit?: number | null; + resource?: InvoiceUsage; + formatValue: (value: number | null | undefined) => string; + hasLimit: boolean; + }) => string; + priceFormatter?: (options: { amount: number; resource?: InvoiceUsage }) => string; + progressFactory?: (options: { + value: number; + planLimit?: number | null; + resource?: InvoiceUsage; + hasLimit: boolean; + }) => Array<{ size: number; color: string; tooltip?: { title: string; label: string } }>; + maxFactory?: (options: { + planLimit?: number | null; + hasLimit: boolean; + resource?: InvoiceUsage; + }) => number | null; +}; diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte index d48875c54..f5ed0d0d9 100644 --- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte +++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte @@ -16,7 +16,6 @@ import { sdk } from '$lib/stores/sdk'; import { confirmPayment } from '$lib/stores/stripe'; import { user } from '$lib/stores/user'; - import { VARS } from '$lib/system'; import { IconPlus } from '@appwrite.io/pink-icons-svelte'; import { Alert, @@ -142,30 +141,14 @@ } async function trackDowngradeFeedback() { - const paidInvoices = await sdk.forConsole.billing.listInvoices(data.organization.$id, [ - Query.equal('status', 'succeeded'), - Query.greaterThan('grossAmount', 0) - ]); - - await fetch(`${VARS.GROWTH_ENDPOINT}/feedback/billing`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - from: tierToPlan(data.organization.billingPlan).name, - to: tierToPlan(selectedPlan).name, - email: data.account.email, - reason: feedbackDowngradeOptions.find( - (option) => option.value === feedbackDowngradeReason - )?.label, - orgId: data.organization.$id, - userId: data.account.$id, - orgAge: data.organization.$createdAt, - userAge: data.account.$createdAt, - paidInvoices: paidInvoices.total, - message: feedbackMessage ?? '' - }) + await sdk.forConsole.organizations.createDowngradeFeedback({ + organizationId: data.organization.$id, + reason: feedbackDowngradeOptions.find( + (option) => option.value === feedbackDowngradeReason + )?.label, + message: feedbackMessage ?? '', + fromPlanId: data.organization.billingPlan, + toPlanId: selectedPlan }); } @@ -175,8 +158,7 @@ await sdk.forConsole.billing.updatePlan( data.organization.$id, selectedPlan, - paymentMethodId, - null + paymentMethodId ); // 2) If the target plan has a project limit, apply selected projects now @@ -256,7 +238,7 @@ data.organization.$id, selectedPlan, paymentMethodId, - null, + undefined, selectedCoupon?.code, newCollaborators, billingBudget, diff --git a/src/routes/(console)/project-[region]-[project]/+layout.ts b/src/routes/(console)/project-[region]-[project]/+layout.ts index c5e02c45d..848adf556 100644 --- a/src/routes/(console)/project-[region]-[project]/+layout.ts +++ b/src/routes/(console)/project-[region]-[project]/+layout.ts @@ -48,27 +48,29 @@ export const load: LayoutLoad = async ({ params, route, depends, parent }) => { // fast path without a network call! let organization = organizations?.teams?.find((org) => org.$id === project.teamId); - const includedInBasePlans = plansInfo.has(organization.billingPlan); + // organization can be null if not in the filtered list! + const includedInBasePlans = plansInfo.has(organization?.billingPlan); - const [org, regionalConsoleVariables, rolesResult, organizationPlan] = await Promise.all([ + const [org, regionalConsoleVariables, rolesResult] = await Promise.all([ !organization ? (sdk.forConsole.teams.get({ teamId: project.teamId }) as Promise) : organization, sdk.forConsoleIn(project.region).console.variables(), isCloud ? sdk.forConsole.billing.getRoles(project.teamId) : null, - // fetch if not available in `plansInfo` - includedInBasePlans - ? plansInfo.get(organization.billingPlan) - : isCloud - ? sdk.forConsole.billing.getOrganizationPlan(organization.$id) - : null, - loadAvailableRegions(project.teamId) ]); if (!organization) organization = org; + // fetch if not available in `plansInfo`. + // out of promise.all because we filter orgs based on platform now! + const organizationPlan = includedInBasePlans + ? plansInfo.get(organization?.billingPlan) + : isCloud + ? await sdk.forConsole.billing.getOrganizationPlan(organization?.$id) + : null; + const roles = rolesResult?.roles ?? defaultRoles; const scopes = rolesResult?.scopes ?? defaultScopes; diff --git a/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte b/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte index 782df6879..355d79654 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/(providers)/microsoftOAuth.svelte @@ -38,8 +38,9 @@ } }; - $: secret = - clientSecret && tenantID ? JSON.stringify({ clientSecret, tenantID }) : provider.secret; + $: secret = clientSecret + ? JSON.stringify({ clientSecret, ...(tenantID && { tenantID }) }) + : provider.secret; diff --git a/src/routes/(console)/project-[region]-[project]/auth/security/updateMockNumbers.svelte b/src/routes/(console)/project-[region]-[project]/auth/security/updateMockNumbers.svelte index b0cf013bf..be735a708 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/security/updateMockNumbers.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/security/updateMockNumbers.svelte @@ -99,7 +99,7 @@ Learn more {#if isComponentDisabled} - +
{#if $app.themeInUse === 'dark'} diff --git a/src/routes/(console)/project-[region]-[project]/auth/templates/emailSignature.svelte b/src/routes/(console)/project-[region]-[project]/auth/templates/emailSignature.svelte index 96b44a925..186096bfb 100644 --- a/src/routes/(console)/project-[region]-[project]/auth/templates/emailSignature.svelte +++ b/src/routes/(console)/project-[region]-[project]/auth/templates/emailSignature.svelte @@ -16,7 +16,7 @@ Enable or disable {resolvedProfile.platform} branding in your email template signature. - +
{#if $app.themeInUse === 'dark'} diff --git a/src/routes/(console)/project-[region]-[project]/databases/create.svelte b/src/routes/(console)/project-[region]-[project]/databases/create.svelte index 0599ab725..f00b68e59 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/create.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/create.svelte @@ -7,14 +7,13 @@ import { ID } from '@appwrite.io/console'; import { createEventDispatcher } from 'svelte'; import { isCloud } from '$lib/system'; - import { organization } from '$lib/stores/organization'; + import { currentPlan } from '$lib/stores/organization'; import { upgradeURL } from '$lib/stores/billing'; import CreatePolicy from './database-[database]/backups/createPolicy.svelte'; import { cronExpression, type UserBackupPolicy } from '$lib/helpers/backups'; import { Alert, Icon, Tag } from '@appwrite.io/pink-svelte'; import { IconPencil } from '@appwrite.io/pink-icons-svelte'; import { page } from '$app/state'; - import { isFreePlan } from '$lib/helpers/billing'; export let showCreate = false; let totalPolicies: UserBackupPolicy[] = []; @@ -132,7 +131,7 @@ {#if isCloud} - {#if isFreePlan($organization?.billingPlan)} + {#if !$currentPlan?.backupsEnabled} Upgrade your plan to ensure your data stays safe and backed up. diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/icon/ai.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/icon/ai.svelte index 9fae0e544..761f3a51c 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/icon/ai.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/icon/ai.svelte @@ -82,9 +82,4 @@ aspect-ratio: 1/1; } } - - :global(.ai-icon-holder.notification) { - width: 36px !important; - height: 32px !important; - } diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.ts b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.ts index 834bfc7aa..c27e09eae 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.ts +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/store.ts @@ -135,6 +135,7 @@ export type ColumnInput = { formatOptions?: { min?: number; max?: number; + elements?: string[]; }; }; @@ -155,7 +156,10 @@ export function mapSuggestedColumns(columns: T[]): Sugges ? (col.max ?? col.formatOptions?.max ?? undefined) : undefined, format: col.format ?? null, - elements: col.elements ?? undefined + elements: + col.format === 'enum' + ? (col.elements ?? col.formatOptions?.elements ?? undefined) + : undefined })); } diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/containerHeader.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/containerHeader.svelte index d340d0f75..1ee5a6e2f 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/containerHeader.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/containerHeader.svelte @@ -5,8 +5,6 @@ import { Badge, Icon, Layout, Tag, Typography } from '@appwrite.io/pink-svelte'; import { goto } from '$app/navigation'; import { upgradeURL } from '$lib/stores/billing'; - import { BillingPlan } from '$lib/constants'; - import { organization } from '$lib/stores/organization'; export let isFlex = true; export let title: string; @@ -50,7 +48,7 @@ paddingBlock="var(--space-5, 12px)" paddingInline="var(--space-6, 16px)" resetListPadding> - {#if $organization?.billingPlan === BillingPlan.PRO} + {#if maxPolicies === 1} all.map((policy) => { policy.id = ID.unique(); @@ -176,7 +175,7 @@
- {#if $organization.billingPlan === BillingPlan.SCALE} + {#if $currentPlan?.backupPolicies > 1} {#if title || subtitle}
{#if title} @@ -195,7 +194,7 @@ {/if} - {#if $organization.billingPlan === BillingPlan.PRO} + {#if $currentPlan?.backupPolicies === 1} {@const dailyPolicy = $presetPolicies[1]} {#if isFromBackupsTab} diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte index 88af9c257..f706ab739 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte @@ -71,7 +71,8 @@ // spatial type selected -> reset column list to single empty column // and the column already is not spatial type $effect(() => { - if (selectedType === IndexType.Spatial && !columnList.at(0).value) { + const firstColumn = $table.columns.find((col) => col.key === columnList.at(0)?.value); + if (selectedType === IndexType.Spatial && firstColumn && !isSpatialType(firstColumn)) { columnList = [{ value: '', order: null, length: null }]; } }); diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte index e3d832a8a..c77dd08d8 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte @@ -251,6 +251,7 @@ data-mode={mode} bind:this={spreadsheetContainer} class:custom-columns={customColumns.length > 0} + class:no-custom-columns={customColumns.length <= 0} class="databases-spreadsheet spreadsheet-container-outer"> .spreadsheet-fade-bottom { + top: var(--top-actions-spacing) !important; + background: var(--bgcolor-neutral-primary) !important; + } + } + } + &:not(.custom-columns) :global(.spreadsheet-container) { overflow-x: hidden; overflow-y: hidden; @@ -393,12 +407,16 @@ } &[data-mode='rows'] { + --top-actions-spacing: 50%; + & :global([role='rowheader'] :nth-last-child(2) [role='presentation']) { display: none; } } &[data-mode='indexes'] { + --top-actions-spacing: 40%; + & :global([role='cell']:last-child [role='presentation']) { display: none; } @@ -463,4 +481,11 @@ margin-bottom: 15%; } } + + @media (max-width: 768px) { + // global but controlled properly! + :global(main:has(.no-custom-columns) .console-container) { + opacity: 0; + } + } diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte index 37f06d174..bd1038880 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte @@ -11,7 +11,7 @@ import { Fieldset, Layout, Icon, Input, Tag } from '@appwrite.io/pink-svelte'; import { IconGithub, IconPencil } from '@appwrite.io/pink-icons-svelte'; import { onMount } from 'svelte'; - import { ID, Runtime } from '@appwrite.io/console'; + import { ID, Runtime, Type } from '@appwrite.io/console'; import { CustomId } from '$lib/components'; import { getIconFromRuntime } from '$lib/stores/runtimes'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -135,7 +135,8 @@ repository: data.repository.name, owner: data.repository.owner, rootDirectory: rootDir || '.', - version: latestTag ?? '1.0.0', + type: Type.Tag, + reference: latestTag ?? '1.0.0', activate: true }); diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte index 0f09e10b7..59727f61f 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte @@ -15,7 +15,7 @@ import { writable } from 'svelte/store'; import ProductionBranch from '$lib/components/git/productionBranchFieldset.svelte'; import Configuration from './configuration.svelte'; - import { ID, Runtime, type Models } from '@appwrite.io/console'; + import { ID, Runtime, Type, type Models } from '@appwrite.io/console'; import { ConnectBehaviour, NewRepository, @@ -180,7 +180,8 @@ repository: data.template.providerRepositoryId || undefined, owner: data.template.providerOwner || undefined, rootDirectory: rt?.providerRootDirectory || undefined, - version: data.template.providerVersion || undefined, + type: Type.Tag, + reference: data.template.providerVersion || undefined, activate: true }); diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts index d5b08e19f..13561dd09 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts @@ -1,4 +1,4 @@ -import { Query } from '@appwrite.io/console'; +import { Query, type Models } from '@appwrite.io/console'; import { sdk } from '$lib/stores/sdk'; import { getLimit, getPage, getQuery, pageToOffset } from '$lib/helpers/load'; import { Dependencies, PAGE_LIMIT } from '$lib/constants'; @@ -15,17 +15,27 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) => const parsedQueries = queryParamToMap(query || '[]'); queries.set(parsedQueries); + let activeDeployment: Models.Deployment | null = null; + if (data.function.deploymentId) { + try { + activeDeployment = await sdk + .forProject(params.region, params.project) + .functions.getDeployment({ + functionId: params.function, + deploymentId: data.function.deploymentId + }); + } catch (error) { + // active deployment with the requested ID could not be found + activeDeployment = null; + } + } + return { offset, limit, query, installations: data.installations, - activeDeployment: data.function.deploymentId - ? await sdk.forProject(params.region, params.project).functions.getDeployment({ - functionId: params.function, - deploymentId: data.function.deploymentId - }) - : null, + activeDeployment, deploymentList: await sdk .forProject(params.region, params.project) .functions.listDeployments({ @@ -41,7 +51,15 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) => 'buildDuration', 'status', 'type', - 'resourceId' + 'resourceId', + 'providerRepositoryUrl', + 'providerRepositoryOwner', + 'providerRepositoryName', + 'providerBranchUrl', + 'providerBranch', + 'providerCommitMessage', + 'providerCommitHash', + 'providerCommitUrl' ]), ...parsedQueries.values() ] diff --git a/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte b/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte index 84e6a7809..4c9bb8150 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte @@ -24,8 +24,8 @@ let isSubmitting = writable(false); let scopes: string[] = []; - let name = '', - expire = ''; + let name = ''; + let expire: string | null = null; async function create() { try { diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte index 877db1b18..48485cc31 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte @@ -26,17 +26,16 @@ + +Cursor diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte index 9ad7963e1..3abd55aa9 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte @@ -17,7 +17,7 @@ import { Card } from '$lib/components'; import { page } from '$app/state'; import { onMount } from 'svelte'; - import { realtime, sdk } from '$lib/stores/sdk'; + import { getApiEndpoint, realtime, sdk } from '$lib/stores/sdk'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { addNotification } from '$lib/stores/notifications'; import { fade } from 'svelte/transition'; @@ -26,6 +26,7 @@ import { PlatformType } from '@appwrite.io/console'; import { project } from '../../store'; import { getCorrectTitle, type PlatformProps } from './store'; + import LlmBanner from './llmBanner.svelte'; let { isConnectPlatform = false }: PlatformProps = $props(); @@ -35,6 +36,60 @@ let isPlatformCreated = $state(isConnectPlatform); const projectId = page.params.project; + const VERSIONS_ENDPOINT = (() => { + const endpoint = getApiEndpoint(page.params.region); + const url = new URL('/versions', endpoint); + return url.toString(); + })(); + let androidSdkVersion = $state('11.3.0'); + + function buildAndroidInstructions(version: string) { + return ` +Confirm you're working inside the correct Android project before editing anything: +- Navigate into the directory that contains the real Android app module (look for gradlew, settings.gradle, and the app-level build.gradle(.kts)). +- If Cursor opens in a parent folder (like your home directory) or you see multiple Android projects, ask which one to modify before making changes. +- Update the app-level build.gradle.kts by default, but be ready to edit a Groovy build.gradle if the project hasn't migrated to Kotlin DSL yet. + +Prefer Version Catalogs when adding the Appwrite SDK: +1. If ./gradle/libs.versions.toml exists, add or reuse an Appwrite entry: +\`\`\`toml +[libraries] +appwrite = { module = "io.appwrite:sdk-for-android", version = "${version}" } +\`\`\` +2. Reference it inside the module's dependencies block: +\`\`\`kotlin +dependencies { + implementation(libs.appwrite) +} +\`\`\` +Only when the project lacks ./gradle/libs.versions.toml should you hardcode the dependency: +\`\`\`kotlin +implementation("io.appwrite:sdk-for-android:${version}") +\`\`\` +Legacy Groovy scripts should use: +\`\`\`groovy +implementation "io.appwrite:sdk-for-android:${version}" +\`\`\` + +Before introducing any new files, search the project (app/src, libs/, shared modules, etc.) for existing Appwrite client helpers (look for \`Client(\`, \`AppwriteClient\`, or \`.setEndpoint\`). If a client already exists, update its configuration instead of creating a duplicate. + +Ensure the Appwrite client is initialized with the application context and current project info: +\`\`\`kotlin +val client = Client(applicationContext) + .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}") + .setProject("${projectId}") + +val account = Account(client) +\`\`\` + +From the app's entry point (e.g., Application class or the first launched Activity), automatically invoke a helper that pings Appwrite so the user can verify connectivity and will be reflected on the Appwrite console: +\`\`\`kotlin +client.ping() +\`\`\` +`; + } + + const alreadyExistsInstructions = $derived(buildAndroidInstructions(androidSdkVersion)); const gitCloneCode = '\ngit clone https://github.com/appwrite/starter-for-android\ncd starter-for-android\n'; @@ -43,6 +98,22 @@ const val APPWRITE_PROJECT_NAME = "${$project.name}" const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"`; + async function fetchAndroidSdkVersion() { + try { + const response = await fetch(VERSIONS_ENDPOINT); + if (!response.ok) { + throw new Error(`Failed to fetch versions: ${response.status}`); + } + const data = await response.json(); + const latestVersion = data?.['client-android']; + if (typeof latestVersion === 'string' && latestVersion.trim()) { + androidSdkVersion = latestVersion.trim(); + } + } catch (error) { + console.error('Unable to fetch latest Android SDK version', error); + } + } + async function createAndroidPlatform() { try { isCreatingPlatform = true; @@ -83,6 +154,7 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page. } onMount(() => { + fetchAndroidSdkVersion(); const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { if (response.events.includes(`projects.${projectId}.ping`)) { connectionSuccessful = true; @@ -171,6 +243,12 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page. {#if isPlatformCreated}
+ + 1. If you're starting a new project, you can clone our starter kit from GitHub using the terminal, VSCode or Android Studio. diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte index 7c1ae8ee6..2a156b76d 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte @@ -28,6 +28,7 @@ import { app } from '$lib/stores/app'; import { project } from '../../store'; import { getCorrectTitle, type PlatformProps } from './store'; + import LlmBanner from './llmBanner.svelte'; let { isConnectPlatform = false, platform = PlatformType.Appleios }: PlatformProps = $props(); @@ -38,6 +39,30 @@ const projectId = page.params.project; + const alreadyExistsInstructions = ` +Install the Appwrite iOS SDK using the following package URL: + +\`\`\` +https://github.com/appwrite/sdk-for-apple +\`\`\` + +From a suitable lib directory, export the Appwrite client as a global variable: + +\`\`\` +let client = Client() + .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}") + .setProject("${projectId}") + +let account = Account(client) +\`\`\` + +On the homepage of the app, create a button that says "Send a ping" and when clicked, it should call the following function: + +\`\`\` +client.ping() +\`\`\` +`; + const gitCloneCode = '\ngit clone https://github.com/appwrite/starter-for-ios\ncd starter-for-ios\n'; @@ -45,7 +70,7 @@ APPWRITE_PROJECT_NAME: "${$project.name}" APPWRITE_PUBLIC_ENDPOINT: "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"`; - let platforms: { [key: string]: PlatformType } = { + const platforms: { [key: string]: PlatformType } = { iOS: PlatformType.Appleios, macOS: PlatformType.Applemacos, watchOS: PlatformType.Applewatchos, @@ -199,6 +224,12 @@ APPWRITE_PUBLIC_ENDPOINT: "${sdk.forProject(page.params.region, page.params.proj {#if isPlatformCreated}
+ + 1. If you're starting a new project, you can clone our starter kit from GitHub using the terminal or XCode. diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte index f6ab670f6..7e569200d 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte @@ -18,7 +18,7 @@ import { Card } from '$lib/components'; import { page } from '$app/state'; import { onMount } from 'svelte'; - import { realtime, sdk } from '$lib/stores/sdk'; + import { getApiEndpoint, realtime, sdk } from '$lib/stores/sdk'; import { Submit, trackError, trackEvent } from '$lib/actions/analytics'; import { addNotification } from '$lib/stores/notifications'; import { fade } from 'svelte/transition'; @@ -28,6 +28,7 @@ import { project } from '../../store'; import { resolvedProfile } from '$lib/profiles/index.svelte'; import { getCorrectTitle, type PlatformProps } from './store'; + import LlmBanner from './llmBanner.svelte'; let { isConnectPlatform = false, platform = PlatformType.Flutterandroid }: PlatformProps = $props(); @@ -38,6 +39,38 @@ let isPlatformCreated = $state(isConnectPlatform); const projectId = page.params.project; + const VERSIONS_ENDPOINT = (() => { + const endpoint = getApiEndpoint(page.params.region); + const url = new URL('/versions', endpoint); + return url.toString(); + })(); + let flutterSdkVersion = $state('20.3.0'); + + function buildFlutterInstructions(version: string) { + return ` +Install the Appwrite Flutter SDK using the following command: + +\`\`\` +flutter pub add appwrite:${version} +\`\`\` + +From a suitable lib directory, export the Appwrite client as a global variable, hardcode the project details too: + +\`\`\` +final Client client = Client() + .setProject("${projectId}") + .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"); +\`\`\` + +On the homepage of the app, create a button that says "Send a ping" and when clicked, it should call the following function: + +\`\`\` +client.ping(); +\`\`\` + `; + } + + const alreadyExistsInstructions = $derived(buildFlutterInstructions(flutterSdkVersion)); const gitCloneCode = '\ngit clone https://github.com/appwrite/starter-for-flutter\ncd starter-for-flutter\n'; @@ -111,6 +144,22 @@ [PlatformType.Flutterwindows]: 'Package name' }; + async function fetchFlutterSdkVersion() { + try { + const response = await fetch(VERSIONS_ENDPOINT); + if (!response.ok) { + throw new Error(`Failed to fetch versions: ${response.status}`); + } + const data = await response.json(); + const latestVersion = data?.['client-flutter']; + if (typeof latestVersion === 'string' && latestVersion.trim()) { + flutterSdkVersion = latestVersion.trim(); + } + } catch (error) { + console.error('Unable to fetch latest Flutter SDK version', error); + } + } + async function createFlutterPlatform() { try { isCreatingPlatform = true; @@ -158,6 +207,7 @@ } onMount(() => { + fetchFlutterSdkVersion(); const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { if (response.events.includes(`projects.${projectId}.ping`)) { connectionSuccessful = true; @@ -281,6 +331,11 @@ {#if isPlatformCreated}
+ 1. If you're starting a new project, you can clone our starter kit from GitHub using the terminal, VSCode or Android Studio. diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte index 74924c819..2abc38dc8 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte @@ -28,6 +28,7 @@ import { project } from '../../store'; import { resolvedProfile } from '$lib/profiles/index.svelte'; import { getCorrectTitle, type PlatformProps } from './store'; + import LlmBanner from './llmBanner.svelte'; let { isConnectPlatform = false, platform = PlatformType.Reactnativeandroid }: PlatformProps = $props(); @@ -39,6 +40,28 @@ const projectId = page.params.project; + const alreadyExistsInstructions = ` +Install the Appwrite React Native SDK using the following command, respect user's package manager of choice and use the one being used in the codebase: + +\`\`\` +npx expo install react-native-appwrite react-native-url-polyfill +\`\`\` + +From a suitable lib directory, export the Appwrite client as a global variable, hardcode the project details too: + +\`\`\` +const client = new Client() + .setProject("${projectId}") + .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"); +\`\`\` + +From the entrypoint of the app, make it so that the following function is automatically called which will ping the Appwrite backend server to verify the setup. Let the user know about this function being added + +\`\`\` +client.ping(); +\`\`\` + `; + const gitCloneCode = '\ngit clone https://github.com/appwrite/starter-for-react-native\ncd starter-for-react-native\n'; @@ -46,6 +69,12 @@ EXPO_PUBLIC_APPWRITE_PROJECT_NAME="${$project.name}" EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}`; + const promptConfigCode = ` + const client = new Client() + .setProject("${projectId}") + .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}") + `; + let platforms: { [key: string]: PlatformType } = { Android: PlatformType.Reactnativeandroid, iOS: PlatformType.Reactnativeios @@ -226,6 +255,12 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p {#if isPlatformCreated}
+ + 1. If you're starting a new project, you can clone our starter kit from GitHub using the terminal or VSCode. diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte index 7189813fb..5b4a67273 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte @@ -48,8 +48,14 @@ } from './components/index'; import { extendedHostnameRegex } from '$lib/helpers/string'; import { project } from '../../store'; + import { + type PlatformProps, + type FrameworkType, + type LLMPromptConfig, + getCorrectTitle + } from './store'; + import LlmBanner from './llmBanner.svelte'; import { resolvedProfile } from '$lib/profiles/index.svelte'; - import { type PlatformProps, type FrameworkType, getCorrectTitle } from './store'; let { key, isConnectPlatform = false, platform = PlatformType.Web }: PlatformProps = $props(); @@ -158,6 +164,57 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p selectedFramework ? selectedFramework.icon : NoFrameworkIcon ); + const llmConfig: LLMPromptConfig = $derived({ + alreadyExistsInstructions: ` +Install the Appwrite web SDK using the following command. Respect the user's package manager of choice. Do not use NPM if the user uses Bun for example. + +\`\`\`bash +npm install appwrite +\`\`\` + +Create a new \`appwrite.js\` (or equivalent, respecting the framework and language, don't create a JS file if TS is being used in the project) file in a suitable lib directory and have the following code: + +\`\`\`js +import { Client, Account, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}") + .setProject("${projectId}"); + +const account = new Account(client); +const databases = new Databases(client); + +export { client, account, databases }; +\`\`\` + +When the app is opened, make it so that the following function is automatically called which will ping the Appwrite backend server to verify the setup. Let the user know about this function being added + +\`\`\`js +client.ping(); +\`\`\` +`, + title: `Copy prompt: starter kit for Appwrite in ${selectedFramework?.label || 'Web'}`, + cloneCommand: `git clone https://github.com/appwrite/starter-for-${selectedFramework?.key}\ncd starter-for-${selectedFramework?.key}`, + configFile: + selectedFramework?.key === 'angular' + ? 'src/environments/environment.ts' + : 'appwrite.js', + configCode: + // selectedFramework?.key === 'angular' + // ? `APPWRITE_PROJECT_ID=${projectId}\nAPPWRITE_PROJECT_NAME=${$project.name}\nAPPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}` + // : ` + // const client = new Client() + // .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}") + // .setProject("${projectId}"); + // `, + `APPWRITE_PROJECT_ID = "${projectId}" +APPWRITE_PROJECT_NAME = "${$project.name}" +APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"`, + configLanguage: selectedFramework?.key === 'angular' ? 'ts' : 'dotenv', + runInstructions: `Install project dependencies using \`npm install\`, then run the app using \`${selectedFramework?.runCommand}\`. Demo app runs on http://localhost:${selectedFramework?.portNumber}. Click the \`Send a ping\` button to verify the setup.`, + using: 'the terminal or VSCode' + }); + async function createWebPlatform() { const hostnameRegex = new RegExp(extendedHostnameRegex); const finalHostname = hostname?.trim() || 'localhost'; @@ -302,6 +359,8 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p {#if isPlatformCreated && !isChangingFramework}
+ + 1. If you're starting a new project, you can clone our starter kit from GitHub using the terminal or VSCode. diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte new file mode 100644 index 000000000..08c28c9ac --- /dev/null +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte @@ -0,0 +1,188 @@ + + +{#if showAlert} + (showAlert = false)}> + + + + + + + Copy the prompt or open it directly in an AI tool like Cursor or Lovable to get + step-by-step instructions, starter code, and SDK commands for your project. + + + + + + + {#each validOpeners as openerId} + {@const o = openersConfig[openerId]} + {#if o} + { + window.open( + o.href(prompt), + '_blank', + 'noopener,noreferrer' + ); + toggle(e); + }}> + + + {#if o.icon} + + {:else if o.imgSrc} + {o.alt} + {/if} + + + {o.label} + + {o.description} + + + + + {/if} + {/each} + + + + + {#if validOpeners.length} + + {/if} + + + + +{/if} diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/store.ts b/src/routes/(console)/project-[region]-[project]/overview/platforms/store.ts index d0b795643..f5241c806 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/store.ts +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/store.ts @@ -17,6 +17,119 @@ export type FrameworkType = { updateConfigCode: string; }; +export type LLMPromptConfig = { + title: string; + alreadyExistsInstructions: string; + cloneCommand: string; + configFile: string; + configCode: string; + configLanguage: string; + runInstructions: string; + using: string; +}; + export function getCorrectTitle(isConnectPlatform: boolean, platform: string) { return isConnectPlatform ? `Connect your ${platform} app` : `Add ${platform} platform`; } + +export function generatePromptFromConfig(config: LLMPromptConfig): string { + return ` +Goal: Setting up Appwrite SDK in the project depending on if a project already exists or not. + +Following are the project details: + +\`\`\` +${config.configCode} +\`\`\` + +Follow the steps depending on if a project already exists on user's working directory or not: + +## If a project already exists: +${config.alreadyExistsInstructions} + +## If a project does not exist: + +1. Clone the starter kit using ${config.using || 'the terminal'}. Make sure to clone in the current working directory so that the cloned files are directly available in the working directory. + +\`\`\`bash +${config.cloneCommand} . +\`\`\` + +2. Replace all occurrences of the environment variables described in the project details section with their corresponding values. This effectively hardcodes the project details wherever those environment variables are used. Use grep (or an equivalent search) to find and update all occurrences. +3. ${config.runInstructions}`; +} + +type PlatformConfig = { + name: string; + title: string; + repoName: string; + configFile: string; + configLanguage: string; + runInstructions: string; + using: string; +}; + +const platformConfigs: Record = { + android: { + name: 'Kotlin', + title: 'Copy prompt: starter kit for Appwrite in Kotlin', + repoName: 'starter-for-android', + configFile: 'constants/AppwriteConfig.kt', + configLanguage: 'kotlin', + runInstructions: + 'Run the app on a connected device or emulator, then click the `Send a ping` button to verify the setup.', + using: 'the terminal, VSCode or Android Studio' + }, + apple: { + name: 'Apple platforms', + title: 'Copy prompt: starter kit for Appwrite for Apple platforms', + repoName: 'starter-for-ios', + configFile: 'Sources/Config.plist', + configLanguage: 'plaintext', + runInstructions: + 'Run the app on a connected device or simulator, then click the `Send a ping` button to verify the setup.', + using: 'the terminal or XCode' + }, + flutter: { + name: 'Flutter', + title: 'Copy prompt: starter kit for Appwrite in Flutter', + repoName: 'starter-for-flutter', + configFile: 'lib/config/environment.dart', + configLanguage: 'dart', + runInstructions: + 'Run the app on a connected device or simulator using `flutter run -d [device_name]`, then click the `Send a ping` button to verify the setup. Ask the user if the AI agent should run the command to run the app for them. Provide the full command while you ask for permission.', + using: 'the terminal' + }, + reactnative: { + name: 'React Native', + title: 'Copy prompt: starter kit for Appwrite in React Native', + repoName: 'starter-for-react-native', + configFile: 'index.ts', + configLanguage: 'typescript', + runInstructions: + 'After replacing and hardcoding project details, run the app on a connected device or simulator using `npm install` followed by `npm run ios` or `npm run android`, then click the `Send a ping` button to verify the setup. Ask the user if the AI agent should run the command to run the app for them. Provide the full command while you ask for permission.', + using: 'the terminal or VSCode' + } +}; + +export function buildPlatformConfig( + platformKey: string, + configCode: string, + alreadyExistsInstructions: string +): LLMPromptConfig { + const config = platformConfigs[platformKey]; + if (!config) { + throw new Error(`Unknown platform: ${platformKey}`); + } + + return { + title: config.title, + alreadyExistsInstructions: alreadyExistsInstructions, + cloneCommand: `git clone https://github.com/appwrite/${config.repoName}\ncd ${config.repoName}`, + configFile: config.configFile, + configCode: configCode, + configLanguage: config.configLanguage, + runInstructions: config.runInstructions, + using: config.using + }; +} diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte index 5e2aa0f55..6e8d386e5 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploy/+page.svelte @@ -12,7 +12,7 @@ import { IconGithub, IconPencil } from '@appwrite.io/pink-icons-svelte'; import { onMount } from 'svelte'; import Domain from '../domain.svelte'; - import { Adapter, BuildRuntime, Framework, ID } from '@appwrite.io/console'; + import { Adapter, BuildRuntime, Framework, ID, Type } from '@appwrite.io/console'; import { CustomId } from '$lib/components'; import { getFrameworkIcon } from '$lib/stores/sites'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -173,7 +173,8 @@ repository: data.repository.name, owner: data.repository.owner, rootDirectory: rootDir || '.', - version: latestTag ?? '1.0.0', + type: Type.Tag, + reference: latestTag ?? '1.0.0', activate: true }); diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/repositories/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/repositories/+page.svelte index 538394668..d57762ca9 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/repositories/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/repositories/+page.svelte @@ -67,7 +67,10 @@ - + diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte index 14d6a8a80..58eea820a 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/templates/template-[template]/+page.svelte @@ -24,7 +24,7 @@ import Details from '../../details.svelte'; import Configuration from './configuration.svelte'; import Aside from '../../aside.svelte'; - import { Adapter, BuildRuntime, Framework, ID, type Models } from '@appwrite.io/console'; + import { Adapter, BuildRuntime, Framework, ID, Type, type Models } from '@appwrite.io/console'; import { ConnectBehaviour, NewRepository, @@ -160,7 +160,8 @@ repository: data.template.providerRepositoryId, owner: data.template.providerOwner, rootDirectory: framework.providerRootDirectory, - version: data.template.providerVersion, + type: Type.Tag, + reference: data.template.providerVersion, activate: true }); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.ts index e442376ce..d139f00b7 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.ts @@ -1,6 +1,6 @@ import { sdk } from '$lib/stores/sdk'; import { Dependencies } from '$lib/constants'; -import { Query } from '@appwrite.io/console'; +import { Query, type Models } from '@appwrite.io/console'; import { RuleType } from '$lib/stores/sdk'; import { DeploymentResourceType } from '$lib/stores/sdk'; @@ -15,7 +15,19 @@ export const load = async ({ params, depends, parent }) => { queries: [ Query.limit(4), Query.orderDesc(''), - Query.select(['status', 'type', 'resourceId']) + Query.select([ + 'status', + 'type', + 'resourceId', + 'providerRepositoryUrl', + 'providerRepositoryOwner', + 'providerRepositoryName', + 'providerBranchUrl', + 'providerBranch', + 'providerCommitMessage', + 'providerCommitHash', + 'providerCommitUrl' + ]) ] }), sdk.forProject(params.region, params.project).sites.listDeployments({ @@ -46,11 +58,18 @@ export const load = async ({ params, depends, parent }) => { }) ]); - const deployment = deploymentList?.total - ? await sdk - .forProject(params.region, params.project) - .sites.getDeployment({ siteId: params.site, deploymentId: site.deploymentId }) - : null; + let deployment: Models.Deployment | null = null; + if (deploymentList?.total && site.deploymentId) { + try { + deployment = await sdk + .forProject(params.region, params.project) + .sites.getDeployment({ siteId: params.site, deploymentId: site.deploymentId }); + } catch (error) { + // active deployment with the requested ID could not be found + deployment = null; + } + } + return { site, deploymentList, diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.ts index 059aefc4d..ac8fdc679 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.ts @@ -1,4 +1,4 @@ -import { Query } from '@appwrite.io/console'; +import { Query, type Models } from '@appwrite.io/console'; import { sdk } from '$lib/stores/sdk'; import { getLimit, getPage, getQuery, pageToOffset } from '$lib/helpers/load'; import { Dependencies, PAGE_LIMIT } from '$lib/constants'; @@ -29,7 +29,15 @@ export const load = async ({ params, depends, url, route, parent }) => { 'buildDuration', 'status', 'type', - 'resourceId' + 'resourceId', + 'providerRepositoryUrl', + 'providerRepositoryOwner', + 'providerRepositoryName', + 'providerBranchUrl', + 'providerBranch', + 'providerCommitMessage', + 'providerCommitHash', + 'providerCommitUrl' ]), ...parsedQueries.values() ] @@ -37,17 +45,24 @@ export const load = async ({ params, depends, url, route, parent }) => { sdk.forProject(params.region, params.project).vcs.listInstallations() ]); + let activeDeployment: Models.Deployment | null = null; + if (site.deploymentId && deploymentList?.total) { + try { + activeDeployment = await sdk + .forProject(params.region, params.project) + .sites.getDeployment({ siteId: params.site, deploymentId: site.deploymentId }); + } catch (error) { + // active deployment with the requested ID could not be found + activeDeployment = null; + } + } + return { offset, limit, query, deploymentList, - activeDeployment: - site.deploymentId && deploymentList?.total - ? await sdk - .forProject(params.region, params.project) - .sites.getDeployment({ siteId: params.site, deploymentId: site.deploymentId }) - : null, + activeDeployment, installations }; }; diff --git a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/+page.svelte b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/+page.svelte index d976ea88f..5392b677d 100644 --- a/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/storage/bucket-[bucket]/settings/+page.svelte @@ -32,7 +32,8 @@ allowedFileExtensions: values.allowedFileExtensions, compression: values.compression, encryption: values.encryption, - antivirus: values.antivirus + antivirus: values.antivirus, + transformations: values.transformations }); await invalidate(Dependencies.BUCKET); @@ -102,7 +103,8 @@ $permissions: permissions, encryption, antivirus, - compression + compression, + transformations } = data.bucket; const compressionOptions = [ @@ -215,6 +217,18 @@ } ); } + + function updateTransformations() { + updateBucket( + data.bucket, + { + transformations + }, + { + trackEventName: Submit.BucketUpdateTransformations + } + ); + } @@ -366,6 +380,28 @@ +
+ + Image transformations + + + + + + + + +
+
diff --git a/src/routes/(console)/supportWizard.svelte b/src/routes/(console)/supportWizard.svelte index eb25fceef..59f17d369 100644 --- a/src/routes/(console)/supportWizard.svelte +++ b/src/routes/(console)/supportWizard.svelte @@ -1,11 +1,17 @@ +{#snippet severityPopover()} + + +
+ + + Critical: System is down or a critical component is non-functional, causing + a complete stoppage of work or significant business impact. + + + High: Major functionality is impaired, but a workaround is available, or a + critical component is significantly degraded. + + + Medium: Minor functionality is impaired without significant business impact. + + + Low: Issue has minor impact on business operations; workaround is not necessary. + + + Question: Requests for information, general guidance, or feature requests. + + +
+
+{/snippet} + @@ -113,24 +223,48 @@ Choose a topic + >Choose a category - {#each ['general', 'billing', 'technical'] as category} + {#each categories as category} { - $supportData.category = category; + if ($supportData.category !== category.value) { + $supportData.topic = undefined; + } + $supportData.category = category.value; }} - selected={$supportData.category === category}>{category} + selected={$supportData.category === category.value} + >{category.label} {/each} - 0} + {#key $supportData.category} + + {/key} + {/if} + + +
+ {@render severityPopover()} +
+
- { wizard.hide(); - }}>Cancel - Submit + }}>Cancel + diff --git a/src/routes/(console)/wizard/support/store.ts b/src/routes/(console)/wizard/support/store.ts index 06f671b6a..56d0e76b2 100644 --- a/src/routes/(console)/wizard/support/store.ts +++ b/src/routes/(console)/wizard/support/store.ts @@ -4,6 +4,8 @@ export type SupportData = { message: string; subject: string; category: string; + topic?: string; + severity?: string; file?: File | null; project?: string; }; @@ -11,7 +13,8 @@ export type SupportData = { export const supportData = writable({ message: '', subject: '', - category: 'general', + category: 'technical', + severity: 'question', file: null }); diff --git a/src/routes/(public)/functions/deploy/+page.ts b/src/routes/(public)/functions/deploy/+page.ts index 661bf8c65..3a5d13724 100644 --- a/src/routes/(public)/functions/deploy/+page.ts +++ b/src/routes/(public)/functions/deploy/+page.ts @@ -81,8 +81,7 @@ export const load: PageLoad = async ({ parent, url }) => { 'Personal Projects', resolvedProfile.freeTier, null, - resolvedProfile.organizationPlatform, - null + resolvedProfile.organizationPlatform ); } else { await sdk.forConsole.teams.create({ diff --git a/src/routes/(public)/template-[template]/+page.ts b/src/routes/(public)/template-[template]/+page.ts index d85d67213..a185fd828 100644 --- a/src/routes/(public)/template-[template]/+page.ts +++ b/src/routes/(public)/template-[template]/+page.ts @@ -55,7 +55,7 @@ export const load = async ({ parent, url, params }) => { 'Personal project', BillingPlan.FREE, null, - null + resolvedProfile.organizationPlatform ); } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 962e62cd1..97bdc76dc 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -363,6 +363,11 @@ } } + /* Fix when no vertical scrollbar is present, some environments reserve a gutter by default */ + html { + scrollbar-gutter: auto !important; + } + /* TODO: remove this block once Pink V2 is incorporated */ input[type='radio'], input[type='checkbox']:not([class='switch']),