From f044340c50e9c4861a448a755102d04e8747f5fe Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 12 Sep 2025 19:38:17 +0530 Subject: [PATCH 01/22] Add new badges to site domains --- src/lib/helpers/date.ts | 20 +++++ .../sites/site-[site]/domains/store.ts | 7 ++ .../sites/site-[site]/domains/table.svelte | 74 +++++++++++++++++-- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/src/lib/helpers/date.ts b/src/lib/helpers/date.ts index 2d56c1cb6a..3adf3d2c18 100644 --- a/src/lib/helpers/date.ts +++ b/src/lib/helpers/date.ts @@ -206,6 +206,26 @@ export function timeFromNow(datetime: string): string { return dayjs().to(dayjs(datetime)); } +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 hoursToDays(hours: number) { if (hours > 24) { return `${Math.floor(hours / 24)} days`; diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts index 902fb3e3e8..647887b620 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts @@ -15,5 +15,12 @@ export const columns = writable([ title: 'Target', type: 'string', width: { min: 120, max: 400 } + }, + + { + id: 'updated', + title: '', + type: 'string', + width: { min: 100, max: 140 } } ]); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte index b5b755480d..6a259cc2d3 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte @@ -25,6 +25,7 @@ import { columns } from './store'; import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store'; import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; + import { timeFromNowShort } from '$lib/helpers/date'; let { proxyRules, @@ -72,18 +73,75 @@ - {#if rule.status === 'verifying'} - - {:else if rule.status !== 'verified'} - + {#if rule.status === 'created'} + + + { + e.preventDefault(); + selectedProxyRule = rule; + showRetry = true; + }}> + Retry + + + {:else if rule.status === 'verifying'} + + + { + e.preventDefault(); + selectedProxyRule = rule; + showLogs = true; + }}> + View logs + + + {:else if rule.status === 'unverified'} + + + { + e.preventDefault(); + selectedProxyRule = rule; + showLogs = true; + }}> + View logs + + {/if} {:else if column.id === 'target'} {proxyTarget(rule)} + {:else if column.id === 'updated'} + {#if rule.status !== 'verified'} + + {#if rule.status === 'created'} + Checked {timeFromNowShort(rule.$updatedAt)} + {:else if rule.status === 'verifying'} + Updated {timeFromNowShort(rule.$updatedAt)} + {:else if rule.status === 'unverified'} + Failed {timeFromNowShort(rule.$updatedAt)} + {/if} + + {/if} {/if} {/each} From 995ef38eabb070025c3dccf4837e1e1cc35ad91d Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Tue, 16 Sep 2025 12:56:47 +0530 Subject: [PATCH 02/22] Add badges and links to functions/projects tables --- src/lib/components/domains/index.ts | 5 + .../components}/domains/viewLogsModal.svelte | 0 src/lib/components/index.ts | 1 + .../domains/add-domain/+page.svelte | 10 +- .../function-[function]/domains/store.ts | 9 +- .../function-[function]/domains/table.svelte | 112 ++++++++++++++-- .../settings/domains/add-domain/+page.svelte | 2 +- .../settings/domains/table.svelte | 122 ++++++++++++++++-- .../sites/site-[site]/domains/store.ts | 4 +- .../sites/site-[site]/domains/table.svelte | 32 ++--- 10 files changed, 255 insertions(+), 42 deletions(-) create mode 100644 src/lib/components/domains/index.ts rename src/{routes/(console)/project-[region]-[project]/sites/site-[site] => lib/components}/domains/viewLogsModal.svelte (100%) diff --git a/src/lib/components/domains/index.ts b/src/lib/components/domains/index.ts new file mode 100644 index 0000000000..8571098162 --- /dev/null +++ b/src/lib/components/domains/index.ts @@ -0,0 +1,5 @@ +export { default as ViewLogsModal } from './viewLogsModal.svelte'; +export { default as CnameTable } from './cnameTable.svelte'; +export { default as DnsRecordsAction } from './dnsRecordsAction.svelte'; +export { default as NameserverTable } from './nameserverTable.svelte'; +export { default as RecordTable } from './recordTable.svelte'; diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/viewLogsModal.svelte b/src/lib/components/domains/viewLogsModal.svelte similarity index 100% rename from src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/viewLogsModal.svelte rename to src/lib/components/domains/viewLogsModal.svelte diff --git a/src/lib/components/index.ts b/src/lib/components/index.ts index 47afdf41ad..5b4ae563d6 100644 --- a/src/lib/components/index.ts +++ b/src/lib/components/index.ts @@ -87,3 +87,4 @@ export { default as ExpirationInput } from './expirationInput.svelte'; export { default as EstimatedCard } from './estimatedCard.svelte'; export { default as EmailVerificationBanner } from './alerts/emailVerificationBanner.svelte'; export { default as SortButton, type SortDirection } from './sortButton.svelte'; +export * from './domains'; diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte index f913e4c91a..edb5bc8faa 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte @@ -101,9 +101,13 @@ await goto(routeBase); await invalidate(Dependencies.FUNCTION_DOMAINS); } else { - await goto( - `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}&domain=${domain.$id}` - ); + let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`; + + if (isCloud && domain?.$id) { + redirect += `&domain=${domain.$id}`; + } + + await goto(redirect); await invalidate(Dependencies.FUNCTION_DOMAINS); } } catch (error) { diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts index 902fb3e3e8..5f36c6bc17 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/store.ts @@ -7,7 +7,7 @@ export const columns = writable([ title: 'Domain', type: 'string', format: 'string', - width: { min: 200 } + width: { min: 300 } }, { @@ -15,5 +15,12 @@ export const columns = writable([ title: 'Target', type: 'string', width: { min: 120, max: 400 } + }, + + { + id: 'updated', + title: '', + type: 'string', + width: { min: 160, max: 180 } } ]); diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte index 80f8663d44..f3a1f1d8a6 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/table.svelte @@ -3,10 +3,16 @@ import { Link } from '$lib/elements'; import { Button } from '$lib/elements/forms'; import type { Models } from '@appwrite.io/console'; - import { IconDotsHorizontal, IconRefresh, IconTrash } from '@appwrite.io/pink-icons-svelte'; + import { + IconDotsHorizontal, + IconRefresh, + IconTerminal, + IconTrash + } from '@appwrite.io/pink-icons-svelte'; import { ActionMenu, Badge, + Divider, Icon, Layout, Popover, @@ -15,9 +21,11 @@ } from '@appwrite.io/pink-svelte'; import DeleteDomainModal from './deleteDomainModal.svelte'; import RetryDomainModal from './retryDomainModal.svelte'; + import { ViewLogsModal } from '$lib/components'; import { columns } from './store'; import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store'; import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; + import { timeFromNowShort } from '$lib/helpers/date'; let { proxyRules, @@ -29,6 +37,7 @@ let showDelete = $state(false); let showRetry = $state(false); + let showLogs = $state(false); let selectedProxyRule: Models.ProxyRule = $state(null); const proxyTarget = (proxy: Models.ProxyRule) => { @@ -63,18 +72,77 @@ {proxyRule.domain} - {#if proxyRule.status === 'verifying'} - - {:else if proxyRule.status !== 'verified'} - + {#if proxyRule.status === 'created'} + + + { + e.preventDefault(); + selectedProxyRule = proxyRule; + showRetry = true; + }}> + Retry + + + {:else if proxyRule.status === 'verifying'} + + + { + e.preventDefault(); + selectedProxyRule = proxyRule; + showLogs = true; + }}> + View logs + + + {:else if proxyRule.status === 'unverified'} + + + { + e.preventDefault(); + selectedProxyRule = proxyRule; + showLogs = true; + }}> + View logs + + {/if} {:else if column.id === 'target'} {proxyTarget(proxyRule)} + {:else if column.id === 'updated'} + + {#if proxyRule.status !== 'verified'} + + {#if proxyRule.status === 'created'} + Checked {timeFromNowShort(proxyRule.$updatedAt)} + {:else if proxyRule.status === 'verifying'} + Updated {timeFromNowShort(proxyRule.$updatedAt)} + {:else if proxyRule.status === 'unverified'} + Failed {timeFromNowShort(proxyRule.$updatedAt)} + {/if} + + {/if} + {/if} {/each} @@ -93,6 +161,17 @@ + {#if proxyRule.logs && (proxyRule.status === 'unverified' || proxyRule.status === 'verifying')} + { + selectedProxyRule = proxyRule; + showLogs = true; + toggle(e); + }}> + View logs + + {/if} {#if proxyRule.status !== 'verified' && proxyRule.status !== 'verifying'} {/if} + {#if proxyRule.logs && (proxyRule.status === 'unverified' || proxyRule.status === 'verifying')} +
+ +
+ {/if} {/if} + +{#if showLogs} + +{/if} + + diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte index 90d5a21595..476e716024 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte @@ -61,7 +61,7 @@ } else { let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`; - if (isCloud) { + if (isCloud && domain?.$id) { /** * Domains are only on cloud! * Self-hosted instances have rules. diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte index 1558e8e3f7..045a269375 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/table.svelte @@ -3,10 +3,16 @@ import { Link } from '$lib/elements'; import { Button } from '$lib/elements/forms'; import type { Models } from '@appwrite.io/console'; - import { IconDotsHorizontal, IconRefresh, IconTrash } from '@appwrite.io/pink-icons-svelte'; + import { + IconDotsHorizontal, + IconRefresh, + IconTerminal, + IconTrash + } from '@appwrite.io/pink-icons-svelte'; import { ActionMenu, Badge, + Divider, Icon, Layout, Popover, @@ -15,8 +21,10 @@ } from '@appwrite.io/pink-svelte'; import DeleteDomainModal from './deleteDomainModal.svelte'; import RetryDomainModal from './retryDomainModal.svelte'; + import { ViewLogsModal } from '$lib/components'; import { regionalProtocol } from '../../store'; import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; + import { timeFromNowShort } from '$lib/helpers/date'; let { domains, @@ -28,6 +36,7 @@ let showDelete = $state(false); let showRetry = $state(false); + let showLogs = $state(false); let selectedDomain: Models.ProxyRule = $state(null); const columns = [ @@ -36,7 +45,13 @@ title: 'Domain', type: 'string', format: 'string', - width: { min: 200, max: 550 } + width: { min: 300, max: 550 } + }, + { + id: 'updated', + title: '', + type: 'string', + width: { min: 160, max: 180 } } ]; @@ -64,14 +79,73 @@ {domain.domain} - {#if domain.status === 'verifying'} - - {:else if domain.status !== 'verified'} - + {#if domain.status === 'created'} + + + { + e.preventDefault(); + selectedDomain = domain; + showRetry = true; + }}> + Retry + + + {:else if domain.status === 'verifying'} + + + { + e.preventDefault(); + selectedDomain = domain; + showLogs = true; + }}> + View logs + + + {:else if domain.status === 'unverified'} + + + { + e.preventDefault(); + selectedDomain = domain; + showLogs = true; + }}> + View logs + + + {/if} + + {:else if column.id === 'updated'} + + {#if domain.status !== 'verified'} + + {#if domain.status === 'created'} + Checked {timeFromNowShort(domain.$updatedAt)} + {:else if domain.status === 'verifying'} + Updated {timeFromNowShort(domain.$updatedAt)} + {:else if domain.status === 'unverified'} + Failed {timeFromNowShort(domain.$updatedAt)} + {/if} + {/if} {/if} @@ -92,7 +166,18 @@ - {#if domain.status !== 'verified' && domain.status !== 'verifiying'} + {#if domain.logs && (domain.status === 'unverified' || domain.status === 'verifying')} + { + selectedDomain = domain; + showLogs = true; + toggle(e); + }}> + View logs + + {/if} + {#if domain.status !== 'verified' && domain.status !== 'verifying'} { @@ -104,6 +189,11 @@ {/if} + {#if domain.logs && (domain.status === 'unverified' || domain.status === 'verifying')} +
+ +
+ {/if} {/if} + +{#if showLogs} + +{/if} + + diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts index 647887b620..5f36c6bc17 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/store.ts @@ -7,7 +7,7 @@ export const columns = writable([ title: 'Domain', type: 'string', format: 'string', - width: { min: 200 } + width: { min: 300 } }, { @@ -21,6 +21,6 @@ export const columns = writable([ id: 'updated', title: '', type: 'string', - width: { min: 100, max: 140 } + width: { min: 160, max: 180 } } ]); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte index 6a259cc2d3..e604cfed4d 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/table.svelte @@ -21,7 +21,7 @@ } from '@appwrite.io/pink-svelte'; import DeleteDomainModal from './deleteDomainModal.svelte'; import RetryDomainModal from './retryDomainModal.svelte'; - import ViewLogsModal from './viewLogsModal.svelte'; + import { ViewLogsModal } from '$lib/components'; import { columns } from './store'; import { regionalProtocol } from '$routes/(console)/project-[region]-[project]/store'; import DnsRecordsAction from '$lib/components/domains/dnsRecordsAction.svelte'; @@ -128,20 +128,22 @@ {:else if column.id === 'target'} {proxyTarget(rule)} {:else if column.id === 'updated'} - {#if rule.status !== 'verified'} - - {#if rule.status === 'created'} - Checked {timeFromNowShort(rule.$updatedAt)} - {:else if rule.status === 'verifying'} - Updated {timeFromNowShort(rule.$updatedAt)} - {:else if rule.status === 'unverified'} - Failed {timeFromNowShort(rule.$updatedAt)} - {/if} - - {/if} + + {#if rule.status !== 'verified'} + + {#if rule.status === 'created'} + Checked {timeFromNowShort(rule.$updatedAt)} + {:else if rule.status === 'verifying'} + Updated {timeFromNowShort(rule.$updatedAt)} + {:else if rule.status === 'unverified'} + Failed {timeFromNowShort(rule.$updatedAt)} + {/if} + + {/if} + {/if} {/each} From bb6c95185ee94a1ffb5ba822d43426a845147fc3 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 17 Sep 2025 17:57:36 +0530 Subject: [PATCH 03/22] Fix verification flows for sites/functions/api --- src/lib/components/domains/cnameTable.svelte | 17 +++- .../components/domains/nameserverTable.svelte | 17 +++- src/lib/components/domains/recordTable.svelte | 17 +++- .../domains/add-domain/+page.svelte | 29 ++---- .../add-domain/verify-[domain]/+page.svelte | 86 ++++++++++++------ .../add-domain/verify-[domain]/+page.ts | 17 +++- .../domains/retryDomainModal.svelte | 87 ++++++++++++++++-- .../settings/domains/add-domain/+page.svelte | 35 ++------ .../add-domain/verify-[domain]/+page.svelte | 89 ++++++++++++------- .../add-domain/verify-[domain]/+page.ts | 15 +++- .../settings/domains/retryDomainModal.svelte | 87 ++++++++++++++++-- .../domains/add-domain/+page.svelte | 22 ++--- .../add-domain/verify-[domain]/+page.svelte | 74 ++++++++++----- .../add-domain/verify-[domain]/+page.ts | 12 ++- .../domains/retryDomainModal.svelte | 8 +- 15 files changed, 436 insertions(+), 176 deletions(-) diff --git a/src/lib/components/domains/cnameTable.svelte b/src/lib/components/domains/cnameTable.svelte index b198524da2..e7b1671ece 100644 --- a/src/lib/components/domains/cnameTable.svelte +++ b/src/lib/components/domains/cnameTable.svelte @@ -12,7 +12,8 @@ import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; export let domain: string; - export let verified = undefined; + export let verified: boolean | undefined = undefined; + export let ruleStatus: string | undefined = undefined; let subdomain = domain.split('.').slice(0, -2).join('.'); @@ -23,10 +24,18 @@ {domain} - {#if verified === true} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} - {:else if verified === false} - {/if} diff --git a/src/lib/components/domains/nameserverTable.svelte b/src/lib/components/domains/nameserverTable.svelte index a08de42080..6b71a72801 100644 --- a/src/lib/components/domains/nameserverTable.svelte +++ b/src/lib/components/domains/nameserverTable.svelte @@ -4,7 +4,8 @@ import { Badge, Layout, Typography, Table, InteractiveText } from '@appwrite.io/pink-svelte'; export let domain: string; - export let verified = undefined; + export let verified: boolean | undefined = undefined; + export let ruleStatus: string | undefined = undefined; const nameserverList = $regionalConsoleVariables?._APP_DOMAINS_NAMESERVERS ? $regionalConsoleVariables?._APP_DOMAINS_NAMESERVERS?.split(',') @@ -16,10 +17,18 @@ {domain} - {#if verified === true} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} - {:else if verified === false} - {/if} diff --git a/src/lib/components/domains/recordTable.svelte b/src/lib/components/domains/recordTable.svelte index 14683b7218..f3adacc098 100644 --- a/src/lib/components/domains/recordTable.svelte +++ b/src/lib/components/domains/recordTable.svelte @@ -11,9 +11,10 @@ import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; export let domain: string; - export let verified = 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; let subdomain = domain?.split('.')?.slice(0, -2)?.join('.'); @@ -37,10 +38,18 @@ {domain} - {#if verified === true} + {#if ruleStatus === 'created'} + + {:else if ruleStatus === 'verifying'} + + {:else if ruleStatus === 'unverified'} + + {:else if verified === true} - {:else if verified === false} - {/if} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte index edb5bc8faa..37ec0506e1 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/+page.svelte @@ -48,25 +48,15 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domains?.domains.find((d: Models.Domain) => d.domain === apexDomain); + 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) {} } try { @@ -100,14 +90,13 @@ if (rule?.status === 'verified') { await goto(routeBase); await invalidate(Dependencies.FUNCTION_DOMAINS); - } else { - let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`; - - if (isCloud && domain?.$id) { - redirect += `&domain=${domain.$id}`; + if (isCloud) { + try { + await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }); + } catch (error) {} } - - await goto(redirect); + } else { + await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); await invalidate(Dependencies.FUNCTION_DOMAINS); } } catch (error) { diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte index 4db9c86d72..56534b19b2 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.svelte @@ -12,6 +12,7 @@ import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; import { organization } from '$lib/stores/organization'; + import type { Models } from '@appwrite.io/console'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -20,7 +21,7 @@ import Wizard from '$lib/layout/wizard.svelte'; import { base } from '$app/paths'; import { writable } from 'svelte/store'; - import { isASubdomain } from '$lib/helpers/tlds'; + import { getApexDomain, isASubdomain } from '$lib/helpers/tlds'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -28,8 +29,7 @@ let { data } = $props(); const ruleId = page.url.searchParams.get('rule'); - const domainId = page.url.searchParams.get('domain'); - const isSubDomain = $derived.by(() => isASubdomain(page.params.domain)); + const isSubDomain = $derived.by(() => isASubdomain(data.proxyRule?.domain)); let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); $effect(() => { @@ -49,28 +49,51 @@ let isSubmitting = $state(writable(false)); async function verify() { - const isNewDomain = - data.domainsList.domains.find((rule) => rule.domain === page.params.domain) === - undefined; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: page.params.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; - } else if (!isNewDomain && isCloud) { - const domain = await sdk.forConsole.domains.updateNameservers({ domainId }); - verified = domain.nameservers.toLowerCase() === 'appwrite'; - if (!verified) - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); + 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) {} + + try { + const domain = data.domainsList.domains.find( + (d: Models.Domain) => d.domain === apexDomain + ); + if (domain) { + 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' + ); + } + } + } catch (error) {} + } + } + + 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' + ); } addNotification({ @@ -96,7 +119,7 @@ .forProject(page.params.region, page.params.project) .proxy.deleteRule({ ruleId }); } - await goto(`${routeBase}/add-domain?domain=${page.params.domain}`); + await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`); } @@ -113,7 +136,7 @@ - {page.params.domain} + {data.proxyRule.domain} @@ -160,9 +183,16 @@ {#if selectedTab === 'nameserver'} - + {:else} - + {/if} diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts index b89c933306..4345a9f741 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/add-domain/verify-[domain]/+page.ts @@ -3,9 +3,14 @@ import { isCloud } from '$lib/system'; import { Dependencies } from '$lib/constants.js'; import { type Models, Query } from '@appwrite.io/console'; -export const load = async ({ depends, parent }) => { - const { organization } = await parent(); - depends(Dependencies.DOMAINS); +export const load = async ({ params, parent, depends, url }) => { + const { function: func, organization } = await parent(); + depends(Dependencies.FUNCTION_DOMAINS); + + const ruleId = url.searchParams.get('rule'); + if (!ruleId) { + throw new Error('Rule ID is required'); + } let domainsList: Models.DomainsList; if (isCloud) { @@ -14,7 +19,11 @@ export const load = async ({ depends, parent }) => { }); } + const proxyRule = await sdk.forProject(params.region, params.project).proxy.getRule({ ruleId }); + return { - domainsList + function: func, + domainsList, + proxyRule }; }; diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte index 8ccd491e2b..27e64808c7 100644 --- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/domains/retryDomainModal.svelte @@ -6,9 +6,14 @@ import { invalidate } from '$app/navigation'; import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; import { Dependencies } from '$lib/constants'; - import RecordsCard from './recordsCard.svelte'; import type { Models } from '@appwrite.io/console'; + import { Divider, Tabs } from '@appwrite.io/pink-svelte'; + import { isCloud } from '$lib/system'; import { page } from '$app/state'; + import { isASubdomain } from '$lib/helpers/tlds'; + import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; + import RecordTable from '$lib/components/domains/recordTable.svelte'; + import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; let { show = $bindable(false), @@ -18,21 +23,44 @@ selectedProxyRule: Models.ProxyRule; } = $props(); + const isSubDomain = $derived.by(() => isASubdomain(selectedProxyRule?.domain)); + + let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); + + $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'; + } + }); + let error = $state(null); + let verified = $state(false); + async function retryProxyRule() { 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` }); trackEvent(Submit.DomainUpdateVerification); } catch (e) { - error = e.message; + error = + e.message ?? + 'Domain verification failed. Please check your domain settings or try again later'; trackError(e, Submit.DomainUpdateVerification); } } @@ -45,8 +73,55 @@ - {#if selectedProxyRule} - +
+ + {#if isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + (selectedTab = 'cname')} + active={selectedTab === 'cname'}> + CNAME + + {/if} + {#if isCloud} + (selectedTab = 'nameserver')} + active={selectedTab === 'nameserver'}> + Nameservers + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A && $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'} + (selectedTab = 'a')} + active={selectedTab === 'a'}> + A + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'} + (selectedTab = 'aaaa')} + active={selectedTab === 'aaaa'}> + AAAA + + {/if} + + +
+ {#if selectedTab === 'nameserver'} + + {:else} + {/if} diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte index 476e716024..088e449847 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/+page.svelte @@ -16,8 +16,6 @@ const routeBase = `${base}/project-${page.params.region}-${page.params.project}/settings/domains`; - let { data } = $props(); - let formComponent: Form; let isSubmitting = $state(writable(false)); let domainName = $state(''); @@ -30,25 +28,15 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domains?.domains.find((d: Models.Domain) => d.domain === apexDomain); + 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) {} } try { @@ -58,18 +46,13 @@ if (rule?.status === 'verified') { await goto(routeBase); await invalidate(Dependencies.DOMAINS); - } else { - let redirect = `${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`; - - if (isCloud && domain?.$id) { - /** - * Domains are only on cloud! - * Self-hosted instances have rules. - */ - redirect += `&domain=${domain.$id}`; + if (isCloud) { + try { + await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }); + } catch (error) {} } - - await goto(redirect); + } else { + await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); await invalidate(Dependencies.DOMAINS); } } catch (error) { diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte index a6c23790f5..89277ae173 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.svelte @@ -12,6 +12,7 @@ import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; import { organization } from '$lib/stores/organization'; + import type { Models } from '@appwrite.io/console'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -20,7 +21,7 @@ import Wizard from '$lib/layout/wizard.svelte'; import { base } from '$app/paths'; import { writable } from 'svelte/store'; - import { isASubdomain } from '$lib/helpers/tlds'; + import { getApexDomain, isASubdomain } from '$lib/helpers/tlds'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -28,8 +29,7 @@ let { data } = $props(); const ruleId = page.url.searchParams.get('rule'); - const domainId = page.url.searchParams.get('domain'); - const isSubDomain = $derived.by(() => isASubdomain(page.params.domain)); + const isSubDomain = $derived.by(() => isASubdomain(data.proxyRule?.domain)); let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); @@ -50,30 +50,52 @@ const isSubmitting = writable(false); async function verify() { - const isNewDomain = - data.domainsList.domains.find((rule) => rule.domain === page.params.domain) === - undefined; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: page.params.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; - } else if (!isNewDomain && isCloud) { - const domain = await sdk.forConsole.domains.updateNameservers({ - domainId - }); - verified = domain.nameservers.toLowerCase() === 'appwrite'; - if (!verified) - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); + if (isCloud) { + const apexDomain = getApexDomain(data.proxyRule.domain); + console.log('apexDomain', apexDomain); + 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) {} + + try { + const domain = data.domainsList.domains.find( + (d: Models.Domain) => d.domain === apexDomain + ); + if (domain) { + 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' + ); + } + } + } catch (error) {} + } + } + + 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' + ); } addNotification({ @@ -98,7 +120,7 @@ .forProject(page.params.region, page.params.project) .proxy.deleteRule({ ruleId }); } - await goto(`${routeBase}/add-domain?domain=${page.params.domain}`); + await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`); } @@ -115,7 +137,7 @@ - {page.params.domain} + {data.proxyRule.domain}
@@ -162,9 +184,16 @@ {#if selectedTab === 'nameserver'} - + {:else} - + {/if} diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts index b89c933306..a5c8d1ad14 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/add-domain/verify-[domain]/+page.ts @@ -3,10 +3,15 @@ import { isCloud } from '$lib/system'; import { Dependencies } from '$lib/constants.js'; import { type Models, Query } from '@appwrite.io/console'; -export const load = async ({ depends, parent }) => { - const { organization } = await parent(); +export const load = async ({ params, parent, depends, url }) => { + const { project, organization } = await parent(); depends(Dependencies.DOMAINS); + const ruleId = url.searchParams.get('rule'); + if (!ruleId) { + throw new Error('Rule ID is required'); + } + let domainsList: Models.DomainsList; if (isCloud) { domainsList = await sdk.forConsole.domains.list({ @@ -14,7 +19,11 @@ export const load = async ({ depends, parent }) => { }); } + const proxyRule = await sdk.forProject(params.region, params.project).proxy.getRule({ ruleId }); + return { - domainsList + project, + domainsList, + proxyRule }; }; diff --git a/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte index 844a2c94be..9b2a8dc347 100644 --- a/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/settings/domains/retryDomainModal.svelte @@ -7,8 +7,13 @@ import { Submit, trackEvent, trackError } from '$lib/actions/analytics'; import { Dependencies } from '$lib/constants'; import type { Models } from '@appwrite.io/console'; - import CnameTable from '$lib/components/domains/cnameTable.svelte'; + import { Divider, Tabs } from '@appwrite.io/pink-svelte'; + import { isCloud } from '$lib/system'; import { page } from '$app/state'; + import { isASubdomain } from '$lib/helpers/tlds'; + import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; + import RecordTable from '$lib/components/domains/recordTable.svelte'; + import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; let { show = $bindable(), @@ -18,21 +23,44 @@ selectedDomain: Models.ProxyRule; } = $props(); + const isSubDomain = $derived.by(() => isASubdomain(selectedDomain?.domain)); + + let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); + + $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'; + } + }); + let error = $state(null); + let verified = $state(false); + async function retryDomain() { try { - await sdk + const domain = await sdk .forProject(page.params.region, page.params.project) .proxy.updateRuleVerification({ ruleId: selectedDomain.$id }); - await invalidate(Dependencies.DOMAINS); + show = false; + verified = domain.status === 'verified'; + await invalidate(Dependencies.DOMAINS); + addNotification({ type: 'success', message: `${selectedDomain.domain} has been verified` }); trackEvent(Submit.DomainUpdateVerification); } catch (e) { - error = e.message; + error = + e.message ?? + 'Domain verification failed. Please check your domain settings or try again later'; trackError(e, Submit.DomainUpdateVerification); } } @@ -45,10 +73,55 @@ - {#if selectedDomain} - + + {#if isSubDomain && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME && $regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME !== 'localhost'} + (selectedTab = 'cname')} + active={selectedTab === 'cname'}> + CNAME + + {/if} + {#if isCloud} + (selectedTab = 'nameserver')} + active={selectedTab === 'nameserver'}> + Nameservers + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_A && $regionalConsoleVariables._APP_DOMAIN_TARGET_A !== '127.0.0.1'} + (selectedTab = 'a')} + active={selectedTab === 'a'}> + A + + {/if} + {#if !isCloud && !!$regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA && $regionalConsoleVariables._APP_DOMAIN_TARGET_AAAA !== '::1'} + (selectedTab = 'aaaa')} + active={selectedTab === 'aaaa'}> + AAAA + + {/if} + + + + {#if selectedTab === 'nameserver'} + + {:else} + + ruleStatus={selectedDomain.status} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte index f0b6df34a3..62cfca3c12 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/+page.svelte @@ -57,27 +57,16 @@ async function addDomain() { const apexDomain = getApexDomain(domainName); - let domain = data.domains?.domains.find((d: Models.Domain) => d.domain === apexDomain); - + let domain: Models.Domain; const isSiteDomain = domainName.endsWith($regionalConsoleVariables._APP_DOMAIN_SITES); - if (isCloud && apexDomain && !domain && !isSiteDomain) { + 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) {} } try { @@ -111,6 +100,11 @@ if (rule?.status === 'verified') { await goto(routeBase); await invalidate(Dependencies.SITES_DOMAINS); + if (isCloud) { + try { + await sdk.forConsole.domains.updateNameservers({ domainId: domain.$id }); + } catch (error) {} + } } else { await goto(`${routeBase}/add-domain/verify-${domainName}?rule=${rule.$id}`); await invalidate(Dependencies.SITES_DOMAINS); diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte index 8422d783a0..79f7fe5edd 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.svelte @@ -12,6 +12,7 @@ import { Button, Form } from '$lib/elements/forms'; import { sdk } from '$lib/stores/sdk'; import { organization } from '$lib/stores/organization'; + import type { Models } from '@appwrite.io/console'; import { addNotification } from '$lib/stores/notifications'; import { goto, invalidate } from '$app/navigation'; import { Dependencies } from '$lib/constants'; @@ -20,7 +21,7 @@ import Wizard from '$lib/layout/wizard.svelte'; import { base } from '$app/paths'; import { writable } from 'svelte/store'; - import { isASubdomain } from '$lib/helpers/tlds'; + import { getApexDomain, isASubdomain } from '$lib/helpers/tlds'; import RecordTable from '$lib/components/domains/recordTable.svelte'; import NameserverTable from '$lib/components/domains/nameserverTable.svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; @@ -28,7 +29,7 @@ let { data } = $props(); const ruleId = page.url.searchParams.get('rule'); - const isSubDomain = $derived.by(() => isASubdomain(page.params.domain)); + const isSubDomain = $derived.by(() => isASubdomain(data.proxyRule?.domain)); let selectedTab = $state<'cname' | 'nameserver' | 'a' | 'aaaa'>('nameserver'); @@ -50,23 +51,48 @@ let isSubmitting = $state(writable(false)); async function verify() { - const isNewDomain = - data.domainsList.domains.findIndex((rule) => rule.domain === page.params.domain) === -1; try { - if (selectedTab !== 'nameserver') { - const ruleData = await sdk - .forProject(page.params.region, page.params.project) - .proxy.updateRuleVerification({ ruleId }); - verified = ruleData.status === 'verified'; - throw new Error( - 'Domain verification failed. Please check your domain settings or try again later' - ); - } else if (isNewDomain && isCloud) { - const domainData = await sdk.forConsole.domains.create({ - teamId: $organization.$id, - domain: page.params.domain - }); - verified = domainData.nameservers.toLowerCase() === 'appwrite'; + 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) {} + + try { + const domain = data.domainsList.domains.find( + (d: Models.Domain) => d.domain === apexDomain + ); + if (domain) { + 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' + ); + } + } + } catch (error) {} + } + } + + 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' ); @@ -95,7 +121,7 @@ .forProject(page.params.region, page.params.project) .proxy.deleteRule({ ruleId }); } - await goto(`${routeBase}/add-domain?domain=${page.params.domain}`); + await goto(`${routeBase}/add-domain?domain=${data.proxyRule.domain}`); } @@ -112,7 +138,7 @@ - {page.params.domain} + {data.proxyRule.domain} @@ -159,13 +185,17 @@ {#if selectedTab === 'nameserver'} - + {:else} + domain={data.proxyRule.domain} + ruleStatus={data.proxyRule.status} /> {/if} diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts index 570e1b27a2..d16a243637 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/add-domain/verify-[domain]/+page.ts @@ -3,10 +3,15 @@ import { isCloud } from '$lib/system'; import { Dependencies } from '$lib/constants.js'; import { type Models, Query } from '@appwrite.io/console'; -export const load = async ({ parent, depends }) => { +export const load = async ({ params, parent, depends, url }) => { const { site, organization } = await parent(); depends(Dependencies.SITES_DOMAINS); + const ruleId = url.searchParams.get('rule'); + if (!ruleId) { + throw new Error('Rule ID is required'); + } + let domainsList: Models.DomainsList; if (isCloud) { domainsList = await sdk.forConsole.domains.list({ @@ -14,8 +19,11 @@ export const load = async ({ parent, depends }) => { }); } + const proxyRule = await sdk.forProject(params.region, params.project).proxy.getRule({ ruleId }); + return { site, - domainsList + domainsList, + proxyRule }; }; diff --git a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte index 949d8079c9..eb8d32761b 100644 --- a/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte +++ b/src/routes/(console)/project-[region]-[project]/sites/site-[site]/domains/retryDomainModal.svelte @@ -111,13 +111,17 @@ {#if selectedTab === 'nameserver'} - + {:else} + domain={selectedProxyRule.domain} + ruleStatus={selectedProxyRule.status} /> {/if} From bfe9c9216a762aa3f048373084c479a69a50de04 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 19 Sep 2025 11:57:42 +0530 Subject: [PATCH 04/22] Simplify timeFromNowShort function --- src/lib/helpers/date.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/lib/helpers/date.ts b/src/lib/helpers/date.ts index 3adf3d2c18..78aa554948 100644 --- a/src/lib/helpers/date.ts +++ b/src/lib/helpers/date.ts @@ -216,14 +216,9 @@ export function timeFromNowShort(datetime: string): string { 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'); + .replace('second', 'sec') // seconds > secs + .replace('minute', 'min') // minutes > mins + .replace('hour', 'hr'); // hours > hrs } export function hoursToDays(hours: number) { From 15e56c37cc90a406bf431fea469707b04af95401 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 19 Sep 2025 18:40:56 +0530 Subject: [PATCH 05/22] Add CNAME flattening changes --- src/lib/components/domains/cnameTable.svelte | 23 ++++++- src/lib/components/domains/recordTable.svelte | 68 ++++++++++++++++--- .../domains/domain-[domain]/+page.svelte | 2 +- .../add-domain/verify-[domain]/+page.svelte | 12 ++-- .../domains/retryDomainModal.svelte | 12 ++-- .../add-domain/verify-[domain]/+page.svelte | 12 ++-- .../settings/domains/retryDomainModal.svelte | 12 ++-- .../add-domain/verify-[domain]/+page.svelte | 12 ++-- .../domains/retryDomainModal.svelte | 12 ++-- 9 files changed, 118 insertions(+), 47 deletions(-) diff --git a/src/lib/components/domains/cnameTable.svelte b/src/lib/components/domains/cnameTable.svelte index e7b1671ece..a7c20acb7b 100644 --- a/src/lib/components/domains/cnameTable.svelte +++ b/src/lib/components/domains/cnameTable.svelte @@ -39,8 +39,8 @@ {/if} - Add the following record on your DNS provider. Note that DNS changes may take time to - propagate fully. + Add the following record on your DNS provider. Note that DNS changes may take up to 48 + hours to propagate fully. @@ -60,6 +60,25 @@ text={$regionalConsoleVariables._APP_DOMAIN_TARGET_CNAME} /> + {#if $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA} + + + + CAA + + + + @ + + + + + {/if} diff --git a/src/lib/components/domains/recordTable.svelte b/src/lib/components/domains/recordTable.svelte index f3adacc098..7dcba6cfdd 100644 --- a/src/lib/components/domains/recordTable.svelte +++ b/src/lib/components/domains/recordTable.svelte @@ -9,15 +9,28 @@ Alert } from '@appwrite.io/pink-svelte'; import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store'; + import { isCloud } from '$lib/system'; export let domain: string; export let verified: boolean | undefined = undefined; export let variant: 'cname' | 'a' | 'aaaa'; export let service: 'sites' | 'general' = 'general'; export let ruleStatus: string | undefined = undefined; + export let onNavigateToNameservers: () => void = () => {}; + export let onNavigateToA: () => void = () => {}; + export let onNavigateToAAAA: () => void = () => {}; let subdomain = domain?.split('.')?.slice(0, -2)?.join('.'); + 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'; + function setTarget() { switch (variant) { case 'cname': @@ -53,8 +66,8 @@ {/if} - Add the following record on your DNS provider. Note that DNS changes may take time to - propagate fully. + Add the following record on your DNS provider. Note that DNS changes may take up to 48 + hours to propagate fully. @@ -71,17 +84,50 @@ + {#if $regionalConsoleVariables._APP_DOMAIN_TARGET_CAA} + + + + CAA + + + + @ + + + + + {/if} - {#if variant === 'cname'} - - If your domain uses CAA records, ensure certainly.com is authorized — otherwise, SSL - setup may fail. A list of all domain providers and their DNS setting is available here. - + {#if variant === 'cname' && !subdomain} + {#if isCloud} + + Since is an apex domain, + CNAME record is only supported by certain providers. If yours doesn't, please verify + using + nameservers instead. + + {:else if aTabVisible || aaaaTabVisible} + + Since is an apex domain, + CNAME record is only supported by certain providers. If yours doesn't, please verify + using + {#if aTabVisible} + A record + {#if aaaaTabVisible} + or AAAA record{/if} + {:else if aaaaTabVisible} + AAAA record + {/if} instead. + + {/if} {:else} A list of all domain providers and their DNS setting is available and . - Note that DNS changes may take time to propagate fully. + Note that DNS changes may take up to 48 hours to propagate fully.