Skip to content

Conversation

vermakhushboo
Copy link
Member

@vermakhushboo vermakhushboo commented Sep 12, 2025

What does this PR do?

a. Fix add-domain and verify domain flows

  1. Show correct states for domain verification flow - verification failed -> generating certificate -> certificate generation failed
  2. Add view logs, retry links nexts to badges
  3. Add view logs in functions + projects domains dropdown
  4. Only call listDomains for cloud
  5. Add updated column in each domains table

b. Update verification flows for sites/ functions/ projects tables

  1. Fix logic of verification
  2. Change badges to reflect rule status
Screenshot 2025-09-16 at 12 52 56 PM

c. Update verification flow for org > domains table

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

  • New Features
    • Added short relative-time formatting for the new "Updated" column; richer status UI for created / verifying / unverified states.
    • View logs modal, contextual View logs / Retry actions, and a tabbed retry workflow; CAA recommendation shown in DNS guidance when applicable.
  • Style / Layout
    • Increased Domain column minimum width for improved table layout.
  • Behavior
    • Streamlined verification flows with apex-domain handling and automatic post‑verification nameserver updates in cloud; some domain-creation errors are now silent.
  • Docs
    • DNS propagation note updated to "up to 48 hours to propagate fully."

Copy link

appwrite bot commented Sep 12, 2025

Console

Project ID: 688b7bf400350cbd60e9

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

Note

Cursor pagination performs better than offset pagination when loading further pages.

@vermakhushboo vermakhushboo marked this pull request as draft September 12, 2025 14:10
Copy link
Contributor

coderabbitai bot commented Sep 12, 2025

Walkthrough

Adds timeFromNowShort(datetime: string) in src/lib/helpers/date.ts. Adds barrel exports for domain components (src/lib/components/domains/index.ts) and re-exports them from src/lib/components/index.ts. Widens Domain column min-width and introduces a new updated column in multiple table stores. Multiple domain-related tables and modals now branch explicitly on rule.status (created / verifying / unverified), show status-specific short timestamps using timeFromNowShort and $updatedAt, wire ViewLogsModal and per-row "View logs" actions, and propagate a new ruleStatus prop to several domain components. Adds getSubdomain in src/lib/helpers/tlds.ts. Several load functions now accept params/url and fetch proxyRule; some domain creation flows now silently swallow creation errors.

Possibly related PRs

Suggested reviewers

  • Meldiron
  • HarshMN2345
  • ItzNotABug

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title "SER-287 Fix domain flows on console" is concise and accurately reflects the primary intent of the changeset — updating domain verification flows and related console UI (status badges, view logs/retry links, updated columns) across pages. It is specific, developer-readable, and aligns with the PR objectives and file-level changes.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-improve-domain-flows

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.

@vermakhushboo vermakhushboo changed the title Add new badges to site domains SER-287 Add new badges to site domains Sep 12, 2025
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]/domains/table.svelte (1)

41-41: Fix type: selectedProxyRule should allow null.

Prevents a TS error with the initial null assignment.

-let selectedProxyRule: Models.ProxyRule = $state(null);
+let selectedProxyRule: Models.ProxyRule | null = $state(null);
🧹 Nitpick comments (4)
src/lib/helpers/date.ts (1)

209-227: Make unit-shortening locale-agnostic and handle future times; dedupe validation.

Current string replaces miss “in x minutes/seconds/hours” and depend on English phrasing; also duplicates validation from timeFromNow. Replace with regex-based unit swaps and reuse timeFromNow.

-export function timeFromNowShort(datetime: string): string {
-    if (!datetime) {
-        return 'unknown time';
-    }
-    if (!isValidDate(datetime)) {
-        return 'invalid date';
-    }
-
-    const timeStr = dayjs().to(dayjs(datetime));
-    return timeStr
-        .replace(' seconds ago', ' secs ago')
-        .replace(' second ago', ' sec ago')
-        .replace(' minutes ago', ' mins ago')
-        .replace(' minute ago', ' min ago')
-        .replace(' hours ago', ' hrs ago')
-        .replace(' hour ago', ' hr ago')
-        .replace(' days ago', ' days ago')
-        .replace(' day ago', ' day ago');
-}
+export function timeFromNowShort(datetime: string): string {
+    const base = timeFromNow(datetime);
+    if (base === 'unknown time' || base === 'invalid date') return base;
+    return base
+        .replace(/\bseconds\b/g, 'secs')
+        .replace(/\bsecond\b/g, 'sec')
+        .replace(/\bminutes\b/g, 'mins')
+        .replace(/\bminute\b/g, 'min')
+        .replace(/\bhours\b/g, 'hrs')
+        .replace(/\bhour\b/g, 'hr');
+}

Note: if the app ever localizes dayjs relativeTime, these swaps should be disabled or made locale-aware.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (3)

93-108: Gate “View logs” by rule.logs to avoid empty modal.

Row UI always shows “View logs”, while the action menu hides it when logs are absent. Make them consistent.

-                                    <Link
-                                        size="s"
-                                        on:click={(e) => {
-                                            e.preventDefault();
-                                            selectedProxyRule = rule;
-                                            showLogs = true;
-                                        }}>
-                                        View logs
-                                    </Link>
+                                    {#if rule.logs}
+                                        <Link
+                                            size="s"
+                                            on:click={(e) => {
+                                                e.preventDefault();
+                                                selectedProxyRule = rule;
+                                                showLogs = true;
+                                            }}>
+                                            View logs
+                                        </Link>
+                                    {/if}

110-125: Apply the same logs gating for the unverified branch.

Mirror the condition used in the action menu.

-                                    <Link
-                                        size="s"
-                                        on:click={(e) => {
-                                            e.preventDefault();
-                                            selectedProxyRule = rule;
-                                            showLogs = true;
-                                        }}>
-                                        View logs
-                                    </Link>
+                                    {#if rule.logs}
+                                        <Link
+                                            size="s"
+                                            on:click={(e) => {
+                                                e.preventDefault();
+                                                selectedProxyRule = rule;
+                                                showLogs = true;
+                                            }}>
+                                            View logs
+                                        </Link>
+                                    {/if}

130-145: Avoid inline styles; use a class for the updated-time text.

Keeps styling consistent and easier to theme.

-                            <Typography.Text
-                                variant="m-400"
-                                color="--fgcolor-neutral-tertiary"
-                                style="font-size: 0.875rem;">
+                            <Typography.Text
+                                variant="m-400"
+                                color="--fgcolor-neutral-tertiary"
+                                class="updated-cell">

Add to the file’s <style>:

.updated-cell { font-size: 0.875rem; }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7af9402 and f044340.

📒 Files selected for processing (3)
  • src/lib/helpers/date.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (2 hunks)
⏰ 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 (3)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts (1)

20-25: Add a visible, accessible header: "Updated".

Blank headers harm accessibility and sorting; set the title and confirm whether this column should be sortable. Apply:

-        title: '',
+        title: 'Updated',

Also confirm whether this column should be sortable; if not, set the appropriate flag on Column to prevent confusing sort UI (depends on your Column type).

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (2)

28-28: LGTM: import of timeFromNowShort.


76-92: Confirm status mapping: created → “Verification failed”.

“created” typically reads as an initial state; showing “Verification failed” might be misleading. Verify backend status semantics before shipping the copy.

@vermakhushboo vermakhushboo marked this pull request as ready for review September 16, 2025 07:27
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

Caution

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

⚠️ Outside diff range comments (2)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (1)

33-35: Type mismatch: initializing string state with null.

let redirect: string = $state(null); (and branch) violates the declared type.

-let redirect: string = $state(null);
-let branch: string = $state(null);
+let redirect = $state('');       // or: let redirect: string | null = $state(null);
+let branch = $state('');         // or: let branch: string | null = $state(null);
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (1)

41-41: Type: allow null in reactive state.

$state(null) conflicts with Models.ProxyRule type. Use a union to avoid TS errors under strict mode.

-let selectedProxyRule: Models.ProxyRule = $state(null);
+let selectedProxyRule: Models.ProxyRule | null = $state(null);
🧹 Nitpick comments (17)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (2)

55-58: Use locale‑independent lowercasing for domains.

toLocaleLowerCase() can miscase in some locales (e.g., Turkish). Use toLowerCase() for DNS labels.

-                .proxy.createAPIRule({ domain: domainName.toLocaleLowerCase() });
+                .proxy.createAPIRule({ domain: domainName.toLowerCase() });

62-70: URL‑encode dynamic path/query parts in redirect.

Safer when domains include wildcards or unusual chars; also encode rule.$id.

-                let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`;
+                const encodedDomain = encodeURIComponent(domainName);
+                let redirect = `${routeBase}/add-domain/verify-${encodedDomain}?rule=${encodeURIComponent(rule.$id)}`;
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (2)

104-111: Encode redirect URL and avoid shadowing redirect state.

The local redirect string shadows the bound redirect field and the domain/rule aren’t encoded. Rename and encode.

-                let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`;
+                const encodedDomain = encodeURIComponent(domainName);
+                let verificationUrl = `${routeBase}/add-domain/verify-${encodedDomain}?rule=${encodeURIComponent(rule.$id)}`;
 
-                if (isCloud && domain?.$id) {
-                    redirect += `&domain=${domain.$id}`;
-                }
+                if (isCloud && domain?.$id) {
+                    verificationUrl += `&domain=${domain.$id}`;
+                }
 
-                await goto(redirect);
+                await goto(verificationUrl);

78-99: Normalize domain before rule creation.

For consistency and to avoid case‑sensitive mismatches, lower‑case the domain in all create calls.

-                        domain: domainName,
+                        domain: domainName.toLowerCase(),
@@
-                        domain: domainName,
+                        domain: domainName.toLowerCase(),
@@
-                        domain: domainName,
+                        domain: domainName.toLowerCase(),
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts (1)

20-25: Add an accessible header for the Updated column.

Empty titles can hurt a11y. Prefer a visible or visually‑hidden label.

-        title: '',
+        title: 'Updated',
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (3)

93-107: Gate “View logs” links on log availability (matches action menu logic).

Action menu checks proxyRule.logs, but inline links don’t. Avoid opening an empty modal.

-                            {:else if proxyRule.status === 'verifying'}
+                            {:else if proxyRule.status === 'verifying' && proxyRule.logs}
@@
-                            {:else if proxyRule.status === 'unverified'}
+                            {:else if proxyRule.status === 'unverified' && proxyRule.logs}

Also applies to: 109-124


83-91: A11y: interactive “Link” without href.

Provide href="#" (with preventDefault) or switch to a button‑styled component to maintain semantics.

-                                    <Link
+                                    <Link href="#"
                                         size="s"
                                         on:click={(e) => {
                                             e.preventDefault();
                                             selectedProxyRule = proxyRule;
                                             showRetry = true;
                                         }}>
@@
-                                    <Link
+                                    <Link href="#"
                                         size="s"
                                         on:click={(e) => {
                                             e.preventDefault();
                                             selectedProxyRule = proxyRule;
                                             showLogs = true;
                                         }}>
@@
-                                    <Link
+                                    <Link href="#"
                                         size="s"
                                         on:click={(e) => {
                                             e.preventDefault();
                                             selectedProxyRule = proxyRule;
                                             showLogs = true;
                                         }}>

Also applies to: 100-107, 116-124


27-29: Prefer importing DnsRecordsAction from the barrel for consistency.

Minor consistency tweak with ViewLogsModal import.

-import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte';
+import { DnsRecordsAction } from '$lib/components';
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (3)

85-91: Instrument “Retry” and “View logs” clicks for analytics.

Deletion is tracked; these new actions aren’t. Add tracking for observability.

Example:

 selectedProxyRule = rule;
 showRetry = true;
+trackEvent(Click.DomainRetryClick, { source: 'sites_domain_overview' });
 selectedProxyRule = rule;
 showLogs = true;
+trackEvent(Click.DomainViewLogsClick, { source: 'sites_domain_overview' });

Also applies to: 101-107, 117-124


153-165: Icon‑only button needs an accessible name.

Add aria-label (and optionally title) to the kebab menu trigger for screen readers.

-<Button
+<Button
   text
   icon
+  aria-label="More actions"
+  title="More actions"
   on:click={(e) => {

130-146: Guard rule.$updatedAt (handle nullish dates); 'updated' column confirmed

  • Confirmed: columns store includes { id: 'updated' } — src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts.
  • Action: avoid "Invalid date" by rendering only when rule.$updatedAt is present. Suggested tweak:
-{#if rule.status !== 'verified'}
+{#if rule.status !== 'verified' && rule.$updatedAt}
   ...
-  {#if rule.status === 'created'}
+  {#if rule.status === 'created'}
     Checked {timeFromNowShort(rule.$updatedAt)}

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte — apply change around the existing updated column render.

src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte (6)

48-55: Columns: width and updated column—OK; add sortability if desired.

If users sort by "updated", consider wiring sort metadata.


134-149: Updated column: add nullish guard.

Prevent rendering when domain.$updatedAt is falsy to avoid bad output.

-{#if domain.status !== 'verified'}
+{#if domain.status !== 'verified' && domain.$updatedAt}

169-178: Action menu logs gating: good; also add analytics.

Track "View logs" selections for parity with delete.

 selectedDomain = domain;
 showLogs = true;
 toggle(e);
+trackEvent(Click.DomainViewLogsClick, { source: 'settings_domain_overview' });

180-190: Retry action: add analytics.

 selectedDomain = domain;
 showRetry = true;
 toggle(e);
+trackEvent(Click.DomainRetryClick, { source: 'settings_domain_overview' });

231-235: CSS nit: align divider styles across pages.

Sites table also adds vertical padding; consider keeping styles consistent.

 .action-menu-divider {
-    margin-inline: -1rem;
+    margin-inline: -1rem;
+    padding-block-start: 0.25rem;
+    padding-block-end: 0.25rem;
 }

156-165: Add accessible name to kebab button.

Icon‑only button needs an aria-label (and title) for SR users.

-<Button
+<Button
   text
   icon
+  aria-label="More actions"
+  title="More actions"
   on:click={(e) => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f044340 and 8ddcc95.

📒 Files selected for processing (9)
  • src/lib/components/domains/index.ts (1 hunks)
  • src/lib/components/index.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte (8 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.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 (14)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (1)

64-70: Good guard on appending domain param only when present.

The added isCloud && domain?.$id check prevents bogus &domain= query strings. LGTM.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts (1)

10-11: Wider domain column looks right.

The increased min width improves readability for long hostnames.

src/lib/components/index.ts (1)

90-90: Barrel re‑export added.

Makes domain components available via $lib/components. Ensure no name collisions with existing exports.

src/lib/components/domains/index.ts (1)

1-5: Barrel for domain components looks good.

Straightforward re‑exports; helps consumers consolidate imports.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (3)

6-16: Imports: OK.

Added IconTerminal, Divider, ViewLogsModal, and timeFromNowShort are appropriate for the new UI.


75-125: Confirm backend→UI status mapping.

You’re rendering:

  • created → “Verification failed” + Retry
  • verifying → “Generating certificate” + View logs
  • unverified → “Certificate generation failed” + View logs

Please confirm these labels align with server semantics so we don’t show “failed” on initial create.


129-146: Updated column rendering looks solid.

Clear, concise relative times via timeFromNowShort. Good right‑alignment for visual scanning.

src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte (5)

6-11: LGTM on icon imports.


39-39: State for logs modal: OK.

No issues spotted.


27-27: timeFromNowShort import/use looks good. Returns 'unknown time' for falsy input and 'invalid date' when isValidDate(datetime) fails — no changes required.


24-24: Verified: ViewLogsModal is exported as a named export.

Found in src/lib/components/domains/index.ts:
export { default as ViewLogsModal } from './viewLogsModal.svelte';


226-229: Prop name & type confirmed — no change required.

src/lib/components/domains/viewLogsModal.svelte exports selectedProxyRule: Models.ProxyRule and uses selectedProxyRule.logs; passing selectedProxyRule={selectedDomain} is correct.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (2)

24-24: ViewLogsModal correctly re-exported.
Confirmed in src/lib/components/domains/index.ts: export { default as ViewLogsModal } from './viewLogsModal.svelte';


76-126: Align status copy, gate "View logs", and prefer Button for actions

File: src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte Lines: 76-126

  • 'created' currently renders "Verification failed" — if created means "not verified yet"/pending, change the copy:
- content="Verification failed"
+ content="Verification pending"
  • Gate inline "View logs" the same way the ActionMenu does (only show when rule.logs):
-    <Link
+    {#if rule.logs}
+      <Link
         size="s"
         on:click={(e) => {
           e.preventDefault();
           selectedProxyRule = rule;
           showLogs = true;
         }}>
-        View logs
-    </Link>
+        View logs
+      </Link>
+    {/if}
  • Actions look like buttons. If Link renders an anchor, prefer a Button (text) for a11y or add appropriate role/aria attributes:
-<Link size="s" on:click={...}>Retry</Link>
+<Button text size="s" on:click={...} aria-label="Retry verification">Retry</Button>

Comment on lines +82 to +133
{#if domain.status === 'created'}
<Layout.Stack direction="row" gap="xs" alignItems="center">
<Badge
variant="secondary"
type="error"
content="Verification failed"
size="xs" />
<Link
size="s"
on:click={(e) => {
e.preventDefault();
selectedDomain = domain;
showRetry = true;
}}>
Retry
</Link>
</Layout.Stack>
{:else if domain.status === 'verifying'}
<Layout.Stack direction="row" gap="xs" alignItems="center">
<Badge
variant="secondary"
content="Generating certificate"
size="xs" />
<Link
size="s"
on:click={(e) => {
e.preventDefault();
selectedDomain = domain;
showLogs = true;
}}>
View logs
</Link>
</Layout.Stack>
{:else if domain.status === 'unverified'}
<Layout.Stack direction="row" gap="xs" alignItems="center">
<Badge
variant="secondary"
type="error"
content="Certificate generation failed"
size="xs" />
<Link
size="s"
on:click={(e) => {
e.preventDefault();
selectedDomain = domain;
showLogs = true;
}}>
View logs
</Link>
</Layout.Stack>
{/if}
</Layout.Stack>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Status mapping, logs gating, and a11y: mirror fixes from sites table.

  • "Verification failed" for domain.status === 'created' is likely incorrect—please confirm and fix copy.
  • Gate inline "View logs" on domain.logs (or make modal handle empty state).
  • Prefer Button (text) for action triggers, or add appropriate aria attributes to Link if it renders as anchor without href.

Apply analogous diffs as suggested in the sites table for these blocks.

import RetryDomainModal from './retryDomainModal.svelte';
import { ViewLogsModal } from '$lib/components';
import { regionalProtocol } from '../../store';
import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte';
Copy link
Member

Choose a reason for hiding this comment

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

doesn't components/domains have a barrel file now? index.ts which is also exported via parent index.ts?

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: 11

Caution

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

⚠️ Outside diff range comments (2)
src/lib/components/domains/recordTable.svelte (1)

76-85: Replace hard‑coded CA vendor with Let's Encrypt (or neutral copy)

File: src/lib/components/domains/recordTable.svelte (lines 76–85) — replace the Alert copy so it references Let's Encrypt (letsencrypt.org) for Appwrite‑managed TLS, or use vendor‑neutral text ("the certificate authority used by Appwrite"). Keep the existing Link to the custom‑domains docs.

Search for other occurrences before committing:

rg -n -C2 -i 'certainly\.com|caa|letsencrypt|sectigo|digicert' src || true
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (1)

128-131: isSubmitting is not bound; submit button won’t reflect submission state.

Use two‑way binding like other pages to prevent double submits and align UX.

-    <Form onSubmit={verify} {isSubmitting}>
+    <Form onSubmit={verify} bind:isSubmitting>
🧹 Nitpick comments (38)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts (3)

10-13: Return a 400 using SvelteKit’s error helper instead of throwing a generic Error

Improves status codes and error handling paths.

Apply:

-    if (!ruleId) {
-        throw new Error('Rule ID is required');
-    }
+    if (!ruleId) {
+        throw error(400, 'Rule ID is required');
+    }

Add import (outside this hunk):

import { error } from '@sveltejs/kit';

6-6: Type the loader with PageLoad for stricter inference and safer data typing

Locks the return shape into route $types and catches regressions.

Apply:

-export const load = async ({ params, parent, depends, url }) => {
+export const load: PageLoad = async ({ params, parent, depends, url }) => {

Add import (outside this hunk):

import type { PageLoad } from './$types';

16-22: Optional: fetch in parallel to shave latency

domains.list and proxy.getRule are independent; run concurrently.

One way:

const proxyRulePromise = sdk.forProject(params.region, params.project).proxy.getRule({ ruleId });
const domainsListPromise: Promise<Models.DomainsList | undefined> = isCloud
  ? sdk.forConsole.domains.list({ queries: [Query.equal('teamId', organization.$id)] })
  : Promise.resolve(undefined);

const [proxyRule, domainsList] = await Promise.all([proxyRulePromise, domainsListPromise]);
src/lib/components/domains/cnameTable.svelte (3)

15-16: Narrow ruleStatus type and include explicit 'verified' branch.

Use a string‑literal union to prevent typos and handle the 'verified' state directly (today it depends on verified === true only).

Apply:

-export let verified: boolean | undefined = undefined;
-export let ruleStatus: string | undefined = undefined;
+type RuleStatus = 'created' | 'verifying' | 'verified' | 'unverified';
+export let verified: boolean | undefined = undefined;
+export let ruleStatus: RuleStatus | undefined = undefined;

27-39: Status-to-badge mapping likely inverted; add a pending state and treat 'unverified' as verification failure.

Current copy shows “Verification failed” for 'created'. Suggest:

  • 'verified' → “Verified”
  • 'verifying' → “Generating certificate”
  • 'unverified' → “Verification failed”
  • 'created' → “Awaiting verification” (or similar)

Apply:

-{#if ruleStatus === 'created'}
-    <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
-{:else if ruleStatus === 'verifying'}
-    <Badge variant="secondary" size="xs" content="Generating certificate" />
-{:else if ruleStatus === 'unverified'}
-    <Badge
-        variant="secondary"
-        type="error"
-        size="xs"
-        content="Certificate generation failed" />
-{:else if verified === true}
+{#if ruleStatus === 'verified' || verified === true}
     <Badge variant="secondary" type="success" size="xs" content="Verified" />
+{:else if ruleStatus === 'verifying'}
+    <Badge variant="secondary" size="xs" content="Generating certificate" />
+{:else if ruleStatus === 'unverified'}
+    <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
+{:else if ruleStatus === 'created'}
+    <Badge variant="secondary" size="xs" content="Awaiting verification" />
 {/if}

55-56: Show “@” for apex domains.

subdomain is empty for apex records; render “@” for clarity (as done in recordTable).

Apply:

-<Table.Cell {root}>{subdomain}</Table.Cell>
+<Table.Cell {root}>{subdomain || '@'}</Table.Cell>
src/lib/components/domains/nameserverTable.svelte (2)

7-8: Constrain ruleStatus to known values.

Prevents accidental strings and aligns with other components.

Apply:

-export let verified: boolean | undefined = undefined;
-export let ruleStatus: string | undefined = undefined;
+type RuleStatus = 'created' | 'verifying' | 'verified' | 'unverified';
+export let verified: boolean | undefined = undefined;
+export let ruleStatus: RuleStatus | undefined = undefined;

20-31: Align badge copy with lifecycle and include 'verified'.

Same mapping suggestion as cnameTable.

Apply:

-{#if ruleStatus === 'created'}
-    <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
-{:else if ruleStatus === 'verifying'}
-    <Badge variant="secondary" size="xs" content="Generating certificate" />
-{:else if ruleStatus === 'unverified'}
-    <Badge
-        variant="secondary"
-        type="error"
-        size="xs"
-        content="Certificate generation failed" />
-{:else if verified === true}
+{#if ruleStatus === 'verified' || verified === true}
     <Badge variant="secondary" type="success" size="xs" content="Verified" />
+{:else if ruleStatus === 'verifying'}
+    <Badge variant="secondary" size="xs" content="Generating certificate" />
+{:else if ruleStatus === 'unverified'}
+    <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
+{:else if ruleStatus === 'created'}
+    <Badge variant="secondary" size="xs" content="Awaiting verification" />
 {/if}
src/lib/components/domains/recordTable.svelte (2)

14-18: Type safety for ruleStatus.

Use a union and keep variant consistent.

Apply:

-export let verified: boolean | undefined = undefined;
+export let verified: boolean | undefined = undefined;
 export let variant: 'cname' | 'a' | 'aaaa';
 export let service: 'sites' | 'general' = 'general';
-export let ruleStatus: string | undefined = undefined;
+type RuleStatus = 'created' | 'verifying' | 'verified' | 'unverified';
+export let ruleStatus: RuleStatus | undefined = undefined;

41-53: Fix status mapping and include 'verified'.

Mirror the same lifecycle mapping used across components.

Apply:

-{#if ruleStatus === 'created'}
-    <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
-{:else if ruleStatus === 'verifying'}
-    <Badge variant="secondary" size="xs" content="Generating certificate" />
-{:else if ruleStatus === 'unverified'}
-    <Badge
-        variant="secondary"
-        type="error"
-        size="xs"
-        content="Certificate generation failed" />
-{:else if verified === true}
+{#if ruleStatus === 'verified' || verified === true}
     <Badge variant="secondary" type="success" size="xs" content="Verified" />
+{:else if ruleStatus === 'verifying'}
+    <Badge variant="secondary" size="xs" content="Generating certificate" />
+{:else if ruleStatus === 'unverified'}
+    <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
+{:else if ruleStatus === 'created'}
+    <Badge variant="secondary" size="xs" content="Awaiting verification" />
 {/if}
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (1)

45-45: Prefer toLowerCase() for domain normalization.

toLocaleLowerCase() can be locale‑sensitive; domains should be ASCII‑lowercased.

Apply:

-                .proxy.createAPIRule({ domain: domainName.toLocaleLowerCase() });
+                .proxy.createAPIRule({ domain: domainName.toLowerCase() });
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte (2)

30-41: Avoid resetting the user’s selected tab on reactive changes.

The $effect will overwrite manual tab picks if dependencies change. Consider setting default only on open.

Apply:

-$effect(() => {
-    if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) {
+ $effect(() => {
+    if (!show) return; // only when opening
+    if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) {
         selectedTab = 'cname';
     } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
         selectedTab = 'a';
     } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
         selectedTab = 'aaaa';
     } else {
         selectedTab = 'nameserver';
     }
 });

113-125: Consistent “verified” rendering across components.

Once components accept 'verified' in ruleStatus, we can rely on selectedProxyRule.status and drop the separate verified prop.

After updating the components, simplify to:

<NameserverTable domain={selectedProxyRule.domain} ruleStatus={selectedProxyRule.status} />
<!-- and -->
<RecordTable service="general" variant={selectedTab} domain={selectedProxyRule.domain} ruleStatus={selectedProxyRule.status} />
src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte (3)

47-54: Success toast can be misleading when status !== 'verified'.

Toast always says “has been verified” even if the rule remains verifying/failed.

-            show = false;
-            verified = domain.status === 'verified';
+            show = false;
+            verified = domain.status === 'verified';
             await invalidate(Dependencies.DOMAINS);
 
             addNotification({
                 type: 'success',
-                message: `${selectedDomain.domain} has been verified`
+                message:
+                    domain.status === 'verified'
+                        ? `${selectedDomain.domain} verified`
+                        : `Verification retried for ${selectedDomain.domain}. We’ll keep checking.`
             });

61-64: Type‑narrow the caught error.

e is unknown in TS; accessing e.message can error.

-        } catch (e) {
-            error =
-                e.message ??
-                'Domain verification failed. Please check your domain settings or try again later';
-            trackError(e, Submit.DomainUpdateVerification);
+        } catch (e) {
+            const message =
+                e instanceof Error && e.message
+                    ? e.message
+                    : 'Domain verification failed. Please check your domain settings or try again later';
+            error = message;
+            trackError(e, Submit.DomainUpdateVerification);
         }

76-112: De‑duplicate tab logic by deriving an allowed‑tabs list.

Keeps selection/render rules in one place and avoids future drift.

Example:

const availableTabs = $derived(() => {
  const tabs: Array<'cname'|'nameserver'|'a'|'aaaa'> = [];
  const hasCname = isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost';
  const hasA = !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A && $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
  const hasAaaa = !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
  if (hasCname) tabs.push('cname');
  if (isCloud) tabs.push('nameserver'); else tabs.push('nameserver'); // always include
  if (hasA) tabs.push('a');
  if (hasAaaa) tabs.push('aaaa');
  return tabs;
});
$effect(() => { selectedTab = availableTabs[0] ?? 'nameserver'; });
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts (3)

10-13: Use SvelteKit’s error helper for bad input.

Return a 400 instead of throwing a generic Error.

+import { error } from '@sveltejs/kit';
...
-    if (!ruleId) {
-        throw new Error('Rule ID is required');
-    }
+    if (!ruleId) {
+        error(400, 'Rule ID is required');
+    }

15-21: domainsList may be undefined on self‑hosted.

Type and initialize accordingly to avoid implicit undefined.

-let domainsList: Models.DomainsList;
+let domainsList: Models.DomainsList | undefined;

17-19: Optional: region‑aware console SDK.

If console endpoints are region‑scoped, prefer sdk.forConsoleIn(params.region).

src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts (3)

10-13: Use SvelteKit’s error helper for bad input.

Return a 400 instead of throwing.

+import { error } from '@sveltejs/kit';
...
-    if (!ruleId) {
-        throw new Error('Rule ID is required');
-    }
+    if (!ruleId) {
+        error(400, 'Rule ID is required');
+    }

15-21: domainsList can be undefined outside cloud.

Adjust type to avoid uninitialized variable.

-let domainsList: Models.DomainsList;
+let domainsList: Models.DomainsList | undefined;

17-19: Optional: region‑aware console SDK.

Prefer sdk.forConsoleIn(params.region) if applicable.

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

99-101: Optional: perform nameserver update before navigation.

Running it pre-goto reduces the chance of cancellation on route change.


103-107: Type‑narrow error in notification.

error is unknown; guard before accessing .message.

-        } catch (error) {
-            addNotification({
-                type: 'error',
-                message: error.message
-            });
+        } catch (error) {
+            addNotification({
+                type: 'error',
+                message: error instanceof Error ? error.message : 'Failed to add domain'
+            });
         }
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (2)

42-44: TS nullability mismatch for redirect and branch.

Declared as string but initialized with null. Make the types explicit to satisfy strict TS and avoid runtime surprises in bound inputs.

-    let redirect: string = $state(null);
-    let branch: string = $state(null);
+    let redirect = $state<string | null>(null);
+    let branch = $state<string | null>(null);

58-71: Follow-up: domain ID discovery for retries (optional).

If create returns domain_already_exists, consider resolving the existing domain ID (e.g., list + filter) so the later nameserver update can still run. This will improve success rate after “verified” short-circuit.

Do you want me to wire a fallback lookup via sdk.forConsole.domains.list({ search: apexDomain, teamId: $project.teamId }) when create says “already exists”?

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (3)

69-69: Empty catch blocks hide actionable failures and break CI.

Replace silent catches with targeted handling for domain_already_exists and user-facing notifications for unexpected errors.

-                    } catch (error) {}
+                    } catch (error: any) {
+                        if (error?.type !== 'domain_already_exists') {
+                            addNotification({ type: 'warning', message: error?.message ?? 'Failed to create apex domain' });
+                        }
+                    }
...
-                    } catch (error) {}
+                    } catch (error: any) {
+                        addNotification({ type: 'warning', message: error?.message ?? 'Failed to update nameservers' });
+                    }

Also applies to: 86-86


72-75: Possible undefined data.domainsList.

data.domainsList may be absent outside cloud or on load failures. Use optional chaining to avoid crashes.

-                        const domain = data.domainsList.domains.find(
+                        const domain = data.domainsList?.domains?.find(
                             (d: Models.Domain) => d.domain === apexDomain
                         );

90-95: Guard missing ruleId.

ruleId can be null if the page is hit directly. Add a guard to prevent a 400 and guide the user.

-            const ruleData = await sdk
+            if (!ruleId) {
+                throw new Error('Missing rule ID. Please restart domain verification.');
+            }
+            const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (5)

50-51: Align isSubmitting store shape with other pages.

Use the same $state(writable(false)) pattern for consistency with bindings.

-    const isSubmitting = writable(false);
+    let isSubmitting = $state(writable(false));

56-56: Remove stray console.log.

Leftover debug log will leak to users’ consoles.

-                console.log('apexDomain', apexDomain);
+                // no-op

69-69: Empty catch blocks.

Same issue as other verify pages; replace with minimal handling to satisfy CI and improve debuggability.

-                    } catch (error) {}
+                    } catch (error: any) {
+                        if (error?.type !== 'domain_already_exists') {
+                            addNotification({ type: 'warning', message: error?.message ?? 'Failed to create apex domain' });
+                        }
+                    }
...
-                    } catch (error) {}
+                    } catch (error: any) {
+                        addNotification({ type: 'warning', message: error?.message ?? 'Failed to update nameservers' });
+                    }

Also applies to: 86-86


72-75: Optional chaining on domains list.

Prevent crashes if domainsList is missing.

-                        const domain = data.domainsList.domains.find(
+                        const domain = data.domainsList?.domains?.find(
                             (d: Models.Domain) => d.domain === apexDomain
                         );

90-98: Guard ruleId before verification.

Avoid calling the API with null and show a clear error.

-            const ruleData = await sdk
+            if (!ruleId) {
+                throw new Error('Missing rule ID. Please restart domain verification.');
+            }
+            const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (4)

46-47: Inconsistent verified typing.

Other pages use boolean. Keep consistent unless components truly need tri‑state.

-    let verified: boolean | undefined = $state(undefined);
+    let verified = $state(false);

67-67: Empty catch blocks.

Mirror the handling used in other verify pages to avoid CI failure and improve UX.

-                    } catch (error) {}
+                    } catch (error: any) {
+                        if (error?.type !== 'domain_already_exists') {
+                            addNotification({ type: 'warning', message: error?.message ?? 'Failed to create apex domain' });
+                        }
+                    }
...
-                    } catch (error) {}
+                    } catch (error: any) {
+                        addNotification({ type: 'warning', message: error?.message ?? 'Failed to update nameservers' });
+                    }

Also applies to: 84-84


70-73: Optional chaining on domainsList.

Prevent runtime errors when the list is unavailable.

-                        const domain = data.domainsList.domains.find(
+                        const domain = data.domainsList?.domains?.find(
                             (d: Models.Domain) => d.domain === apexDomain
                         );

88-95: Guard missing ruleId.

Avoid API call with null and provide clear remediation.

-            const ruleData = await sdk
+            if (!ruleId) {
+                throw new Error('Missing rule ID. Please restart domain verification.');
+            }
+            const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddcc95 and bb6c951.

📒 Files selected for processing (15)
  • src/lib/components/domains/cnameTable.svelte (2 hunks)
  • src/lib/components/domains/nameserverTable.svelte (2 hunks)
  • src/lib/components/domains/recordTable.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (6 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts (2 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (6 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (6 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts (1 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts (3)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts (1)
  • load (6-29)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts (1)
  • load (6-29)
src/lib/stores/sdk.ts (1)
  • sdk (142-165)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts (4)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts (1)
  • load (6-29)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts (1)
  • load (6-29)
src/lib/system.ts (1)
  • isCloud (24-24)
src/lib/stores/sdk.ts (1)
  • sdk (142-165)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts (5)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts (1)
  • load (6-29)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts (1)
  • load (6-29)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/+page.ts (1)
  • load (10-50)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/store.ts (1)
  • func (7-7)
src/lib/stores/sdk.ts (1)
  • sdk (142-165)
🪛 GitHub Check: build
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte

[failure] 59-59:
Empty block statement


[failure] 96-96:
Empty block statement

src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte

[failure] 84-84:
Empty block statement


[failure] 67-67:
Empty block statement

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

[failure] 69-69:
Empty block statement


[failure] 106-106:
Empty block statement

src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte

[failure] 86-86:
Empty block statement


[failure] 69-69:
Empty block statement

src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte

[failure] 39-39:
Empty block statement


[failure] 52-52:
Empty block statement

🪛 GitHub Actions: Tests
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte

[error] 59-59: ESLint: Empty block statement (no-empty). Step: pnpm run lint

⏰ 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). (1)
  • GitHub Check: e2e
🔇 Additional comments (9)
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts (3)

22-22: LGTM: per‑project proxy rule fetch aligns with new ruleStatus plumbing


8-8: Dependencies.DOMAINS is correct for this project-level verify page — no change needed. Matches other project domain routes (src/routes/(console)/project-[region]-[project]/settings/domains/+page.ts and add-domain/+page.ts) and the verify Svelte invalidates the same key.


15-20: domainsList may be undefined when isCloud is false — make the type optional or initialize it

domainsList is declared but only assigned inside the if (isCloud) branch, so it can be unassigned (undefined) for self‑hosted runs; change the type or provide a default/guard before use.

File: src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts — lines 15–20 (also applies to 24–27)

Suggested change:

-let domainsList: Models.DomainsList;
+let domainsList: Models.DomainsList | undefined;

If callers expect a non‑null value, either initialize to an empty list/object or guard in the loader/UI before using domainsList.

src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (1)

54-56: Route uses domainName as typed; ensure consistent normalization.

If normalization is required (lowercase), apply the same when building the verify URL.

Do you want this to be verify-${domainName.toLowerCase()} to match the create call?

src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte (1)

114-125: Props handoff looks correct.

Passing domain, verified, and ruleStatus into NameserverTable/RecordTable aligns with the new domains UI.

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

114-124: LGTM on new prop wiring.

ruleStatus={selectedProxyRule.status} is consistent across both tables.

If not already covered by types, confirm both components export export let ruleStatus: string | undefined;.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts (1)

26-27: Return shape clarity.

Returning domainsList as possibly undefined is fine if consumers handle it; otherwise default to null for explicitness.

Search consumers of data.domainsList on this route to ensure undefined is handled.

src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts (1)

24-28: Return payload LGTM.

Naming function: func avoids reserved word collisions; inclusion of proxyRule aligns with the UI.

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

65-68: Team/Org ID source inconsistent — confirm equivalence

Search shows create calls use different ID sources: some use $project.teamId while verify/org flows use $organization.$id or page.params.organization. Confirm $project.teamId === $organization.$id in all console contexts or unify to a single source to avoid accidental cross-org writes.

  • Uses $project.teamId:

    • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (lines ~65–67)
    • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (lines ~55–57)
    • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (lines ~35–37)
  • Uses $organization.$id or page.params.organization:

    • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (teamId: $organization.$id)
    • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (teamId: $organization.$id)
    • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (teamId: $organization.$id)
    • src/routes/(console)/organization-[organization]/domains/add-domain/+page.svelte (teamId: page.params.organization)

If these IDs are not guaranteed equal, switch to a single canonical org-id source (or explicitly map project.teamId → organization id) before calling sdk.forConsole.domains.create.

Comment on lines 51 to 60
let domain: Models.Domain;
if (apexDomain && !domain && isCloud) {
if (isCloud && apexDomain) {
try {
domain = await sdk.forConsole.domains.create({
teamId: $project.teamId,
domain: apexDomain
});
} catch (error) {
// apex might already be added on organization level, skip.
const alreadyAdded = error?.type === 'domain_already_exists';
if (!alreadyAdded) {
addNotification({
type: 'error',
message: error.message
});
return;
}
}
} catch (error) {}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Empty catch triggers lint failure and hides real errors; also domain may remain uninitialized.

Replace the try/catch with a safe promise .catch and make domain nullable.

-        let domain: Models.Domain;
-
-        if (isCloud && apexDomain) {
-            try {
-                domain = await sdk.forConsole.domains.create({
-                    teamId: $project.teamId,
-                    domain: apexDomain
-                });
-            } catch (error) {}
-        }
+        let domain: Models.Domain | null = null;
+        if (isCloud && apexDomain) {
+            domain = await sdk.forConsole.domains
+                .create({ teamId: $project.teamId, domain: apexDomain })
+                .catch(() => null); // Domain may already exist; safe to ignore
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let domain: Models.Domain;
if (apexDomain && !domain && isCloud) {
if (isCloud && apexDomain) {
try {
domain = await sdk.forConsole.domains.create({
teamId: $project.teamId,
domain: apexDomain
});
} catch (error) {
// apex might already be added on organization level, skip.
const alreadyAdded = error?.type === 'domain_already_exists';
if (!alreadyAdded) {
addNotification({
type: 'error',
message: error.message
});
return;
}
}
} catch (error) {}
}
let domain: Models.Domain | null = null;
if (isCloud && apexDomain) {
domain = await sdk.forConsole.domains
.create({ teamId: $project.teamId, domain: apexDomain })
.catch(() => null); // Domain may already exist; safe to ignore
}
🧰 Tools
🪛 GitHub Check: build

[failure] 59-59:
Empty block statement

🪛 GitHub Actions: Tests

[error] 59-59: ESLint: Empty block statement (no-empty). Step: pnpm run lint

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte
around lines 51 to 60, the empty catch both silences errors and can leave
`domain` uninitialized; change `domain` to be nullable (e.g., Models.Domain |
null) and replace the try/catch with the promise form using `.catch(...)` so any
error is handled explicitly (log or surface it) and set `domain = null` on
failure; additionally, adjust any downstream code to handle the nullable
`domain` case safely.

return;
}
}
} catch (error) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

Fix pipeline: remove empty catch blocks.

These exact lines are failing ESLint (no-empty). The diffs above resolve both occurrences.

Run to confirm no empty catch blocks remain:

Also applies to: 96-96


🏁 Script executed:

#!/bin/bash
rg -nP "catch\s*\([^)]*\)\s*\{\s*\}" -S || true

Length of output: 1764


Fix pipeline: remove empty catch blocks.

ESLint no-empty failures found at:

  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte:39
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte:52
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte:69
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte:86
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte:69
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte:106
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte:69
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte:86
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte:59
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte:96
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte:67
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte:84

Replace empty catch bodies with proper handling (log, rethrow, or an explicit justified eslint-disable comment).

🧰 Tools
🪛 GitHub Check: build

[failure] 59-59:
Empty block statement

🪛 GitHub Actions: Tests

[error] 59-59: ESLint: Empty block statement (no-empty). Step: pnpm run lint

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte
around line 59, there is an empty catch block; replace it with proper error
handling by capturing the caught error (e.g., catch (error)) and either log it
(console.error/processLogger.error) and surface a user-friendly message/state
update, rethrow the error if it must propagate, or if suppression is intentional
add a single-line eslint-disable comment with a justification; ensure any added
logging includes the error object for debugging and preserve original control
flow.

Comment on lines 93 to 97
if (isCloud) {
try {
await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
} catch (error) {}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard updateNameservers and avoid empty catch.

Prevent null deref on domain and remove empty catch.

-                if (isCloud) {
-                    try {
-                        await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
-                    } catch (error) {}
-                }
+                if (isCloud && domain?.$id) {
+                    await sdk.forConsole.domains
+                        .updateNameservers({ domainId: domain.$id })
+                        .catch(() => {}); // Non-blocking best-effort
+                }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (isCloud) {
try {
await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
} catch (error) {}
}
if (isCloud && domain?.$id) {
await sdk.forConsole.domains
.updateNameservers({ domainId: domain.$id })
.catch(() => void 0); // Non-blocking best-effort
}
🧰 Tools
🪛 GitHub Check: build

[failure] 96-96:
Empty block statement

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte
around lines 93-97, avoid potential null dereference of domain and remove the
empty catch: ensure you only call updateNameservers when domain and domain.$id
are present and when the method exists (use a guard/optional chaining on
sdk.forConsole.domains.updateNameservers), and replace the empty catch with
proper error handling (e.g., log the error and/or surface a user-facing message
or rethrow) so failures are not silently ignored.

Comment on lines 46 to 58
try {
await sdk
const domain = await sdk
.forProject(page.params.region, page.params.project)
.proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id });
await invalidate(Dependencies.FUNCTION_DOMAINS);
show = false;
verified = domain.status === 'verified';
await invalidate(Dependencies.FUNCTION_DOMAINS);
addNotification({
type: 'success',
message: `${selectedProxyRule.domain} has been verified`
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Success toast always claims “verified” even when status isn’t verified.

Use the returned status to tailor the message.

Apply:

-    show = false;
-    verified = domain.status === 'verified';
-    await invalidate(Dependencies.FUNCTION_DOMAINS);
-
-    addNotification({
-        type: 'success',
-        message: `${selectedProxyRule.domain} has been verified`
-    });
+    show = false;
+    verified = domain.status === 'verified';
+    await invalidate(Dependencies.FUNCTION_DOMAINS);
+
+    addNotification({
+        type: 'success',
+        message:
+            domain.status === 'verified'
+                ? `${selectedProxyRule.domain} has been verified`
+                : `Verification retried for ${selectedProxyRule.domain} (status: ${domain.status})`
+    });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
await sdk
const domain = await sdk
.forProject(page.params.region, page.params.project)
.proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id });
await invalidate(Dependencies.FUNCTION_DOMAINS);
show = false;
verified = domain.status === 'verified';
await invalidate(Dependencies.FUNCTION_DOMAINS);
addNotification({
type: 'success',
message: `${selectedProxyRule.domain} has been verified`
});
try {
const domain = await sdk
.forProject(page.params.region, page.params.project)
.proxy.updateRuleVerification({ ruleId: selectedProxyRule.$id });
show = false;
verified = domain.status === 'verified';
await invalidate(Dependencies.FUNCTION_DOMAINS);
addNotification({
type: 'success',
message:
domain.status === 'verified'
? `${selectedProxyRule.domain} has been verified`
: `Verification retried for ${selectedProxyRule.domain} (status: ${domain.status})`
});
🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte
around lines 46–58, the success notification always says "verified" regardless
of the returned domain.status; update the toast to use the actual status
returned by the API. After awaiting sdk...updateRuleVerification and setting
verified = domain.status === 'verified', build the notification message from
domain.status (e.g., `${selectedProxyRule.domain} has been ${domain.status}`) or
conditionally choose wording for known statuses, then call addNotification with
that message so the toast reflects the real verification result.

return;
}
}
} catch (error) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix build failure: empty block statements.

Fill the catch blocks with logging/notifications as suggested above to resolve CI.

Also applies to: 52-52

🧰 Tools
🪛 GitHub Check: build

[failure] 39-39:
Empty block statement

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte
around lines 39 and 52, there are empty catch blocks causing build failures;
replace each empty catch with proper error handling: catch the error as unknown
(e.g., catch (error: unknown)), log it (console.error or processLogger) and
surface a user-facing notification or set an error state so the UI shows the
failure (use the existing toast/notification helper in the project or import
one), and optionally rethrow or return after handling; ensure imports for any
notification utilities are added.

Comment on lines 50 to 53
try {
await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
} catch (error) {}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid null dereference on domain.$id and surface errors.

domain can be null if creation failed/skipped. Also, the empty catch eats real issues.

Apply:

-                if (isCloud) {
-                    try {
-                        await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
-                    } catch (error) {}
-                }
+                if (isCloud && apexDomain && domain?.$id) {
+                    try {
+                        await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
+                    } catch (error) {
+                        console.warn('updateNameservers failed for', apexDomain, error);
+                        addNotification({
+                            type: 'warning',
+                            message: `Nameserver update skipped: ${apexDomain}`
+                        });
+                    }
+                }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
} catch (error) {}
}
if (isCloud && apexDomain && domain?.$id) {
try {
await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
} catch (error) {
console.warn('updateNameservers failed for', apexDomain, error);
addNotification({
type: 'warning',
message: `Nameserver update skipped: ${apexDomain}`
});
}
}
🧰 Tools
🪛 GitHub Check: build

[failure] 52-52:
Empty block statement

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte
around lines 50–53, avoid dereferencing domain.$id when domain may be null and
stop swallowing errors in the catch block: first guard that domain and
domain.$id exist (e.g., if (!domain?.$id) return or display an appropriate
error/validation message to the user) before calling
sdk.forConsole.domains.updateNameservers, and replace the empty catch with error
handling that surfaces the problem (log to console, show a user-facing
toast/alert, or rethrow) so real failures are visible to developers and users.

Comment on lines 30 to 40
$effect(() => {
if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) {
selectedTab = 'cname';
} else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
selectedTab = 'a';
} else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
selectedTab = 'aaaa';
} else {
selectedTab = 'nameserver';
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Initial tab selection can target a non-rendered tab (mismatch with UI conditions).

The $effect doesn’t mirror the render-time exclusions for localhost/loopback targets. It can auto-select a/aaaa/cname even when those tabs are hidden, leaving content out of sync with the visible tabs.

Apply this diff to align selection with render conditions:

 $effect(() => {
-    if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) {
-        selectedTab = 'cname';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
-        selectedTab = 'a';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
-        selectedTab = 'aaaa';
-    } else {
-        selectedTab = 'nameserver';
-    }
+    const hasCname =
+        isSubDomain &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost';
+    const hasA =
+        !isCloud &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
+    const hasAaaa =
+        !isCloud &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
+
+    if (hasCname) selectedTab = 'cname';
+    else if (hasA) selectedTab = 'a';
+    else if (hasAaaa) selectedTab = 'aaaa';
+    else selectedTab = 'nameserver';
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$effect(() => {
if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && isSubDomain) {
selectedTab = 'cname';
} else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
selectedTab = 'a';
} else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
selectedTab = 'aaaa';
} else {
selectedTab = 'nameserver';
}
});
$effect(() => {
const hasCname =
isSubDomain &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost';
const hasA =
!isCloud &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
const hasAaaa =
!isCloud &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
if (hasCname) selectedTab = 'cname';
else if (hasA) selectedTab = 'a';
else if (hasAaaa) selectedTab = 'aaaa';
else selectedTab = 'nameserver';
});

Comment on lines 63 to 70
if (isCloud && apexDomain && !isSiteDomain) {
try {
domain = await sdk.forConsole.domains.create({
teamId: $project.teamId,
domain: apexDomain
});
} catch (error) {
// apex might already be added on organization level, skip.
const alreadyAdded = error?.type === 'domain_already_exists';
if (!alreadyAdded) {
addNotification({
type: 'error',
message: error.message
});
return;
}
}
} catch (error) {}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Over-eager apex domain creation and swallowed errors.

  • Removing the !domain guard triggers a create attempt on every add (cloud + apex), causing noisy domain_already_exists errors.
  • The empty catch hides real failures and trips CI (“Empty block statement”).

Handle the known duplicate gracefully and report unexpected errors.

Apply this diff:

-        if (isCloud && apexDomain && !isSiteDomain) {
-            try {
-                domain = await sdk.forConsole.domains.create({
-                    teamId: $project.teamId,
-                    domain: apexDomain
-                });
-            } catch (error) {}
-        }
+        if (isCloud && apexDomain && !isSiteDomain) {
+            try {
+                domain = await sdk.forConsole.domains.create({
+                    teamId: $project.teamId,
+                    domain: apexDomain
+                });
+            } catch (error: any) {
+                // Ignore "already exists", surface anything else.
+                if (error?.type !== 'domain_already_exists') {
+                    addNotification({
+                        type: 'error',
+                        message: error?.message ?? 'Failed to create apex domain'
+                    });
+                    return;
+                }
+            }
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (isCloud && apexDomain && !isSiteDomain) {
try {
domain = await sdk.forConsole.domains.create({
teamId: $project.teamId,
domain: apexDomain
});
} catch (error) {
// apex might already be added on organization level, skip.
const alreadyAdded = error?.type === 'domain_already_exists';
if (!alreadyAdded) {
addNotification({
type: 'error',
message: error.message
});
return;
}
}
} catch (error) {}
}
if (isCloud && apexDomain && !isSiteDomain) {
try {
domain = await sdk.forConsole.domains.create({
teamId: $project.teamId,
domain: apexDomain
});
} catch (error: any) {
// Ignore "already exists", surface anything else.
if (error?.type !== 'domain_already_exists') {
addNotification({
type: 'error',
message: error?.message ?? 'Failed to create apex domain'
});
return;
}
}
}
🧰 Tools
🪛 GitHub Check: build

[failure] 69-69:
Empty block statement

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte
around lines 63–70, reintroduce the guard so we only attempt creating the apex
domain when no domain object exists (e.g., keep/check !domain) and avoid
creating on every add; wrap the create call in a try/catch that does not swallow
errors—detect the known duplicate case (error code/message like
"domain_already_exists") and ignore or handle it silently, but for any other
error log/report it to the UI or rethrow so CI/monitoring sees it (do not leave
an empty catch block).

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

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]/domains/retryDomainModal.svelte (1)

52-56: Success toast fires even when verification didn’t succeed.

You always notify success after updateRuleVerification, regardless of domain.status. Gate the toast on success; otherwise show an info/error.

-            show = false;
-            verified = domain.status === 'verified';
-            await invalidate(Dependencies.SITES_DOMAINS);
-
-            addNotification({
-                type: 'success',
-                message: `${selectedProxyRule.domain} has been verified`
-            });
+            show = false;
+            verified = domain.status === 'verified';
+            await invalidate(Dependencies.SITES_DOMAINS);
+            if (verified) {
+                addNotification({
+                    type: 'success',
+                    message: `${selectedProxyRule.domain} has been verified`
+                });
+            } else {
+                addNotification({
+                    type: 'info',
+                    message: `Verification retried. Current status: ${domain.status}`
+                });
+            }
♻️ Duplicate comments (3)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte (2)

40-41: Initialize verified from the selected rule.

Prevents incorrect “unverified” badges before retry completes.

-let verified = $state(false);
+let verified = $state(selectedProxyRule?.status === 'verified');

52-55: Toast claims “verified” even when status isn’t verified.

Use the returned status in the message.

 addNotification({
   type: 'success',
-  message: `${selectedProxyRule.domain} has been verified`
+  message:
+    domain.status === 'verified'
+      ? `${selectedProxyRule.domain} has been verified`
+      : `Verification retried for ${selectedProxyRule.domain} (status: ${domain.status})`
 });
src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte (1)

27-37: Initial tab can target a hidden tab. Mirror render conditions.

Prevents selecting CNAME/A/AAAA when they’re filtered (localhost/loopback) and avoiding Nameservers on self‑hosted.

 $effect(() => {
-    if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) {
-        selectedTab = 'cname';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
-        selectedTab = 'a';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
-        selectedTab = 'aaaa';
-    } else {
-        selectedTab = 'nameserver';
-    }
+    const hasCname =
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost';
+    const hasNameserver = isCloud;
+    const hasA =
+        !isCloud &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
+    const hasAaaa =
+        !isCloud &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
+
+    if (hasCname) selectedTab = 'cname';
+    else if (hasNameserver) selectedTab = 'nameserver';
+    else if (hasA) selectedTab = 'a';
+    else if (hasAaaa) selectedTab = 'aaaa';
+    else selectedTab = 'cname';
 });
🧹 Nitpick comments (23)
src/lib/components/domains/cnameTable.svelte (2)

27-39: Double‑check status→badge mapping ("created" => "Verification failed" looks off).

Confirm backend enum→UI copy. Today:

  • created → "Verification failed"
  • verifying → "Generating certificate"
  • unverified → "Certificate generation failed"

If "created" is initial/new, showing "failed" is misleading. Consider a small mapper + default branch to avoid incorrect badges for unknown states.

Apply a mapper inline:

-            {#if ruleStatus === 'created'}
-                <Badge variant="secondary" type="error" size="xs" content="Verification failed" />
-            {:else if ruleStatus === 'verifying'}
-                <Badge variant="secondary" size="xs" content="Generating certificate" />
-            {:else if ruleStatus === 'unverified'}
-                <Badge
-                    variant="secondary"
-                    type="error"
-                    size="xs"
-                    content="Certificate generation failed" />
+            {#if ruleStatus}
+                {#if ruleStatus === 'verifying'}
+                    <Badge variant="secondary" size="xs" content="Generating certificate" />
+                {:else if ruleStatus === 'unverified' || ruleStatus === 'failed'}
+                    <Badge variant="secondary" type="error" size="xs" content="Certificate generation failed" />
+                {:else if ruleStatus === 'created'}
+                    <Badge variant="secondary" size="xs" content="Verification pending" />
+                {/if}
             {:else if verified === true}
                 <Badge variant="secondary" type="success" size="xs" content="Verified" />
             {/if}

63-81: CAA row UX: clarify value format for common cases.

Nice addition. Minor polish: add a short hint that multiple CAA tags (issue, issuewild) may be needed, and that the provided value is a recommended baseline.

src/lib/components/domains/recordTable.svelte (4)

54-66: Same status→badge mapping concerns as cnameTable.

Align copy and handle unknown states via a mapper to avoid showing a "failed" badge for "created".

Apply the same diff pattern used in cnameTable here.


25-33: Make A/AAAA tab visibility reactive (or explicitly constant).

These are computed once. If regionalConsoleVariables can change (region switch), this won’t update. Either:

  • mark as intentional (constant per session), or
  • make them reactive ($:) so UI updates when the store changes.

108-130: Apex detection uses a naive subdomain check; use getApexDomain for correctness.

!subdomain assumes two‑label apex (fails for e.g., example.co.uk). Use TLD helper for apex detection and subdomain derivation.

Apply this diff locally for the condition:

-        {#if variant === 'cname' && !subdomain}
+        {#if variant === 'cname' && domain === getApexDomain(domain)}

And add at top:

+    import { getApexDomain } from '$lib/helpers/tlds';

Outside this hunk, update subdomain derivation to be TLD‑aware (example):

// replace current subdomain logic
const apex = getApexDomain(domain);
const subdomain = domain && apex && domain.endsWith(`.${apex}`)
  ? domain.slice(0, -(apex.length + 1))
  : '';

87-105: CAA row: same minor UX hint as cnameTable.

Consider a brief caption or help icon noting when to use issue vs issuewild and that multiple CAA records can coexist.

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (4)

35-45: Default tab gating inconsistent with tab visibility.

You gate the CNAME tab button on _APP_DOMAIN_TARGET_CNAME !== 'localhost', but the default‑selection effect doesn’t. Result: default selects a hidden tab. Align both.

Apply this diff:

-        if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) {
+        if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost') {
             selectedTab = 'cname';

Also applies to: 151-159


52-87: Apex‑domain pre‑verification: silent catches hide actionable failures.

Swallowing errors twice makes troubleshooting hard. At minimum, log or track them; ideally, surface a non‑blocking info notification.

Add lightweight logging:

-                    } catch (error) {}
+                    } catch (error) {
+                        console.warn('Apex domain create/verify skipped:', error);
+                    }
...
-                    } catch (error) {}
+                    } catch (error) {
+                        console.warn('Apex domain nameserver update skipped:', error);
+                    }

107-114: Type‑safe error handling in catch.

error is unknown in TS. Accessing error.message can break type‑checks. Normalize safely.

Apply this diff:

-        } catch (error) {
+        } catch (error: unknown) {
             verified = false;
             isSubmitting.set(false);
             addNotification({
                 type: 'error',
-                message: error.message
+                message: error instanceof Error ? error.message : String(error)
             });
         }

123-124: URL‑encode the domain query param.

Avoid issues with IDNs/punycode or special chars.

Apply this diff:

-        await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`);
+        await goto(`${routeBase}/add-domain?domain=${encodeURIComponent(data.proxyRule.domain)}`);
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (4)

35-44: Default tab gating inconsistent with tab visibility (same as Sites).

Add the !== 'localhost' guard to the default‑selection effect.

-        if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) {
+        if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost') {
             selectedTab = 'cname';

Also applies to: 149-157


52-86: Apex‑domain pre‑verification: avoid empty catches.

Mirror Sites page advice: at least log warnings so support can trace issues.

-                    } catch (error) {}
+                    } catch (error) {
+                        console.warn('Apex domain create/verify skipped:', error);
+                    }
...
-                    } catch (error) {}
+                    } catch (error) {
+                        console.warn('Apex domain nameserver update skipped:', error);
+                    }

105-112: Type‑safe error handling in catch.

Normalize unknown errors before reading .message.

-        } catch (error) {
+        } catch (error: unknown) {
             verified = false;
             isSubmitting.set(false);
             addNotification({
                 type: 'error',
-                message: error.message
+                message: error instanceof Error ? error.message : String(error)
             });
         }

121-122: URL‑encode the domain query param on back.

-        await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`);
+        await goto(`${routeBase}/add-domain?domain=${encodeURIComponent(data.proxyRule.domain)}`);
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte (1)

28-36: Default tab gating inconsistent with visibility (localhost case).

Align the effect with the tab button guard to avoid defaulting to a hidden CNAME tab.

-        if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) {
+        if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost') {
             selectedTab = 'cname';

Also applies to: 75-83

src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte (3)

27-37: Align default tab selection with what’s actually rendered.

Effect can select CNAME/A/AAAA even when hidden (localhost/loopback), or fall back to Nameservers on self‑hosted. Mirror render conditions.

 $effect(() => {
-    if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) {
-        selectedTab = 'cname';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
-        selectedTab = 'a';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
-        selectedTab = 'aaaa';
-    } else {
-        selectedTab = 'nameserver';
-    }
+    const hasCname =
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost';
+    const hasNameserver = isCloud;
+    const hasA =
+        !isCloud &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
+    const hasAaaa =
+        !isCloud &&
+        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
+
+    if (hasCname) selectedTab = 'cname';
+    else if (hasNameserver) selectedTab = 'nameserver';
+    else if (hasA) selectedTab = 'a';
+    else if (hasAaaa) selectedTab = 'aaaa';
+    else selectedTab = 'cname';
 });

58-61: Handle unknown error type safely.

Avoid assuming e.message.

-            error =
-                e.message ??
-                'Domain verification failed. Please check your domain settings or try again later';
+            const msg =
+                e instanceof Error
+                    ? e.message
+                    : (typeof e === 'string' ? e : null);
+            error =
+                msg ??
+                'Domain verification failed. Please check your domain settings or try again later';

52-55: Optional: notification type by status.

Success for verified; info otherwise.

-addNotification({
-    type: 'success',
-    message:
-        domain.status === 'verified'
-            ? `${selectedProxyRule.domain} has been verified`
-            : `Verification retried for ${selectedProxyRule.domain} (status: ${domain.status})`
-});
+addNotification({
+    type: domain.status === 'verified' ? 'success' : 'info',
+    message:
+        domain.status === 'verified'
+            ? `${selectedProxyRule.domain} has been verified`
+            : `Verification retried for ${selectedProxyRule.domain} (status: ${domain.status})`
+});
src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte (5)

18-23: Default bindable show to false for consistency.

Prevents an accidental undefined initial state.

-    let {
-        show = $bindable(),
+    let {
+        show = $bindable(false),
         selectedDomain

40-41: Initialize verified from the selected domain status.

Ensures correct badges before retry.

-let verified = $state(false);
+let verified = $state(selectedDomain?.status === 'verified');

52-55: Toast claims “verified” regardless of result.

Reflect actual domain.status.

 addNotification({
   type: 'success',
-  message: `${selectedDomain.domain} has been verified`
+  message:
+    domain.status === 'verified'
+      ? `${selectedDomain.domain} has been verified`
+      : `Verification retried for ${selectedDomain.domain} (status: ${domain.status})`
 });

58-61: Harden error handling for non-Error throws.

Avoids any/unknown pitfalls.

-            error =
-                e.message ??
-                'Domain verification failed. Please check your domain settings or try again later';
+            const msg =
+                e instanceof Error
+                    ? e.message
+                    : (typeof e === 'string' ? e : null);
+            error =
+                msg ??
+                'Domain verification failed. Please check your domain settings or try again later';

52-55: Optional: notification type by status.

Use success for verified; info otherwise.

-addNotification({
-    type: 'success',
-    message:
-        domain.status === 'verified'
-            ? `${selectedDomain.domain} has been verified`
-            : `Verification retried for ${selectedDomain.domain} (status: ${domain.status})`
-});
+addNotification({
+    type: domain.status === 'verified' ? 'success' : 'info',
+    message:
+        domain.status === 'verified'
+            ? `${selectedDomain.domain} has been verified`
+            : `Verification retried for ${selectedDomain.domain} (status: ${domain.status})`
+});
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ee96d1 and 15e56c3.

📒 Files selected for processing (9)
  • src/lib/components/domains/cnameTable.svelte (3 hunks)
  • src/lib/components/domains/recordTable.svelte (3 hunks)
  • src/routes/(console)/organization-[organization]/domains/domain-[domain]/+page.svelte (1 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte (3 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/routes/(console)/organization-[organization]/domains/domain-[domain]/+page.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.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 (1)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte (1)

111-115: Props passthrough LGTM.

Passing ruleStatus to child tables is consistent with the new badge logic; navigation callbacks are wired correctly.

Please sanity‑check that NameserverTable uses ruleStatus the same way as the Record/CNAME tables do.

Also applies to: 120-124

@vermakhushboo vermakhushboo changed the title SER-287 Add new badges to site domains SER-287 Fix domain flows on console Sep 22, 2025
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 (7)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (1)

60-60: Type should reflect optional state (domain can be undefined).

domain is not guaranteed to be set; widen the type to avoid misleading types and follow-on runtime assumptions.

-let domain: Models.Domain;
+let domain: Models.Domain | undefined;
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (3)

55-55: Use console.debug instead of console.log for debug statements

Production code should use appropriate logging levels.

-console.log('apexDomain', apexDomain);
+console.debug('apexDomain', apexDomain);

62-67: Silent verification failures from apex domain creation are confusing

The apex domain creation sets verified = true based on nameservers, but then throws an error if not verified. This error is caught silently in lines 68-70, leaving users unaware of the actual verification state until line 97.

Consider removing the intermediate verification check since the final verification happens at line 97 anyway:

-verified = domainData.nameservers.toLowerCase() === 'appwrite';
-if (!verified) {
-    throw new Error(
-        'Domain verification failed. Please check your domain settings or try again later'
-    );
-}
+// Apex domain creation successful, verification will be checked later

68-70: Empty catch blocks without context lose important error details

Silently swallowing errors makes debugging difficult. Consider at least logging them at debug level.

-} catch (error) {
-    // Empty as domain creation error needs to be silent
-}
+} catch (error) {
+    console.debug('Apex domain creation skipped:', error.message);
+}

And similarly for the second catch block:

-} catch (error) {
-    // Empty as domain update error needs to be silent  
-}
+} catch (error) {
+    console.debug('Apex domain nameserver update skipped:', error.message);
+}

Also applies to: 87-89

src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (3)

62-67: Silent verification failures from apex domain creation are confusing

Same issue as in the settings domains file - the apex domain creation sets verified = true based on nameservers but throws an error that gets silently caught.

Consider removing the intermediate verification check:

-verified = domainData.nameservers.toLowerCase() === 'appwrite';
-if (!verified) {
-    throw new Error(
-        'Domain verification failed. Please check your domain settings or try again later'
-    );
-}
+// Apex domain creation successful, verification will be checked later

68-70: Empty catch blocks lose debugging context

Consider adding debug logging for troubleshooting:

-} catch (error) {
-    // Empty as domain creation error needs to be silent
-}
+} catch (error) {
+    console.debug('Apex domain creation skipped:', error.message);
+}

And for the second catch:

-} catch (error) {
-    // Empty as domain update error needs to be silent
-}
+} catch (error) {
+    console.debug('Apex domain nameserver update skipped:', error.message);
+}

Also applies to: 87-89


52-119: Extract apex-domain verification into a shared helper (src/lib/helpers/domains.ts)

Identical apex-domain extraction + create/update verification logic appears in multiple places — consolidate into a single helper (e.g., verifyApexDomain) and call it from each location:

  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte
  • (helper candidate) src/lib/helpers/domains.ts — add exported verification utility here and replace the in-file implementations.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 15e56c3 and 2b68cf9.

📒 Files selected for processing (6)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.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 (9)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (2)

63-71: Stop swallowing apex create errors; handle duplicate explicitly and surface real failures.

Empty catch trips CI and hides genuine faults. Treat domain_already_exists as benign; report others and abort to avoid inconsistent follow-up.

-        if (isCloud && apexDomain && !isSiteDomain) {
-            try {
-                domain = await sdk.forConsole.domains.create({
-                    teamId: $project.teamId,
-                    domain: apexDomain
-                });
-            } catch (error) {
-                // Empty as domain creation error needs to be silent
-            }
-        }
+        if (isCloud && apexDomain && !isSiteDomain) {
+            try {
+                domain = await sdk.forConsole.domains.create({
+                    teamId: $project.teamId,
+                    domain: apexDomain
+                });
+            } catch (error: any) {
+                // Ignore "already exists", surface anything else.
+                if (error?.type !== 'domain_already_exists') {
+                    addNotification({
+                        type: 'error',
+                        message: error?.message ?? 'Failed to create apex domain'
+                    });
+                    return;
+                }
+            }
+        }

Optional: If you have the domains list in data, short‑circuit the create when the apex already exists to avoid noisy duplicates.


105-111: Guard updateNameservers and don’t swallow failures.

domain may be undefined; calling domain.$id can crash. Also avoid empty catch; warn the user so they can retry via “View logs.”

-                if (isCloud) {
-                    try {
-                        await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
-                    } catch (error) {
-                        // Empty as domain update error needs to be silent
-                    }
-                }
+                if (isCloud && domain?.$id) {
+                    try {
+                        await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
+                    } catch (error: any) {
+                        addNotification({
+                            type: 'warning',
+                            message:
+                                'Failed to update nameservers for apex domain. You can retry from Domains → View logs.'
+                        });
+                    }
+                }
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (1)

93-96: Guard missing ruleId before verifying

ruleId can be null (line 31); passing it into the SDK will likely throw. This should fail fast with a clear message.

+if (!ruleId) {
+    throw new Error('Missing rule id. Please restart the verification flow.');
+}
 const ruleData = await sdk
     .forProject(page.params.region, page.params.project)
     .proxy.updateRuleVerification({ ruleId });
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (1)

93-95: Missing ruleId guard before SDK call

ruleId from line 31 can be null. The SDK call needs protection against null values.

+if (!ruleId) {
+    throw new Error('Missing rule id. Please restart the verification flow.');
+}
 const ruleData = await sdk
     .forProject(page.params.region, page.params.project)
     .proxy.updateRuleVerification({ ruleId });
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (2)

59-61: Fix empty catch block that causes lint failure.

ESLint ignores block statements which contain a comment to indicate intentional behavior. The comments in lines 60 and 99 resolve the lint issue, but the approach violates error handling best practices.

Apply this diff to handle domain creation errors properly:

-        let domain: Models.Domain;
-
-        if (isCloud && apexDomain) {
-            try {
-                domain = await sdk.forConsole.domains.create({
-                    teamId: $project.teamId,
-                    domain: apexDomain
-                });
-            } catch (error) {
-                // Empty as domain creation error needs to be silent
-            }
-        }
+        let domain: Models.Domain | null = null;
+        if (isCloud && apexDomain) {
+            domain = await sdk.forConsole.domains
+                .create({ teamId: $project.teamId, domain: apexDomain })
+                .catch(() => null); // Domain may already exist; safe to ignore
+        }

95-101: Guard against null reference and fix empty catch block.

ESLint ignores block statements which contain a comment, but this approach can mask real errors and cause null reference issues if domain is undefined.

Apply this diff to safely handle the nameserver update:

-                if (isCloud) {
-                    try {
-                        await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id });
-                    } catch (error) {
-                        // Empty as domain update error needs to be silent
-                    }
-                }
+                if (isCloud && domain?.$id) {
+                    await sdk.forConsole.domains
+                        .updateNameservers({ domainId: domain.$id })
+                        .catch(() => {}); // Non-blocking best-effort
+                }
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (3)

