Skip to content

Conversation

@ItzNotABug
Copy link
Member

@ItzNotABug ItzNotABug commented Oct 27, 2025

What does this PR do?

(Provide a description of what this PR does.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • Refactor
    • Unified realtime subscription flow across the console for consistent live-update behavior and simpler lifecycle handling.
    • Improved subscription lifecycle to use a single callback/unsubscribe pattern, reducing complexity and cleanup errors.
  • Bug Fixes
    • Reduced subscription leaks and ensured subscriptions terminate reliably after relevant events, improving stability.
    • Prevented runtime errors when organization data is unavailable.
    • Faster, more reliable invalidation and navigation when deployments and related resources reach ready states.

@railway-app
Copy link

railway-app bot commented Oct 27, 2025

This PR was not deployed automatically as @ItzNotABug does not have access to the Railway project.

In order to get automatic PR deploys, please add @ItzNotABug to your workspace on Railway.

@appwrite
Copy link

appwrite bot commented Oct 27, 2025

Console

Project ID: 688b7bf400350cbd60e9

Sites (1)
Site Status Logs Preview QR
 console-stage
688b7cf6003b1842c9dc
Ready Ready View Logs Preview URL QR Code

Tip

Appwrite has a Discord community with over 16 000 members.

@ItzNotABug ItzNotABug self-assigned this Oct 27, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 27, 2025

Walkthrough

This PR replaces subscribe-style realtime usage with a closure-based API: realtime.forConsole(...) and realtime.forProject(...). Many components and pages switch their onMount subscription setup/teardown to use the returned unsubscribe closure. The sdk store is reworked: new RealtimeResponse and AppwriteRealtimeResponseEvent types, createRealtimeSubscription helper, forConsole added, and AppwriteRealtimeSubscription and createAdminClient removed. Several pages move from exporting data to reading typed PageProps via $props(). A few runtime guards were hardened with optional chaining.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Change characteristics: large, consistent pattern replacement across many files with a concentrated, higher-impact refactor in src/lib/stores/sdk.ts.
  • Heterogeneity: mostly repetitive API swaps, with some files adding types or changing prop consumption that require individual checks.

Files/areas to pay extra attention:

  • src/lib/stores/sdk.ts — new createRealtimeSubscription, forConsole/forProject signatures, added types, and removed exports.
  • Files that changed subscription lifecycle from .then(...).close() or .close() to invoking returned unsubscribe closures — verify cleanup ordering and that subscriptions are always terminated (platform create pages, deploying/deployment pages).
  • Pages that switched from export let data to PageProps/$props() — ensure props typing and consumption are correct.
  • Files where event payload typing changed (e.g., deployments, migrations, backups, table layout) — validate payload extraction and status/event checks.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title "Fix: logic in onMount for realtime" is vague and uses non-descriptive language that doesn't convey meaningful information about the changeset. While it references real components being modified (onMount and realtime), the actual PR is a comprehensive refactoring of the realtime subscription API across approximately 20 files—changing from a chained subscription pattern to a callback-based approach with region-aware handling. The term "fix" combined with "logic" is too generic to help a teammate understand the scope and nature of this significant architectural change from a title scan alone. The title appears to describe a targeted bug fix rather than a systematic API refactoring. Consider revising the title to be more specific and descriptive, such as "Refactor: realtime subscription API to callback-based pattern with region parameter" or "Refactor: convert realtime subscriptions from chained to direct callback API". This would clearly communicate that the PR involves systematic API changes across multiple files rather than a localized fix in onMount handlers.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-realtime-logic

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f27386 and fff134e.

📒 Files selected for processing (6)
  • src/lib/stores/sdk.ts (3 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte
📚 Learning: 2025-10-05T09:41:40.439Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2398
File: src/routes/(console)/verify-email/+page.svelte:48-51
Timestamp: 2025-10-05T09:41:40.439Z
Learning: In SvelteKit 5, `page` imported from `$app/state` is a reactive state object (using runes), not a store. It should be accessed as `page.data` without the `$` prefix, unlike the store-based `$page` from `$app/stores` in earlier versions.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte
📚 Learning: 2025-10-21T06:07:53.455Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2477
File: src/routes/(console)/project-[region]-[project]/overview/platforms/llmBanner.svelte:27-38
Timestamp: 2025-10-21T06:07:53.455Z
Learning: In the Appwrite Console codebase, the `copy` helper utility (src/lib/helpers/copy.ts) already handles errors internally with try-catch blocks and returns a boolean success indicator. Additional error handling with try-catch is not needed when calling this utility.

Applied to files:

  • src/lib/stores/sdk.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (9)
src/lib/stores/sdk.ts (3)

143-157: LGTM: Clean delegation to subscription helper.

The forProject method properly instantiates a region-aware realtime client and delegates to createRealtimeSubscription. The pattern is clear and consistent.


159-169: LGTM: Region-aware console subscription.

The forConsole method correctly selects region-specific or default console realtime instances and delegates to the subscription helper.


213-220: LGTM: Well-defined realtime types.

The RealtimeResponse and AppwriteRealtimeResponseEvent types provide clear contracts for the new subscription API.

src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (3)

21-21: LGTM: Import updated for new realtime API.

The import correctly reflects the migration from subscription-based to callback-based realtime handling.


141-144: LGTM: Parallel invalidations improve performance.

Using Promise.all for concurrent invalidations is more efficient than sequential awaits.


160-174: LGTM: Proper synchronous onMount with cleanup.

The refactored onMount correctly:

  • Returns a cleanup function synchronously (fixes the async issue from past reviews)
  • Uses the new realtime.forConsole API
  • Handles both success (ping event) and unmount cleanup paths

Note: The unsubscribe() function is called in both the event handler (line 166) and cleanup (line 171). This is safe once the error handling in createRealtimeSubscription (sdk.ts) is added.

src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte (1)

21-21: LGTM: Consistent migration to new realtime API.

All changes mirror the pattern in createFlutter.svelte:

  • Import updated for the new realtime API (line 21)
  • Parallel invalidations with Promise.all (lines 102-105)
  • Synchronous onMount with proper cleanup (lines 121-135)

The double-unsubscribe pattern (lines 127, 132) is safe once the error handling in createRealtimeSubscription is added.

Also applies to: 102-105, 121-135

src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte (1)

20-20: LGTM: Consistent realtime migration pattern.

All changes follow the established pattern:

  • Updated imports (line 20)
  • Parallel invalidations (lines 66-69)
  • Synchronous onMount with unsubscribe cleanup (lines 85-99)

The implementation correctly addresses the async onMount issue from previous reviews.

Also applies to: 66-69, 85-99

src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte (1)

31-31: LGTM: Final platform file follows the migration pattern.

All changes are consistent with the other platform creation files:

  • Import updated for new realtime API (line 31)
  • Parallel invalidations (lines 187-190)
  • Synchronous onMount with cleanup (lines 206-220)

The refactor successfully addresses the async onMount cleanup issue flagged in previous reviews.

Also applies to: 187-190, 206-220


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte (1)

19-43: Critical: onMount is async; teardown won’t register

Make onMount synchronous; chain the subscribe promise and guard close to avoid leaks. (svelte.dev)

-onMount(async () => {
-    const subscription: AppwriteRealtimeSubscription = await 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 subscription.close();
-});
+onMount(() => {
+    let subscription: AppwriteRealtimeSubscription | undefined;
+    let closed = false;
+
+    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}`);
+                }
+            }
+        })
+        .then((s) => (closed ? s.close() : (subscription = s)))
+        .catch((e) => console.error('Realtime subscribe failed', e));
+
+    return () => {
+        if (!closed) {
+            closed = true;
+            subscription?.close();
+        }
+    };
+});
🧹 Nitpick comments (4)
src/lib/components/csvImportBox.svelte (1)

161-170: Consider using await for consistency.

Since onMount is now async, consider converting the promise chain to use await for consistency with the subscription pattern below. This also enables better error handling if needed.

Apply this diff:

-        sdk.forProject(page.params.region, page.params.project)
-            .migrations.list({
-                queries: [
-                    Query.equal('source', 'CSV'),
-                    Query.equal('status', ['pending', 'processing'])
-                ]
-            })
-            .then((migrations) => {
-                migrations.migrations.forEach(updateOrAddItem);
-            });
+        const migrations = await sdk
+            .forProject(page.params.region, page.params.project)
+            .migrations.list({
+                queries: [
+                    Query.equal('source', 'CSV'),
+                    Query.equal('status', ['pending', 'processing'])
+                ]
+            });
+        migrations.migrations.forEach(updateOrAddItem);
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte (1)

33-44: Consider adding error handling for subscription setup.

The async subscription setup has no error handling. If the subscription fails to establish, it could lead to unhandled promise rejections.

Consider wrapping the subscription in a try-catch:

 onMount(async () => {
+    try {
         const subscription: AppwriteRealtimeSubscription = await sdk
             .forConsoleIn(page.params.region)
             .realtime.subscribe('console', async (response) => {
                 if (
                     response.events.includes(
                         `sites.${page.params.site}.deployments.${page.params.deployment}.update`
                     )
                 ) {
                     await invalidate(Dependencies.DEPLOYMENT);
                 }
             });
 
-        return subscription?.close();
+        return () => subscription?.close();
+    } catch (error) {
+        console.error('Failed to establish realtime subscription:', error);
+    }
 });
src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte (1)

20-24: Optional: narrow the subscription channel to reduce noise

Subscribing to 'console' may deliver many unrelated events. If supported by your SDK wrapper, prefer a targeted channel like 'functions.*.executions.*' to minimize churn before the includes filter.

Example:

- subscription = await sdk.forConsole.realtime.subscribe('console', (response) => {
+ subscription = await sdk.forConsole.realtime.subscribe('functions.*.executions.*', (response) => {
src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (1)

174-175: Optional: remove unnecessary async on resetPlatformStore.

resetPlatformStore is declared async but only calls createPlatform.reset(). Consider dropping async to avoid implying awaited work.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30e23c9 and 2f62c77.

📒 Files selected for processing (14)
  • src/lib/components/csvImportBox.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
PR: appwrite/console#2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/lib/components/csvImportBox.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e
  • GitHub Check: build
🔇 Additional comments (14)
src/lib/components/csvImportBox.svelte (1)

5-5: LGTM! Type import added correctly.

The type import for AppwriteRealtimeSubscription follows TypeScript best practices and aligns with the PR's refactoring pattern.

src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte (1)

220-220: LGTM: Store cleanup on component destroy.

The onDestroy hook properly resets the platform store when the component is destroyed, ensuring clean state management.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte (1)

3-3: LGTM!

The type import is properly declared and used for type annotation.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte (2)

15-15: PageProps import is correct; codebase uses runes

The Svelte ^5.25.3 and SvelteKit ^2.42.1 stack supports runes. The file itself uses PageProps with $props() on line 17, confirming the import on line 15 is appropriate.


7-7: Type definition and import are correct and properly aligned.

Verification confirms:

  • AppwriteRealtimeSubscription is correctly defined as Awaited<ReturnType<Realtime['subscribe']>> in src/lib/stores/sdk.ts
  • The type is properly imported and used in the page file at line 20
  • The subscribe() call is correctly annotated with the type alias
  • The type derives from the external Appwrite SDK (@appwrite.io/console), ensuring correct alignment

The review comment's reference to .close() usage cannot be verified as there are no .close() calls in the codebase. The type definition itself is sound.

src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte (1)

19-19: LGTM: imports and onDestroy usage

Importing onDestroy and resetting the platform store on teardown looks good.

Also applies to: 99-99

src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte (1)

20-20: LGTM: imports and teardown store reset

Also applies to: 108-108

src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte (1)

20-20: LGTM: lifecycle imports and onDestroy(resetPlatformStore)

Also applies to: 135-135

src/routes/(console)/project-[region]-[project]/sites/+page.svelte (1)

28-28: LGTM: type import for AppwriteRealtimeSubscription

src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (1)

20-20: Imports look good.

Adding onDestroy is appropriate given the separate store reset. No issues here.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte (1)

7-7: Type import addition is fine.

Explicit typing improves clarity.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.svelte (1)

16-16: Type import is good.

Keeps subscription handling explicit.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte (1)

4-4: Type import looks good.

No concerns.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte (1)

10-10: Type import addition LGTM.

@ItzNotABug ItzNotABug marked this pull request as draft October 27, 2025 11:14
@ItzNotABug ItzNotABug closed this Oct 27, 2025
@ItzNotABug ItzNotABug reopened this Oct 30, 2025
@ItzNotABug ItzNotABug marked this pull request as ready for review October 31, 2025 06:29
@ItzNotABug ItzNotABug marked this pull request as draft October 31, 2025 07:40
@ItzNotABug ItzNotABug marked this pull request as ready for review October 31, 2025 09:07
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;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

randomly gave an error during tests, figured I'd just add a ? for now.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte (1)

14-40: Critical: Unsafe payload access before event-type check.

Lines 17-22 cast and access payload.status before verifying the event is deployment-related (lines 24-38). Non-deployment console events can have incompatible payload structures, causing runtime errors.

Apply this diff to check event type first:

 onMount(() => {
     let previousStatus: string = null;
     return realtime.forConsole(page.params.region, 'console', (message) => {
-        const payload = message.payload as Models.Deployment;
-        if (payload.status !== 'ready' && previousStatus === payload.status) {
-            return;
-        }
-
-        previousStatus = payload.status;
-
         if (message.events.includes('sites.*.deployments.*.create')) {
             invalidate(Dependencies.DEPLOYMENTS);
-
             return;
         }
         if (message.events.includes('sites.*.deployments.*.update')) {
+            const payload = message.payload as Models.Deployment;
+            if (payload.status !== 'ready' && previousStatus === payload.status) {
+                return;
+            }
+            previousStatus = payload.status;
             invalidate(Dependencies.DEPLOYMENTS);
             invalidate(Dependencies.SITE);
             return;
         }
         if (message.events.includes('sites.*.deployments.*.delete')) {
             invalidate(Dependencies.DEPLOYMENTS);
-
             return;
         }
     });
 });

Note: Only .update events need status checking; .create and .delete don't require deduplication.

♻️ Duplicate comments (1)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte (1)

18-18: Destructuring $props() breaks reactivity—props won't update on invalidate().

Destructuring from $props() performs a one-time copy, so data won't react to prop changes when invalidate(Dependencies.EXECUTIONS) is called.

Apply this diff to preserve reactivity:

-let { data }: PageProps = $props();
+const props: PageProps = $props();

Then update all references from data.* to props.data.* throughout the template (lines 31, 35, 36, 47, 48, 52-55, 67, 72, 73).

🧹 Nitpick comments (1)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.svelte (1)

34-40: Consider adding error handling for subscription setup.

While the current implementation may be acceptable depending on your app's error handling strategy, wrapping the subscription in a try-catch could prevent component crashes if the realtime connection fails.

Example with error handling:

 onMount(() => {
-    return realtime.forConsole(page.params.region, 'console', (response) => {
-        if (response.events.includes('sites.*.deployments.*')) {
-            invalidate(Dependencies.DEPLOYMENTS);
-        }
-    });
+    try {
+        return realtime.forConsole(page.params.region, 'console', (response) => {
+            if (response.events.includes('sites.*.deployments.*')) {
+                invalidate(Dependencies.DEPLOYMENTS);
+            }
+        });
+    } catch (error) {
+        console.error('Failed to setup realtime subscription:', error);
+        return () => {}; // Return no-op cleanup function
+    }
 });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 407163c and 24ce79c.

📒 Files selected for processing (16)
  • src/lib/components/backupRestoreBox.svelte (1 hunks)
  • src/lib/components/csvImportBox.svelte (2 hunks)
  • src/lib/stores/sdk.ts (2 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/+page.svelte
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte
  • src/lib/components/csvImportBox.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte
  • src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte
  • src/routes/(console)/project-[region]-[project]/sites/+page.svelte
📚 Learning: 2025-10-05T09:41:40.439Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2398
File: src/routes/(console)/verify-email/+page.svelte:48-51
Timestamp: 2025-10-05T09:41:40.439Z
Learning: In SvelteKit 5, `page` imported from `$app/state` is a reactive state object (using runes), not a store. It should be accessed as `page.data` without the `$` prefix, unlike the store-based `$page` from `$app/stores` in earlier versions.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte
  • src/lib/components/csvImportBox.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+layout.svelte
  • src/routes/(console)/project-[region]-[project]/sites/+page.svelte
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte
  • src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte
📚 Learning: 2025-09-25T04:21:57.071Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:536-552
Timestamp: 2025-09-25T04:21:57.071Z
Learning: In the Appwrite console database suggestions flow, after successfully creating columns via `createColumns()`, the `await invalidate(Dependencies.TABLE)` call causes the view to be destroyed and another view (populated table view) to be rendered, automatically cleaning up component state without needing manual reset.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte
📚 Learning: 2025-10-13T05:16:07.656Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/header.svelte:54-58
Timestamp: 2025-10-13T05:16:07.656Z
Learning: In SvelteKit apps, shared layout components (like headers) that use `$derived(page.data.*)` should use optional chaining when accessing properties that may not be present on all routes. During page transitions, reactive statements can briefly evaluate with different page.data structures, so optional chaining prevents runtime errors when navigating between routes with different data shapes (e.g., between `/databases` and `/databases/database-[database]`).

Applied to files:

  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/+page.svelte
🧬 Code graph analysis (1)
src/lib/stores/sdk.ts (1)
src/lib/system.ts (1)
  • isDev (28-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (15)
src/lib/components/backupRestoreBox.svelte (1)

128-128: Verify the logic when organization data is undefined.

The optional chaining prevents the crash, but it changes the behavior when $organization is undefined. Currently:

  • If $organization is undefined, then $organization?.billingPlan evaluates to undefined
  • undefined === BillingPlan.FREE evaluates to false
  • The condition becomes isSelfHosted || false, so the subscription will be set up

Is this intended? If the organization data hasn't loaded yet, should the subscription be established optimistically, or should we wait until we can confirm the billing plan?

Consider one of these alternatives if the current behavior is problematic:

Option 1: Skip subscription when organization is undefined

-if (isSelfHosted || (isCloud && $organization?.billingPlan === BillingPlan.FREE)) return;
+if (isSelfHosted || !$organization || (isCloud && $organization.billingPlan === BillingPlan.FREE)) return;

Option 2: Only set up subscription when explicitly allowed

-if (isSelfHosted || (isCloud && $organization?.billingPlan === BillingPlan.FREE)) return;
+if (isSelfHosted || (isCloud && (!$organization || $organization.billingPlan === BillingPlan.FREE))) return;

Otherwise, if organization data is guaranteed to be available at mount time or optimistic subscription is acceptable, the current implementation is fine.

src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte (1)

83-97: LGTM! Realtime subscription correctly refactored.

The synchronous onMount pattern now properly registers the cleanup function. The new realtime.forConsole API elegantly handles the subscription lifecycle, and calling subscription() on both successful ping and unmount ensures proper cleanup.

src/lib/stores/sdk.ts (1)

152-177: LGTM! Clean subscription lifecycle management.

The realtime.forConsole implementation properly handles the async subscription lifecycle by returning a synchronous cleanup closure that chains the promise. The closed flag prevents double-closing, and error handling in dev mode aids debugging.

src/lib/components/csvImportBox.svelte (1)

190-195: LGTM! Clean direct return of cleanup function.

The refactored subscription correctly returns the cleanup function from realtime.forConsole directly. This is the cleanest pattern for this use case.

src/routes/(console)/project-[region]-[project]/sites/+page.svelte (1)

52-58: LGTM! Proper subscription cleanup.

The refactored realtime subscription correctly uses the synchronous onMount pattern and directly returns the cleanup function from realtime.forConsole.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/deployment-[deployment]/+page.svelte (1)

33-43: LGTM! Correct subscription lifecycle.

The refactored subscription properly uses the synchronous onMount pattern and returns the cleanup function from realtime.forConsole. The async callback with awaited invalidate is fine—realtime handlers support async callbacks.

src/routes/(console)/project-[region]-[project]/overview/platforms/createReactNative.svelte (1)

119-133: LGTM: Subscription lifecycle correctly implemented.

The new realtime.forConsole API is used correctly. The subscription function is invoked to close the stream both when the ping event is received and during component cleanup.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+page.svelte (1)

20-26: LGTM: Subscription correctly implemented.

The realtime.forConsole pattern is used correctly—returning the subscription function directly from onMount ensures proper cleanup.

src/routes/(console)/project-[region]-[project]/overview/platforms/createApple.svelte (1)

92-106: LGTM: Subscription lifecycle correctly implemented.

The new realtime.forConsole API is used correctly, with proper cleanup.

src/routes/(console)/project-[region]-[project]/overview/platforms/createFlutter.svelte (1)

158-172: LGTM: Subscription lifecycle correctly implemented.

The new realtime.forConsole API is used correctly, with proper cleanup.

src/routes/(console)/project-[region]-[project]/sites/create-site/deploying/+page.svelte (1)

20-40: LGTM: Async callback and subscription lifecycle correctly implemented.

The async callback is appropriate here since it needs to await goto(). The subscription function is returned directly from onMount for proper cleanup.

src/routes/(console)/project-[region]-[project]/overview/platforms/createWeb.svelte (1)

204-218: LGTM: Subscription lifecycle correctly implemented.

The new realtime.forConsole API is used correctly, with proper cleanup.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/logs/+page.svelte (1)

16-22: LGTM: Subscription lifecycle correctly implemented.

The new realtime.forConsole API is used correctly—returning the subscription function directly from onMount ensures proper cleanup.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/deployments/+page.svelte (2)

16-16: LGTM: Import updated for new realtime API.

The addition of the realtime import is necessary for the updated subscription pattern used in the onMount function.


34-40: Cleanup pattern verified and correct.

The realtime.forConsole method at src/lib/stores/sdk.ts:152-157 has the return type : () => void, confirming it returns a cleanup function synchronously. The onMount implementation correctly returns this cleanup function for proper teardown when the component unmounts. The pattern is sound.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/lib/stores/sdk.ts (1)

143-157: Consider caching the Realtime instance.

Creating a new Realtime instance on every call to forProject could impact performance if this method is invoked frequently. Consider caching the instance and reusing it when the endpoint hasn't changed.

Example approach:

+let cachedRealtime: Realtime | null = null;
+let cachedEndpoint: string | null = null;
+
 forProject(
     region: string,
     channels: string | string[],
     callback: AppwriteRealtimeResponseEvent
 ) {
     const endpoint = getApiEndpoint(region);
     if (endpoint !== clientRealtime.config.endpoint) {
         clientRealtime.setEndpoint(endpoint);
+        cachedRealtime = null;
     }

-    // because uses a different client!
-    const realtime = new Realtime(clientRealtime);
+    if (!cachedRealtime || cachedEndpoint !== endpoint) {
+        cachedRealtime = new Realtime(clientRealtime);
+        cachedEndpoint = endpoint;
+    }

-    return createRealtimeSubscription(realtime, channels, callback);
+    return createRealtimeSubscription(cachedRealtime, channels, callback);
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24ce79c and 601eb81.

📒 Files selected for processing (9)
  • src/lib/components/backupRestoreBox.svelte (1 hunks)
  • src/lib/components/migrationBox.svelte (1 hunks)
  • src/lib/stores/sdk.ts (4 hunks)
  • src/routes/(console)/project-[region]-[project]/+layout.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/+layout.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+layout.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/components/backupRestoreBox.svelte
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+layout.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
📚 Learning: 2025-09-25T04:21:57.071Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:536-552
Timestamp: 2025-09-25T04:21:57.071Z
Learning: In the Appwrite console database suggestions flow, after successfully creating columns via `createColumns()`, the `await invalidate(Dependencies.TABLE)` call causes the view to be destroyed and another view (populated table view) to be rendered, automatically cleaning up component state without needing manual reset.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+layout.svelte
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
📚 Learning: 2025-09-30T07:41:06.679Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2425
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:454-468
Timestamp: 2025-09-30T07:41:06.679Z
Learning: In `src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte`, the column suggestions API (console.suggestColumns) has a maximum limit of 7 columns returned, which aligns with the initial placeholder count of 7 in customColumns.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
🧬 Code graph analysis (1)
src/lib/stores/sdk.ts (1)
src/lib/system.ts (1)
  • isDev (28-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (9)
src/routes/(console)/project-[region]-[project]/settings/migrations/+page.svelte (1)

41-45: Returning the unsubscribe fixes onMount cleanup

Good call letting onMount hand back the new realtime.forProject unsubscribe closure—this keeps the subscription scoped to the component lifecycle with the updated API.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/executions/+layout.svelte (1)

9-13: Realtime executions subscription now matches the new API

The streamlined forProject call cleanly ties the executions invalidation to the returned unsubscribe function—looks solid.

src/routes/(console)/project-[region]-[project]/databases/database-[database]/backups/+page.svelte (1)

164-171: Scoped invalidation keeps backups refresh precise

Thanks for deferring to the new forProject signature and retaining the channel guard—this keeps the BACKUPS cache invalidation tight to the active project.

src/routes/(console)/project-[region]-[project]/+layout.svelte (1)

30-36: Stats stream now cleans up via returned unsubscribe

The refactor to return the closure from realtime.forProject ensures the stats listener is registered and torn down correctly with the layout.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/+layout.svelte (1)

24-45: Deployment watcher aligns with the closure-based realtime API

Happy to see the deployment listener now rely on the callback-returned unsubscribe—keeps lifecycle management tidy while preserving the existing status guard logic.

src/lib/components/migrationBox.svelte (1)

53-60: Console channel subscription now lifecycles correctly

Returning the forProject cleanup here dovetails with the channel filter to keep migration updates scoped to the active project—looks good.

src/lib/stores/sdk.ts (3)

1-1: LGTM!

The isDev import is appropriately used for conditional error logging in the new subscription handler.


159-169: LGTM!

The region-aware logic correctly selects the appropriate realtime instance, and the subscription setup is properly delegated.


213-221: LGTM!

The new types provide a clear contract for realtime responses and callbacks. Using unknown for payload is appropriate given the varied nature of realtime events.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]/+page.svelte (2)

46-59: Good refactor to closure-based subscription; verify type safety of payload.

The new realtime.forProject API simplifies subscription management and cleanup. However, the type assertion at line 53 assumes the payload always matches Models.Deployment without runtime validation.

Consider verifying that the realtime response payload typing is enforced server-side, or add a runtime check to ensure the payload shape matches expectations before casting:

const payload = response.payload as Models.Deployment;
if (payload && typeof payload.status === 'string' && payload.status === 'ready') {
    invalidate(Dependencies.DEPLOYMENT);
}

Alternatively, if the realtime API guarantees type safety, this is acceptable as-is. You may also want to add error handling for subscription failures:

onMount(() => {
    try {
        return realtime.forProject(page.params.region, 'console', (response) => {
            // ... existing logic
        });
    } catch (error) {
        console.error('Failed to subscribe to deployment updates:', error);
    }
});

39-39: Consider migrating to $props() for consistency with broader refactor.

While export let data is still valid, the AI summary indicates that several pages in this PR are switching to typed PageProps via $props(). Consider whether this file should also adopt that pattern for consistency:

const { data }: PageProps = $props();

If the phased migration is intentional, feel free to ignore this suggestion.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 601eb81 and 8d38c0d.

📒 Files selected for processing (1)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]/+page.svelte (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-08T13:20:47.308Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2316
File: src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte:29-29
Timestamp: 2025-09-08T13:20:47.308Z
Learning: The Form.svelte component in the Appwrite console creates a FormContext with isSubmitting as writable(false) and expects consumers to work with Svelte writable stores, not plain booleans.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]/+page.svelte
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]/+page.svelte
📚 Learning: 2025-10-05T09:41:40.439Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2398
File: src/routes/(console)/verify-email/+page.svelte:48-51
Timestamp: 2025-10-05T09:41:40.439Z
Learning: In SvelteKit 5, `page` imported from `$app/state` is a reactive state object (using runes), not a store. It should be accessed as `page.data` without the `$` prefix, unlike the store-based `$page` from `$app/stores` in earlier versions.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]/+page.svelte
🔇 Additional comments (1)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/deployment-[deployment]/+page.svelte (1)

4-4: LGTM: Clean migration to the new realtime API.

The import change correctly reflects the new realtime subscription approach.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (1)

85-85: Type fix applied correctly.

The parentheses correctly wrap the function signature before the null union, as addressed in the previous review.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d38c0d and 2f27386.

📒 Files selected for processing (1)
  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (3 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-09-30T07:41:06.679Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2425
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:454-468
Timestamp: 2025-09-30T07:41:06.679Z
Learning: In `src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte`, the column suggestions API (console.suggestColumns) has a maximum limit of 7 columns returned, which aligns with the initial placeholder count of 7 in customColumns.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
📚 Learning: 2025-10-07T14:17:11.597Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts:28-28
Timestamp: 2025-10-07T14:17:11.597Z
Learning: In src/routes/(console)/project-[region]-[project]/databases/database-[database]/(entity)/helpers/terminology.ts, the empty `vectordb: {}` entry in baseTerminology is intentional. The vectordb database type is not currently used because the backend API is not finalized, and no database type returns 'vectordb' at the moment.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
📚 Learning: 2025-10-13T05:13:54.542Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2413
File: src/routes/(console)/project-[region]-[project]/databases/table.svelte:33-39
Timestamp: 2025-10-13T05:13:54.542Z
Learning: In Svelte 5, `import { page } from '$app/state'` provides a reactive state proxy that can be accessed directly (e.g., `page.params`), unlike the older `import { page } from '$app/stores'` which returns a readable store requiring the `$page` syntax for auto-subscription in components.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
📚 Learning: 2025-09-25T04:21:57.071Z
Learnt from: ItzNotABug
Repo: appwrite/console PR: 2373
File: src/routes/(console)/project-[region]-[project]/databases/database-[database]/(suggestions)/empty.svelte:536-552
Timestamp: 2025-09-25T04:21:57.071Z
Learning: In the Appwrite console database suggestions flow, after successfully creating columns via `createColumns()`, the `await invalidate(Dependencies.TABLE)` call causes the view to be destroyed and another view (populated table view) to be rendered, automatically cleaning up component state without needing manual reset.

Applied to files:

  • src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (2)
src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/+layout.svelte (2)

23-23: LGTM!

The type import improves type safety for realtime event handlers.


268-268: LGTM!

The parameter type annotation is consistent with the handler type definition and improves type safety.

@ItzNotABug ItzNotABug merged commit 60d0bdb into main Oct 31, 2025
4 checks passed
@ItzNotABug ItzNotABug deleted the fix-realtime-logic branch October 31, 2025 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants