diff --git a/.github/workflows/copilot-setup-steps.yml b/.github/workflows/copilot-setup-steps.yml new file mode 100644 index 000000000..6926b0c50 --- /dev/null +++ b/.github/workflows/copilot-setup-steps.yml @@ -0,0 +1,28 @@ +name: Copilot Setup Steps + +# Automatically run the setup steps when they are changed to allow for easy validation, and +# allow manual testing through the repository's "Actions" tab +on: + workflow_dispatch: + push: + paths: + - .github/workflows/copilot-setup-steps.yml + pull_request: + paths: + - .github/workflows/copilot-setup-steps.yml + +jobs: + copilot-setup-steps: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v5 + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version: 20 + - name: Install pnpm + uses: pnpm/action-setup@v4 + - name: Install dependencies + run: pnpm install --frozen-lockfile diff --git a/src/lib/components/apiEndpoint.svelte b/src/lib/components/apiEndpoint.svelte new file mode 100644 index 000000000..33e70341d --- /dev/null +++ b/src/lib/components/apiEndpoint.svelte @@ -0,0 +1,15 @@ + + + + + + + API endpoint + + + diff --git a/src/lib/components/backupRestoreBox.svelte b/src/lib/components/backupRestoreBox.svelte index 2f660985e..f1de9d3ba 100644 --- a/src/lib/components/backupRestoreBox.svelte +++ b/src/lib/components/backupRestoreBox.svelte @@ -125,20 +125,18 @@ onMount(() => { // fast path: don't subscribe if org is on a free plan or is self-hosted. - if (isSelfHosted || (isCloud && $organization.billingPlan === BillingPlan.FREE)) return; + if (isSelfHosted || (isCloud && $organization?.billingPlan === BillingPlan.FREE)) return; - return realtime - .forProject(page.params.region, page.params.project) - .subscribe('console', (response) => { - if (!response.channels.includes(`projects.${getProjectId()}`)) return; + return realtime.forProject(page.params.region, 'console', (response) => { + if (!response.channels.includes(`projects.${getProjectId()}`)) return; - if ( - response.events.includes('archives.*') || - response.events.includes('restorations.*') - ) { - updateOrAddItem(response.payload); - } - }); + if ( + response.events.includes('archives.*') || + response.events.includes('restorations.*') + ) { + updateOrAddItem(response.payload); + } + }); }); diff --git a/src/lib/components/copy.svelte b/src/lib/components/copy.svelte index c178913c7..d9a619e01 100644 --- a/src/lib/components/copy.svelte +++ b/src/lib/components/copy.svelte @@ -57,6 +57,7 @@ disabled={tooltipDisabled} portal={tooltipPortal} delay={tooltipDelay} + maxWidth="500px" placement={tooltipPlacement}> { + return realtime.forConsole(page.params.region, 'console', (response) => { if (!response.channels.includes(`projects.${getProjectId()}`)) return; if (response.events.includes('migrations.*')) { updateOrAddItem(response.payload as Payload); diff --git a/src/lib/components/id.svelte b/src/lib/components/id.svelte index 314e8fac2..201f651c1 100644 --- a/src/lib/components/id.svelte +++ b/src/lib/components/id.svelte @@ -95,10 +95,11 @@ export let tooltipPortal = false; export let tooltipDelay: number = 0; export let tooltipPlacement: TooltipPlacement = undefined; + export let copyText: string | undefined = undefined; {#key value} - + { - return realtime - .forProject(page.params.region, page.params.project) - .subscribe(['console'], async (response) => { - if (!response.channels.includes(`projects.${getProjectId()}`)) return; - if (response.events.includes('migrations.*')) { - if (response.payload.source === 'Backup') return; - migration = response.payload; - } - }); + return realtime.forProject(page.params.region, ['console'], async (response) => { + if (!response.channels.includes(`projects.${getProjectId()}`)) return; + if (response.events.includes('migrations.*')) { + const payload = response.payload as Models.Migration; + if (payload.source === 'Backup') return; + migration = payload; + } + }); }); diff --git a/src/lib/components/regionEndpoint.svelte b/src/lib/components/regionEndpoint.svelte index aeaef43de..3d9bae139 100644 --- a/src/lib/components/regionEndpoint.svelte +++ b/src/lib/components/regionEndpoint.svelte @@ -1,9 +1,9 @@ {#if region} - - - - {#if flagSrc} - {region?.name} - {/if} - - - {region?.name} - - + + + + API endpoint + {#if flagSrc} + {region?.name} + {/if} {/if} + + diff --git a/src/lib/stores/sdk.ts b/src/lib/stores/sdk.ts index 8fd1b477b..92c5a53cf 100644 --- a/src/lib/stores/sdk.ts +++ b/src/lib/stores/sdk.ts @@ -42,7 +42,6 @@ import { SUBDOMAIN_TOR } from '$lib/constants'; import { building } from '$app/environment'; -import { getProjectId } from '$lib/helpers/project'; export function getApiEndpoint(region?: string): string { if (building) return ''; @@ -141,12 +140,32 @@ const sdkForProject = { }; export const realtime = { - forProject(region: string, _projectId: string) { + forProject( + region: string, + channels: string | string[], + callback: AppwriteRealtimeResponseEvent + ) { const endpoint = getApiEndpoint(region); if (endpoint !== clientRealtime.config.endpoint) { clientRealtime.setEndpoint(endpoint); } - return clientRealtime; + + // because uses a different client! + const realtime = new Realtime(clientRealtime); + + return createRealtimeSubscription(realtime, channels, callback); + }, + + forConsole( + region: string, + channels: string | string[], + callback: AppwriteRealtimeResponseEvent + ): () => void { + const realtimeInstance = region + ? sdk.forConsoleIn(region).realtime + : sdk.forConsole.realtime; + + return createRealtimeSubscription(realtimeInstance, channels, callback); } }; @@ -176,8 +195,8 @@ export const sdk = { }; export enum RuleType { - DEPLOYMENT = 'deployment', API = 'api', + DEPLOYMENT = 'deployment', REDIRECT = 'redirect' } @@ -191,11 +210,24 @@ export enum RuleTrigger { MANUAL = 'manual' } -/** - * Some type imports are broken on the SDK, this works correctly for the time being! - */ -export type AppwriteRealtimeSubscription = Awaited>; - -export const createAdminClient = () => { - return new Client().setEndpoint(getApiEndpoint()).setMode('admin').setProject(getProjectId()); +export type RealtimeResponse = { + events: string[]; + channels: string[]; + timestamp: string; + payload: unknown; }; + +export type AppwriteRealtimeResponseEvent = (response: RealtimeResponse) => void; + +function createRealtimeSubscription( + realtimeInstance: Realtime, + channels: string | string[], + callback: AppwriteRealtimeResponseEvent +): () => void { + const channelsArray = Array.isArray(channels) ? channels : [channels]; + const subscriptionPromise = realtimeInstance.subscribe(channelsArray, callback); + + return () => { + subscriptionPromise.then((sub) => sub.close()); + }; +} diff --git a/src/routes/(console)/project-[region]-[project]/+layout.svelte b/src/routes/(console)/project-[region]-[project]/+layout.svelte index f233956c0..426821259 100644 --- a/src/routes/(console)/project-[region]-[project]/+layout.svelte +++ b/src/routes/(console)/project-[region]-[project]/+layout.svelte @@ -27,15 +27,13 @@ import CsvImportBox from '$lib/components/csvImportBox.svelte'; onMount(() => { - return realtime - .forProject(page.params.region, page.params.project) - .subscribe(['project', 'console'], (response) => { - if (response.events.includes('stats.connections')) { - for (const [projectId, value] of Object.entries(response.payload)) { - stats.add(projectId, [new Date(response.timestamp).toISOString(), value]); - } + return realtime.forProject(page.params.region, ['project', 'console'], (response) => { + if (response.events.includes('stats.connections')) { + for (const [projectId, value] of Object.entries(response.payload)) { + stats.add(projectId, [new Date(response.timestamp).toISOString(), value]); } - }); + } + }); }); $: $registerCommands([ diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte index b9c1c57c8..99521078d 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte @@ -161,19 +161,14 @@ }; onMount(() => { - return realtime - .forProject(page.params.region, page.params.project) - .subscribe(['project', 'console'], (response) => { - // fast path return. - if (!response.channels.includes(`projects.${getProjectId()}`)) return; + return realtime.forProject(page.params.region, ['project', 'console'], (response) => { + // fast path return. + if (!response.channels.includes(`projects.${getProjectId()}`)) return; - if ( - response.events.includes('archives.*') || - response.events.includes('policies.*') - ) { - invalidate(Dependencies.BACKUPS); - } - }); + if (response.events.includes('archives.*') || response.events.includes('policies.*')) { + invalidate(Dependencies.BACKUPS); + } + }); }); diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte index cfefc3a7f..f5908ae50 100644 --- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte +++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte @@ -20,7 +20,7 @@ diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte index 7c4280fc1..55a275d5b 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte @@ -4,7 +4,7 @@ import { Dependencies } from '$lib/constants'; import { Button } from '$lib/elements/forms'; import { Container, ResponsiveContainerHeader } from '$lib/layout'; - import { sdk } from '$lib/stores/sdk'; + import { realtime } from '$lib/stores/sdk'; import { onMount } from 'svelte'; import { project } from '$routes/(console)/project-[region]-[project]/store'; import { base } from '$app/paths'; @@ -12,11 +12,13 @@ import { IconPlus } from '@appwrite.io/pink-icons-svelte'; import Table from './table.svelte'; import { columns } from './store'; + import type { PageProps } from './$types'; + import { page } from '$app/state'; - export let data; + let { data }: PageProps = $props(); onMount(() => { - return sdk.forConsole.realtime.subscribe('console', (response) => { + return realtime.forConsole(page.params.region, 'console', (response) => { if (response.events.includes('functions.*.executions.*')) { invalidate(Dependencies.EXECUTIONS); } 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 0df14759c..84e6a7809 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte @@ -15,6 +15,7 @@ import { writable } from 'svelte/store'; import Scopes from '../api-keys/scopes.svelte'; import { page } from '$app/state'; + import { copy } from '$lib/helpers/copy'; const projectId = page.params.project; @@ -28,7 +29,7 @@ async function create() { try { - const { $id } = await sdk.forConsole.projects.createKey({ + const { $id, secret } = await sdk.forConsole.projects.createKey({ projectId, name, scopes, @@ -45,7 +46,21 @@ ); addNotification({ message: `API key has been created`, - type: 'success' + type: 'success', + buttons: [ + { + name: 'Copy API key', + method: async () => { + await copy(secret); + } + }, + { + name: 'Copy endpoint', + method: async () => { + await copy(sdk.forConsole.client.config.endpoint); + } + } + ] }); } catch (error) { addNotification({ diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/[key]/header.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/[key]/header.svelte index 0b4b527d6..984700097 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/[key]/header.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/[key]/header.svelte @@ -3,6 +3,10 @@ import { page } from '$app/state'; import { Cover, CoverTitle } from '$lib/layout'; import { key } from './store'; + import { RegionEndpoint, Copy } from '$lib/components'; + import { Layout, Tag, Icon } from '@appwrite.io/pink-svelte'; + import { IconDuplicate } from '@appwrite.io/pink-icons-svelte'; + import { projectRegion } from '../../../store'; const projectId = page.params.project; @@ -12,5 +16,26 @@ {$key?.name} + + {#if $key?.secret} + + + + API secret + + + {/if} + {#if $projectRegion} + + {/if} + + + diff --git a/src/routes/(console)/project-[region]-[project]/overview/assets/platform-sdk-dark.png b/src/routes/(console)/project-[region]-[project]/overview/assets/platform-sdk-dark.png new file mode 100644 index 000000000..e778c55b9 Binary files /dev/null and b/src/routes/(console)/project-[region]-[project]/overview/assets/platform-sdk-dark.png differ diff --git a/src/routes/(console)/project-[region]-[project]/overview/assets/platform-sdk.jpg b/src/routes/(console)/project-[region]-[project]/overview/assets/platform-sdk.jpg new file mode 100644 index 000000000..b891d6a12 Binary files /dev/null and b/src/routes/(console)/project-[region]-[project]/overview/assets/platform-sdk.jpg differ diff --git a/src/routes/(console)/project-[region]-[project]/overview/header.svelte b/src/routes/(console)/project-[region]-[project]/overview/header.svelte index 8a412281c..ff2107397 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/header.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/header.svelte @@ -2,19 +2,24 @@ import { page } from '$app/state'; import { Id, RegionEndpoint } from '$lib/components'; import { Cover } from '$lib/layout'; - import { project, projectRegion } from '../store'; + import { projectRegion } from '../store'; import { hasOnboardingDismissed, setHasOnboardingDismissed } from '$lib/helpers/onboarding'; import { goto } from '$app/navigation'; - import { base } from '$app/paths'; + import { resolve } from '$app/paths'; import { Layout, Button, Typography } from '@appwrite.io/pink-svelte'; import { user } from '$lib/stores/user'; import { isSmallViewport } from '$lib/stores/viewport'; import { trackEvent } from '$lib/actions/analytics'; function dismissOnboarding() { - setHasOnboardingDismissed($project.$id, $user); + setHasOnboardingDismissed(page.params.project, $user); trackEvent('onboarding_hub_platform_dismiss'); - goto(`${base}/project-${$project.region}-${$project.$id}/overview/platforms`); + goto( + resolve('/(console)/project-[region]-[project]/overview/platforms', { + region: page.params.region, + project: page.params.project + }) + ); } @@ -24,12 +29,15 @@ - {$project?.name} + {page.data.project?.name} - {$project.$id} - + {page.params.project} + {#if $projectRegion} + + {/if} @@ -53,7 +61,7 @@ >Follow a few quick steps to get started with Appwrite
- {#if !hasOnboardingDismissed($project.$id, $user)} + {#if !hasOnboardingDismissed(page.params.project, $user)} Dismiss this page diff --git a/src/routes/(console)/project-[region]-[project]/overview/onboard.svelte b/src/routes/(console)/project-[region]-[project]/overview/onboard.svelte index 5b98b45d1..78757226d 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/onboard.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/onboard.svelte @@ -14,12 +14,7 @@ import { app } from '$lib/stores/app'; import AuthPreview from './assets/auth-preview.svg'; import AuthPreviewDark from './assets/auth-preview-dark.svg'; - import { - IconArrowRight, - IconNodeJs, - IconPhp, - IconPython - } from '@appwrite.io/pink-icons-svelte'; + import { IconArrowRight } from '@appwrite.io/pink-icons-svelte'; import DatabaseImgSource from './assets/database.png'; import DatabaseImgSourceDark from './assets/database-dark.png'; import DiscordImgSource from './assets/discord.png'; @@ -31,9 +26,10 @@ import PlatformAndroidImgSourceDark from './assets/platform-android-dark.svg'; import PlatformFlutterImgSource from './assets/platform-flutter.svg'; import PlatformFlutterImgSourceDark from './assets/platform-flutter-dark.svg'; + import PlatformSdkImgSource from './assets/platform-sdk.jpg'; + import PlatformSdkImgSourceDark from './assets/platform-sdk-dark.png'; import { base } from '$app/paths'; import { isSmallViewport } from '$lib/stores/viewport'; - import { AvatarGroup } from '$lib/components'; import type { Models } from '@appwrite.io/console'; import { getPlatformInfo } from '$lib/helpers/platform'; import { Click, trackEvent } from '$lib/actions/analytics'; @@ -103,7 +99,9 @@
- + { openPlatformWizard(0, platformMap.get('Web')); @@ -341,17 +339,34 @@ - - Or connect - server side -
- -
-
+ or + + + +
+ + + Create API key + Connect your server or backend to Appwrite + +
+ +
+
+
+
+
{ - let subscription: AppwriteRealtimeSubscription; - sdk.forConsole.realtime - .subscribe('console', (response) => { - if (response.events.includes(`projects.${projectId}.ping`)) { - connectionSuccessful = true; - invalidate(Dependencies.ORGANIZATION); - invalidate(Dependencies.PROJECT); - subscription?.close(); - } - }) - .then((realtime) => (subscription = realtime)); + const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { + if (response.events.includes(`projects.${projectId}.ping`)) { + connectionSuccessful = true; + invalidate(Dependencies.ORGANIZATION); + invalidate(Dependencies.PROJECT); + unsubscribe(); + } + }); return () => { - subscription?.close(); + unsubscribe(); resetPlatformStore(); }; }); 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 ff672f611..7c1ae8ee6 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte @@ -18,7 +18,7 @@ import { Card } from '$lib/components'; import { page } from '$app/state'; import { onMount } from 'svelte'; - import { type AppwriteRealtimeSubscription, sdk } from '$lib/stores/sdk'; + import { 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'; @@ -72,8 +72,10 @@ APPWRITE_PUBLIC_ENDPOINT: "${sdk.forProject(page.params.region, page.params.proj message: 'Platform created.' }); - invalidate(Dependencies.PROJECT); - invalidate(Dependencies.PLATFORMS); + await Promise.all([ + invalidate(Dependencies.PROJECT), + invalidate(Dependencies.PLATFORMS) + ]); } catch (error) { trackError(error, Submit.PlatformCreate); addNotification({ @@ -90,20 +92,17 @@ APPWRITE_PUBLIC_ENDPOINT: "${sdk.forProject(page.params.region, page.params.proj } onMount(() => { - let subscription: AppwriteRealtimeSubscription; - sdk.forConsole.realtime - .subscribe('console', (response) => { - if (response.events.includes(`projects.${projectId}.ping`)) { - connectionSuccessful = true; - invalidate(Dependencies.ORGANIZATION); - invalidate(Dependencies.PROJECT); - subscription?.close(); - } - }) - .then((realtime) => (subscription = realtime)); + const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { + if (response.events.includes(`projects.${projectId}.ping`)) { + connectionSuccessful = true; + invalidate(Dependencies.ORGANIZATION); + invalidate(Dependencies.PROJECT); + unsubscribe(); + } + }); return () => { - subscription?.close(); + unsubscribe(); resetPlatformStore(); }; }); 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 f04ed60e3..65f7b732c 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 { type AppwriteRealtimeSubscription, sdk } from '$lib/stores/sdk'; + import { 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'; @@ -138,8 +138,10 @@ message: 'Platform created.' }); - invalidate(Dependencies.PROJECT); - invalidate(Dependencies.PLATFORMS); + await Promise.all([ + invalidate(Dependencies.PROJECT), + invalidate(Dependencies.PLATFORMS) + ]); } catch (error) { trackError(error, Submit.PlatformCreate); addNotification({ @@ -156,20 +158,17 @@ } onMount(() => { - let subscription: AppwriteRealtimeSubscription; - sdk.forConsole.realtime - .subscribe('console', (response) => { - if (response.events.includes(`projects.${projectId}.ping`)) { - connectionSuccessful = true; - invalidate(Dependencies.ORGANIZATION); - invalidate(Dependencies.PROJECT); - subscription?.close(); - } - }) - .then((realtime) => (subscription = realtime)); + const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { + if (response.events.includes(`projects.${projectId}.ping`)) { + connectionSuccessful = true; + invalidate(Dependencies.ORGANIZATION); + invalidate(Dependencies.PROJECT); + unsubscribe(); + } + }); return () => { - subscription?.close(); + unsubscribe(); resetPlatformStore(); }; }); 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 cd5f35eab..f8c8f17c0 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte @@ -18,7 +18,7 @@ import { Card } from '$lib/components'; import { page } from '$app/state'; import { onMount } from 'svelte'; - import { type AppwriteRealtimeSubscription, sdk } from '$lib/stores/sdk'; + import { 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'; @@ -99,8 +99,10 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p message: 'Platform created.' }); - invalidate(Dependencies.PROJECT); - invalidate(Dependencies.PLATFORMS); + await Promise.all([ + invalidate(Dependencies.PROJECT), + invalidate(Dependencies.PLATFORMS) + ]); } catch (error) { trackError(error, Submit.PlatformCreate); addNotification({ @@ -117,20 +119,17 @@ EXPO_PUBLIC_APPWRITE_ENDPOINT=${sdk.forProject(page.params.region, page.params.p } onMount(() => { - let subscription: AppwriteRealtimeSubscription; - sdk.forConsole.realtime - .subscribe('console', (response) => { - if (response.events.includes(`projects.${projectId}.ping`)) { - connectionSuccessful = true; - invalidate(Dependencies.ORGANIZATION); - invalidate(Dependencies.PROJECT); - subscription?.close(); - } - }) - .then((realtime) => (subscription = realtime)); + const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { + if (response.events.includes(`projects.${projectId}.ping`)) { + connectionSuccessful = true; + invalidate(Dependencies.ORGANIZATION); + invalidate(Dependencies.PROJECT); + unsubscribe(); + } + }); return () => { - subscription?.close(); + unsubscribe(); resetPlatformStore(); }; }); 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 681abc97b..31ec878fc 100644 --- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte +++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte @@ -28,7 +28,7 @@ } from '@appwrite.io/pink-icons-svelte'; import { page } from '$app/state'; import { onMount } from 'svelte'; - import { type AppwriteRealtimeSubscription, sdk } from '$lib/stores/sdk'; + import { 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'; @@ -184,8 +184,10 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p message: 'Platform created.' }); - invalidate(Dependencies.PROJECT); - invalidate(Dependencies.PLATFORMS); + await Promise.all([ + invalidate(Dependencies.PROJECT), + invalidate(Dependencies.PLATFORMS) + ]); } catch (error) { trackError(error, Submit.PlatformCreate); addNotification({ @@ -202,21 +204,18 @@ ${prefix}APPWRITE_ENDPOINT = "${sdk.forProject(page.params.region, page.params.p } onMount(() => { - let subscription: AppwriteRealtimeSubscription; - sdk.forConsole.realtime - .subscribe('console', (response) => { - if (response.events.includes(`projects.${projectId}.ping`)) { - connectionSuccessful = true; - invalidate(Dependencies.ORGANIZATION); - invalidate(Dependencies.PROJECT); - subscription?.close(); - } - }) - .then((realtime) => (subscription = realtime)); + const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => { + if (response.events.includes(`projects.${projectId}.ping`)) { + connectionSuccessful = true; + invalidate(Dependencies.ORGANIZATION); + invalidate(Dependencies.PROJECT); + unsubscribe(); + } + }); return () => { + unsubscribe(); resetPlatformStore(); - subscription?.close(); }; }); diff --git a/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte index b6f8083bc..cc82cb18c 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte @@ -38,13 +38,11 @@ let migration: Models.Migration = null; onMount(() => { - return realtime - .forProject(page.params.region, page.params.project) - .subscribe(['project', 'console'], (response) => { - if (response.events.includes('migrations.*')) { - invalidate(Dependencies.MIGRATIONS); - } - }); + return realtime.forProject(page.params.region, ['project', 'console'], (response) => { + if (response.events.includes('migrations.*')) { + invalidate(Dependencies.MIGRATIONS); + } + }); }); $: $registerCommands([ diff --git a/src/routes/(console)/project-[region]-[project]/sites/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/+page.svelte index e1eb6bb66..3c4ee175a 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/+page.svelte @@ -25,7 +25,8 @@ import { onMount } from 'svelte'; import { invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; - import { sdk } from '$lib/stores/sdk'; + import { realtime } from '$lib/stores/sdk'; + import { page } from '$app/state'; export let data; @@ -49,7 +50,7 @@ $updateCommandGroupRanks({ sites: 1000 }); onMount(() => { - return sdk.forConsole.realtime.subscribe('console', (response) => { + return realtime.forConsole(page.params.region, 'console', (response) => { if (response.events.includes('sites.*')) { invalidate(Dependencies.SITES); } diff --git a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte index bdb1741ac..3cb100543 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte @@ -7,42 +7,36 @@ import Aside from '../aside.svelte'; import Logs from '../../(components)/logs.svelte'; import { Copy, SvgIcon } from '$lib/components'; - import { type AppwriteRealtimeSubscription, sdk } from '$lib/stores/sdk'; + import { realtime } from '$lib/stores/sdk'; import { goto } from '$app/navigation'; import { onMount } from 'svelte'; import { getFrameworkIcon } from '$lib/stores/sites'; + import type { Models } from '@appwrite.io/console'; let { data } = $props(); let deployment = $state(data.deployment); onMount(() => { - let subscription: AppwriteRealtimeSubscription; - sdk.forConsoleIn(page.params.region) - .realtime.subscribe('console', async (response) => { - if ( - response.events.includes( - `sites.${data.site.$id}.deployments.${data.deployment.$id}.update` - ) - ) { - deployment = response.payload; - if (response.payload.status === 'ready') { - const resolvedUrl = resolve( - '/(console)/project-[region]-[project]/sites/create-site/finish', - { - region: page.params.region, - project: page.params.project - } - ); - await goto(`${resolvedUrl}?site=${data.site.$id}`); - } + return realtime.forConsole(page.params.region, 'console', async (response) => { + if ( + response.events.includes( + `sites.${data.site.$id}.deployments.${data.deployment.$id}.update` + ) + ) { + deployment = response.payload as Models.Deployment; + if (deployment.status === 'ready') { + const resolvedUrl = resolve( + '/(console)/project-[region]-[project]/sites/create-site/finish', + { + region: page.params.region, + project: page.params.project + } + ); + await goto(`${resolvedUrl}?site=${data.site.$id}`); } - }) - .then((realtime) => (subscription = realtime)); - - return () => { - subscription?.close(); - }; + } + }); }); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte index adbf16091..9a3c98817 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte @@ -7,19 +7,21 @@ import { Button } from '$lib/elements/forms'; import InstantRollbackDomain from './instantRollbackModal.svelte'; import { app } from '$lib/stores/app'; - import { sdk } from '$lib/stores/sdk'; + import { realtime } from '$lib/stores/sdk'; import { invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; import { onMount } from 'svelte'; import { page } from '$app/state'; import { base } from '$app/paths'; + import type { PageProps } from './$types'; import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store'; - export let data; - let showRollback = false; + let { data }: PageProps = $props(); + + let showRollback = $state(false); onMount(() => { - return sdk.forConsole.realtime.subscribe('console', (response) => { + return realtime.forConsole(page.params.region, 'console', (response) => { if (response.events.includes(`sites.${page.params.site}.deployments.*`)) { invalidate(Dependencies.SITE); } diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte index 8ff3fe4e8..64a7454fa 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte @@ -1,7 +1,7 @@ diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte index 7d710cb40..3ad6b4645 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte @@ -4,16 +4,17 @@ import { Dependencies } from '$lib/constants'; import { Button } from '$lib/elements/forms'; import { Container, ResponsiveContainerHeader } from '$lib/layout'; - import { sdk } from '$lib/stores/sdk'; + import { realtime } from '$lib/stores/sdk'; import { onMount } from 'svelte'; import Table from './table.svelte'; import { Card, Empty } from '@appwrite.io/pink-svelte'; import { columns } from './store'; + import { page } from '$app/state'; export let data; onMount(() => { - return sdk.forConsole.realtime.subscribe('console', (response) => { + return realtime.forConsole(page.params.region, 'console', (response) => { if (response.events.includes('sites.*.executions.*')) { invalidate(Dependencies.EXECUTIONS); }