91-95: Guard against missing ruleId before SDK call.

The code calls updateRuleVerification with ruleId without checking if it's null or undefined, which could cause SDK errors.

+            if (!ruleId) {
+                throw new Error('Missing rule ID. Please restart the verification flow.');
+            }
+            
             const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });

189-202: LGTM! Clean component integration with proper status propagation.

The component integration correctly passes ruleStatus from data.proxyRule.status to both NameserverTable and RecordTable components, along with the navigation callbacks for tab switching. This provides a consistent UI experience across the verification flow.


52-89: Complex apex domain verification with multiple silent error handling issues.

The verification flow has several problematic patterns:

  1. Multiple empty catch blocks that silence all errors without proper handling
  2. Inconsistent verification state management
  3. Potential null reference issues with domain lookups

Apply this comprehensive refactor:

     async function verify() {
         try {
+            let apexVerified = true;
             if (isCloud) {
                 const apexDomain = getApexDomain(data.proxyRule.domain);
                 if (apexDomain) {
-                    try {
-                        const domainData = await sdk.forConsole.domains.create({
-                            teamId: $organization.$id,
-                            domain: apexDomain
-                        });
-                        verified = domainData.nameservers.toLowerCase() === 'appwrite';
-                        if (!verified) {
-                            throw new Error(
-                                'Domain verification failed. Please check your domain settings or try again later'
-                            );
-                        }
-                    } catch (error) {
-                        // Empty as domain creation error needs to be silent
-                    }
-
-                    try {
+                    // Create apex domain if needed (ignore if already exists)
+                    const domainData = await sdk.forConsole.domains.create({
+                        teamId: $organization.$id,
+                        domain: apexDomain
+                    }).catch(() => null);
+                    
+                    if (domainData) {
+                        apexVerified = domainData.nameservers.toLowerCase() === 'appwrite';
+                    }
+                    
+                    // Update nameservers for existing domain
+                    if (!apexVerified) {
                         const domain = data.domainsList.domains.find(
                             (d: Models.Domain) => d.domain === apexDomain
                         );
                         if (domain) {
-                            const output = await sdk.forConsole.domains.updateNameservers({
+                            const output = await sdk.forConsole.domains
+                                .updateNameservers({
-                                domainId: domain.$id
-                            });
-                            verified = output.nameservers.toLowerCase() === 'appwrite';
-                            if (!verified) {
-                                throw new Error(
-                                    'Domain verification failed. Please check your domain settings or try again later'
-                                );
-                            }
+                                    domainId: domain.$id
+                                })
+                                .catch(() => ({ nameservers: '' }));
+                            apexVerified = output.nameservers.toLowerCase() === 'appwrite';
                         }
-                    } catch (error) {
-                        // Empty as domain update error needs to be silent
                     }
+                    
+                    if (!apexVerified) {
+                        throw new Error(
+                            'Apex domain verification failed. Please check your domain settings.'
+                        );
+                    }
                 }
             }
 
+            if (!ruleId) {
+                throw new Error('Missing rule ID. Please restart the verification flow.');
+            }
+            
             const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
 
             verified = ruleData.status === 'verified';
             if (!verified) {
                 throw new Error(
                     'Domain verification failed. Please check your domain settings or try again later'
                 );
             }

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: 3

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]/domains/table.svelte (1)

41-41: Fix type: selectedProxyRule can be null.

Allow null to satisfy TS and Svelte runes.

-let selectedProxyRule: Models.ProxyRule = $state(null);
+let selectedProxyRule: Models.ProxyRule | null = $state(null);
🧹 Nitpick comments (2)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (2)

226-230: Unify ActionMenu divider styles with Sites table.

Match padding used in Sites variant for consistent spacing.

 .action-menu-divider {
     margin-inline: -1rem;
+    padding-block-start: 0.25rem;
+    padding-block-end: 0.25rem;
 }

186-186: Nit: prefer consistent prop style for DnsRecordsAction.

Either use shorthand {rule} or explicit rule={proxyRule} across files for consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b68cf9 and ce61ac0.

📒 Files selected for processing (3)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte (8 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/settings/domains/table.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). (6)
  • GitHub Check: publish-cloud-no-regions
  • GitHub Check: publish-self-hosted
  • GitHub Check: publish-cloud-stage
  • GitHub Check: publish-cloud
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (3)
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (2)

130-146: LGTM: updated column with short relative time.

Good conditional rendering and concise timestamp via timeFromNowShort.


76-92: Confirm backend/UX semantics for domain status → badge copy

Frontend consistently maps: created → "Verification failed"; verifying → "Generating certificate"; unverified → "Certificate generation failed". Verify that the backend status meanings and intended product/UX copy match this mapping.

Locations to check:

  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte (≈ lines 76–116)
  • src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte (≈ lines 82–121)
  • src/lib/components/domains/cnameTable.svelte (≈ lines 27–36), nameserverTable.svelte (≈ lines 20–29), recordTable.svelte (≈ lines 54–63)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (≈ lines 75–114)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte (1)

130-146: LGTM: updated column with timeFromNowShort.

Comment on lines +99 to +107
size="s"
on:click={(e) => {
e.preventDefault();
selectedProxyRule = proxyRule;
showLogs = true;
}}>
View logs
</Link>
</Layout.Stack>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard “View logs” link behind presence of logs (aligns with ActionMenu).

-                                    <Link
-                                        size="s"
-                                        on:click={(e) => {
-                                            e.preventDefault();
-                                            selectedProxyRule = proxyRule;
-                                            showLogs = true;
-                                        }}>
-                                        View logs
-                                    </Link>
+                                    {#if proxyRule.logs}
+                                        <Link
+                                            size="s"
+                                            on:click={(e) => {
+                                                e.preventDefault();
+                                                selectedProxyRule = proxyRule;
+                                                showLogs = true;
+                                            }}>
+                                            View logs
+                                        </Link>
+                                    {/if}
-                                    <Link
-                                        size="s"
-                                        on:click={(e) => {
-                                            e.preventDefault();
-                                            selectedProxyRule = proxyRule;
-                                            showLogs = true;
-                                        }}>
-                                        View logs
-                                    </Link>
+                                    {#if proxyRule.logs}
+                                        <Link
+                                            size="s"
+                                            on:click={(e) => {
+                                                e.preventDefault();
+                                                selectedProxyRule = proxyRule;
+                                                showLogs = true;
+                                            }}>
+                                            View logs
+                                        </Link>
+                                    {/if}

Also applies to: 115-123

🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte
around lines 99-107 (and similarly at 115-123), the "View logs" Link is always
rendered; guard it so the link only appears when logs are present. Update the
template to conditionally render the Link (or replace it with a disabled/hidden
element) based on the same log-presence check used by ActionMenu (e.g., check
proxyRule.logs or proxyRule.hasLogs), and ensure the on:click handler is only
attached when logs exist to avoid no-op clicks.

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

🧹 Nitpick comments (6)
src/lib/helpers/tlds.ts (1)

7-8: Small robustness/DRY tweak: normalize input and reuse parse options.

  • Trim and strip a trailing dot before parsing to handle inputs like example.com..
  • Hoist parse options to avoid repeating literals.

Apply this diff and add the helper just below imports:

-import { parse } from 'tldts';
+import { parse } from 'tldts';
+const parseOpts = { allowPrivateDomains: true } as const;
+
+function normalizeDomain(input: string | null | undefined): string {
+    return (input ?? '').trim().replace(/\.$/, '');
+}

Then update calls:

-export function getApexDomain(domain: string): string | null {
-    return parse(domain, { allowPrivateDomains: true }).domain;
+export function getApexDomain(domain: string): string | null {
+    return parse(normalizeDomain(domain), parseOpts).domain;
 }
@@
-    const { domain: apex, subdomain } = parse(domain, { allowPrivateDomains: true });
+    const { domain: apex, subdomain } = parse(normalizeDomain(domain), parseOpts);
@@
-export function getSubdomain(domain: string): string {
-    if (!domain) return '';
-
-    return parse(domain, { allowPrivateDomains: true }).subdomain || '';
+export function getSubdomain(domain: string): string {
+    if (!domain) return '';
+    return parse(normalizeDomain(domain), parseOpts).subdomain || '';
 }

Also applies to: 16-20, 25-29

src/lib/components/domains/cnameTable.svelte (2)

19-20: Make subdomain reactive to domain changes.

As written, subdomain won’t update if domain prop changes after mount.

Apply this diff:

-    let subdomain = getSubdomain(domain);
+    let subdomain: string;
+    $: subdomain = getSubdomain(domain);

64-82: Guard CAA string handling (minor).

includes(' ') assumes a string. It’s wrapped in an {#if _APP_DOMAIN_TARGET_CAA}, but if the store ever returns a non-string (e.g., boolean), this will throw. Coerce to string before using.

Apply this diff:

-                        text={$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA.includes(' ')
-                            ? $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA
-                            : `0 issue "${$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}"`} />
+                        text={(String($regionalConsoleVariables._APP_DOMAIN_TARGET_CAA)).includes(' ')
+                            ? String($regionalConsoleVariables._APP_DOMAIN_TARGET_CAA)
+                            : `0 issue "${String($regionalConsoleVariables._APP_DOMAIN_TARGET_CAA)}"`} />
src/lib/components/domains/recordTable.svelte (3)

23-24: Make subdomain reactive to domain changes.

Same issue as in CNAME table; ensure updates on prop change.

Apply this diff:

-    let subdomain = getSubdomain(domain);
+    let subdomain: string;
+    $: subdomain = getSubdomain(domain);

87-105: Guard CAA string handling (minor).

Mirror the CNAME table fix to avoid potential runtime errors if the store value isn’t a string.

Apply this diff:

-                    <InteractiveText
+                    <InteractiveText
                         variant="copy"
                         isVisible
-                        text={$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA.includes(' ')
-                            ? $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA
-                            : `0 issue "${$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}"`} />
+                        text={(String($regionalConsoleVariables._APP_DOMAIN_TARGET_CAA)).includes(' ')
+                            ? String($regionalConsoleVariables._APP_DOMAIN_TARGET_CAA)
+                            : `0 issue "${String($regionalConsoleVariables._APP_DOMAIN_TARGET_CAA)}"`} />

108-130: Nice UX for apex guidance; consider extracting shared badge/status view.

This banner logic is solid. Given similar status/badge blocks across domain components, consider a tiny helper to centralize status→badge text/type and re-use it to avoid drift.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce61ac0 and 2fcdf31.

📒 Files selected for processing (3)
  • src/lib/components/domains/cnameTable.svelte (4 hunks)
  • src/lib/components/domains/recordTable.svelte (3 hunks)
  • src/lib/helpers/tlds.ts (2 hunks)
⏰ 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 (3)
src/lib/helpers/tlds.ts (1)

7-8: Private-domain awareness looks correct (LGTM).

Using allowPrivateDomains: true aligns apex/subdomain detection with PSL private suffixes and matches the new UI flows.

Also applies to: 16-20

src/lib/components/domains/cnameTable.svelte (1)

28-41: Confirm status mapping for ruleStatus.

Mapping created → "Verification failed" and unverified → "Certificate generation failed" is non‑obvious. Verify these align with backend rule statuses to avoid misleading badges.

src/lib/components/domains/recordTable.svelte (1)

54-66: Confirm status mapping for ruleStatus.

Same mapping concern as CNAME table; ensure wording matches actual backend states.

Comment on lines +25 to 33
const aTabVisible =
!isCloud &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
const aaaaTabVisible =
!isCloud &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
Copy link
Contributor

@coderabbitai coderabbitai bot Sep 23, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix non‑reactive use of store values (visible tabs won’t update).

aTabVisible/aaaaTabVisible are computed once; they won’t reflect async store updates. Convert to reactive declarations.

Apply this diff:

-    const aTabVisible =
-        !isCloud &&
-        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
-        $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
-    const aaaaTabVisible =
-        !isCloud &&
-        !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
-        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
+    let aTabVisible = false;
+    let aaaaTabVisible = false;
+    $: aTabVisible =
+        !isCloud &&
+        Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_A) &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
+    $: aaaaTabVisible =
+        !isCloud &&
+        Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const aTabVisible =
!isCloud &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
const aaaaTabVisible =
!isCloud &&
!!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
let aTabVisible = false;
let aaaaTabVisible = false;
$: aTabVisible =
!isCloud &&
Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_A) &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1';
$: aaaaTabVisible =
!isCloud &&
Boolean($regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1';
🤖 Prompt for AI Agents
In src/lib/components/domains/recordTable.svelte around lines 25 to 33, the
boolean flags aTabVisible and aaaaTabVisible are defined as plain consts so they
are computed once and won’t update when the regionalConsoleVariables store
changes; change them to Svelte reactive declarations (use $: aTabVisible = ...
and $: aaaaTabVisible = ...) that reference $regionalConsoleVariables so the
values re-evaluate when the store updates, preserving the existing logic
(!isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
$regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1' and similarly for
the AAAA check against '::1').

Copy link
Member

Choose a reason for hiding this comment

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

makes sense. @vermakhushboo using svelte5 would make this $derived or $derived.by instead.

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Member

Choose a reason for hiding this comment

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

lets move to runes (svelte5) syntax. pretty direct migration.

Comment on lines +77 to +79
text={$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA.includes(' ')
? $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA
: `0 issue "${$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}"`} />
Copy link
Member

Choose a reason for hiding this comment

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

lets extract this to a derived const.

Copy link
Member

Choose a reason for hiding this comment

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

svelte5

{#if ruleStatus === 'created'}
<Badge variant="secondary" type="error" size="xs" content="Verification failed" />
{:else if ruleStatus === 'verifying'}
<Badge variant="secondary" size="xs" content="Generating certificate" />
Copy link
Member

Choose a reason for hiding this comment

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

do we not use a warning [orange] variant in similar places for different states? 🤔

</Typography.Text>
{#if verified === true}
{#if ruleStatus === 'created'}
<Badge variant="secondary" type="error" size="xs" content="Verification failed" />
Copy link
Member

Choose a reason for hiding this comment

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

is this correct? does ruleStatus === 'created mean it failed verification? is there no other status on rule?

Comment on lines +54 to +57
{#if ruleStatus === 'created'}
<Badge variant="secondary" type="error" size="xs" content="Verification failed" />
{:else if ruleStatus === 'verifying'}
<Badge variant="secondary" size="xs" content="Generating certificate" />
Copy link
Member

Choose a reason for hiding this comment

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

same as above

Comment on lines +100 to +102
text={$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA.includes(' ')
? $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA
: `0 issue "${$regionalConsoleVariables._APP_DOMAIN_TARGET_CAA}"`} />
Copy link
Member

Choose a reason for hiding this comment

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

same as before.

Comment on lines 58 to 61
const domainData = await sdk.forConsole.domains.create({
teamId: $organization.$id,
domain: apexDomain
});
Copy link
Member

Choose a reason for hiding this comment

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

can we group this and the below call into Promise.all if they both are independent? would save some time to go sequentially.

Copy link
Member Author

Choose a reason for hiding this comment

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

I would like to keep it sequential 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: 3

🧹 Nitpick comments (3)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (3)

35-44: Align default tab selection with tab visibility gates

Default selection can point to a tab that’s hidden (e.g., localhost/127.0.0.1/::1, or self‑host where Nameservers tab is hidden). Make selection logic consistent with render conditions and avoid selecting Nameservers on self‑host.

-    if ($regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME) {
+    if (
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'
+    ) {
         selectedTab = 'cname';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_A) {
+    } else if (
+        !isCloud &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_A &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'
+    ) {
         selectedTab = 'a';
-    } else if (!isCloud && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA) {
+    } else if (
+        !isCloud &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA &&
+        $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'
+    ) {
         selectedTab = 'aaaa';
     } else {
-        selectedTab = 'nameserver';
+        selectedTab = isCloud ? 'nameserver' : 'a';
     }

52-68: Optional: clarify “fire‑and‑forget” intent

These promises are intentionally not awaited; consider prefixing with void for linter clarity and to signal intent. Also guard nameservers on potential null.

-                    sdk.forConsole.domains
+                    void sdk.forConsole.domains
                         .create({
                             teamId: $organization.$id,
                             domain: apexDomain
                         })
                         .then((domainData) => {
-                            if (domainData.nameservers.toLowerCase() === 'appwrite') {
+                            if (domainData.nameservers?.toLowerCase() === 'appwrite') {
                                 verified = true;
                             }
                         })

123-124: URL‑encode domain in navigation

Avoid malformed URLs for domains with special characters.

-        await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`);
+        await goto(`${routeBase}/add-domain?domain=${encodeURIComponent(data.proxyRule.domain)}`);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fcdf31 and 18de91d.

📒 Files selected for processing (6)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (2 hunks)
  • src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte
🔇 Additional comments (13)
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte (6)

15-15: LGTM: Type import for Models

Type import is appropriate and used below for Models.Domain.


24-24: LGTM: Import getApexDomain

Import aligns with usage in verify().


140-141: LGTM: Use proxyRule.domain for display

Consistent with the rest of the flow.


151-166: LGTM: Tab visibility guards

Conditions correctly hide tabs for localhost/127.0.0.1/::1 and self‑host/cloud.

Double‑check that the default selection logic (Lines 35‑44) is updated per earlier suggestion to avoid selecting a hidden tab.

Also applies to: 167-182


187-191: LGTM: Propagate ruleStatus and domain to tables

Matches the updated component interfaces in this PR.

Ensure nameserverTable.svelte and recordTable.svelte accept ruleStatus as a prop and handle undefined verified.

Also applies to: 192-200


89-91: Guard missing ruleId before calling updateRuleVerification

-            const ruleData = await sdk
+            if (!ruleId) {
+                throw new Error('Missing rule id. Please restart the verification flow.');
+            }
+            const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
 
             verified = ruleData.status === 'verified';
             if (!verified) {
                 throw new Error(
                     'Domain verification failed. Please check your domain settings or try again later'
                 );
             }

Also applies to: 93-97

src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte (2)

55-55: Remove debug log.

Leftover console.log should be dropped.

Apply:

-                console.log('apexDomain', apexDomain);

91-94: Guard ruleId before verification.

Prevents SDK call with null/undefined.

Apply:

-            const ruleData = await sdk
+            if (!ruleId) {
+                throw new Error('Missing rule id. Please restart the verification flow.');
+            }
+            const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte (2)

60-75: Avoid empty catch; await domain creation and handle duplicates explicitly.

The non-awaited create with a comment-only catch both hides failures and can trip the linter (“empty block”). Also, without awaiting, domain may still be undefined when you later try to use it, causing the nameserver update to be skipped due to a race.

Apply:

-        let domain: Models.Domain;
+        let domain: Models.Domain | undefined;
@@
-        if (isCloud && apexDomain && !isSiteDomain) {
-            sdk.forConsole.domains
-                .create({
-                    teamId: $project.teamId,
-                    domain: apexDomain
-                })
-                .then((createdDomain) => {
-                    domain = createdDomain;
-                })
-                .catch(() => {
-                    // Empty as domain creation error needs to be silent
-                });
-        }
+        if (isCloud && apexDomain && !isSiteDomain) {
+            try {
+                domain = await sdk.forConsole.domains.create({
+                    teamId: $project.teamId,
+                    domain: apexDomain
+                });
+            } catch (error: any) {
+                // Ignore known duplicate, surface anything else.
+                if (error?.type !== 'domain_already_exists') {
+                    addNotification({
+                        type: 'error',
+                        message: error?.message ?? 'Failed to create apex domain'
+                    });
+                    return;
+                }
+            }
+        }

108-112: Guard domain.$id and don’t swallow update errors.

Avoid comment-only catch; also ensure $id exists.

Apply:

-                if (isCloud && domain) {
-                    sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }).catch(() => {
-                        // Empty as domain update error needs to be silent
-                    });
-                }
+                if (isCloud && domain?.$id) {
+                    sdk.forConsole.domains
+                        .updateNameservers({ domainId: domain.$id })
+                        .catch((error: any) => {
+                            addNotification({
+                                type: 'warning',
+                                message:
+                                    'Failed to update nameservers for apex domain. You can retry from Domains → View logs.'
+                            });
+                        });
+                }
src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte (1)

91-96: Guard missing ruleId before calling updateRuleVerification.

Fail fast with a clear message to avoid SDK errors.

Apply:

-            const ruleData = await sdk
+            if (!ruleId) {
+                throw new Error('Missing rule id. Please restart the verification flow.');
+            }
+            const ruleData = await sdk
                 .forProject(page.params.region, page.params.project)
                 .proxy.updateRuleVerification({ ruleId });
src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte (2)

54-57: Guard domain?.$id and surface failures in catch.

Apply:

-                if (isCloud && domain) {
-                    sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }).catch(() => {
-                        // Empty as domain update error needs to be silent
-                    });
-                }
+                if (isCloud && domain?.$id) {
+                    sdk.forConsole.domains
+                        .updateNameservers({ domainId: domain.$id })
+                        .catch((error: any) => {
+                            addNotification({
+                                type: 'warning',
+                                message:
+                                    'Failed to update nameservers for apex domain. You can retry from Domains → View logs.'
+                            });
+                        });
+                }

31-45: Same issue: empty catch and race on domain; await and handle errors.

The comment-only catch will fail lint; also without awaiting, domain may not be set.

Apply:

-        let domain: Models.Domain;
+        let domain: Models.Domain | undefined;
@@
-        if (isCloud && apexDomain) {
-            sdk.forConsole.domains
-                .create({
-                    teamId: $project.teamId,
-                    domain: apexDomain
-                })
-                .then((createdDomain) => {
-                    domain = createdDomain;
-                })
-                .catch(() => {
-                    // Empty as domain creation error needs to be silent
-                });
-        }
+        if (isCloud && apexDomain) {
+            try {
+                domain = await sdk.forConsole.domains.create({
+                    teamId: $project.teamId,
+                    domain: apexDomain
+                });
+            } catch (error: any) {
+                if (error?.type !== 'domain_already_exists') {
+                    addNotification({
+                        type: 'error',
+                        message: error?.message ?? 'Failed to create apex domain'
+                    });
+                    return;
+                }
+            }
+        }

Comment on lines +69 to +85
const domain = data.domainsList.domains.find(
(d: Models.Domain) => d.domain === apexDomain
);
if (domain) {
sdk.forConsole.domains
.updateNameservers({
domainId: domain.$id
})
.then((output) => {
if (output.nameservers.toLowerCase() === 'appwrite') {
verified = true;
}
})
.catch(() => {
// Empty as domain update error needs to be silent
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Make domains list access null‑safe

data.domainsList may be absent or fail to load; direct access can throw at runtime.

-                    const domain = data.domainsList.domains.find(
-                        (d: Models.Domain) => d.domain === apexDomain
-                    );
+                    const domain = data.domainsList?.domains?.find(
+                        (d: Models.Domain) => d.domain === apexDomain
+                    );
                     if (domain) {
                         sdk.forConsole.domains
                             .updateNameservers({
                                 domainId: domain.$id
                             })
                             .then((output) => {
-                                if (output.nameservers.toLowerCase() === 'appwrite') {
+                                if (output.nameservers?.toLowerCase() === 'appwrite') {
                                     verified = true;
                                 }
                             })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const domain = data.domainsList.domains.find(
(d: Models.Domain) => d.domain === apexDomain
);
if (domain) {
sdk.forConsole.domains
.updateNameservers({
domainId: domain.$id
})
.then((output) => {
if (output.nameservers.toLowerCase() === 'appwrite') {
verified = true;
}
})
.catch(() => {
// Empty as domain update error needs to be silent
});
}
const domain = data.domainsList?.domains?.find(
(d: Models.Domain) => d.domain === apexDomain
);
if (domain) {
sdk.forConsole.domains
.updateNameservers({
domainId: domain.$id
})
.then((output) => {
if (output.nameservers?.toLowerCase() === 'appwrite') {
verified = true;
}
})
.catch(() => {
// Empty as domain update error needs to be silent
});
}
🤖 Prompt for AI Agents
In
src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte
around lines 69 to 85, the code directly accesses data.domainsList.domains which
can be undefined and cause a runtime crash; make this null-safe by first
guarding that data and data.domainsList exist and using optional chaining or a
default empty array when calling .find (e.g. const domains =
data?.domainsList?.domains || []; const domain = domains.find(...)) and if no
domain is found simply skip the updateNameservers call (or return early) so
updateNameservers is only invoked when domain is present.

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.

2 participants