Skip to content
This repository was archived by the owner on Sep 21, 2026. It is now read-only.

Commit 241dde8

Browse files
Merge pull request #2981 from appwrite/feat/project-premium-geo-db-addon
feat: add Premium Geo DB addon to project settings
2 parents c067aa8 + 74e69fc commit 241dde8

7 files changed

Lines changed: 573 additions & 16 deletions

File tree

‎playwright.config.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const config: PlaywrightTestConfig = {
1313
webServer: {
1414
timeout: 120000,
1515
env: {
16-
PUBLIC_APPWRITE_ENDPOINT: 'https://stage.cloud.appwrite.io/v1',
16+
PUBLIC_APPWRITE_ENDPOINT: 'https://cloud.staging.appwrite.io/v1',
1717
PUBLIC_CONSOLE_MODE: 'cloud',
1818
PUBLIC_APPWRITE_MULTI_REGION: 'true',
1919
PUBLIC_STRIPE_KEY:

‎src/routes/(console)/organization-[organization]/billing/planSummary.svelte‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,9 @@
299299
// on the resource entry. Once the cloud rollout is complete this map can
300300
// be removed entirely.
301301
const billingAddonNamesFallback: Record<string, string> = {
302-
addon_baa: 'HIPAA BAA'
302+
addon_baa: 'HIPAA BAA',
303+
addon_premiumGeoDB: 'Premium Geo DB',
304+
addon_premiumGeoDBOrg: 'Premium Geo DB'
303305
};
304306
305307
const addons = (currentAggregation?.resources || [])
@@ -466,6 +468,21 @@
466468
priceFormatter: ({ amount }) => formatCurrency(amount),
467469
includeProgress: false
468470
}),
471+
...resources
472+
.filter((r) => r.resourceId?.startsWith('addon_') && (r.amount ?? 0) > 0)
473+
.map((addon) =>
474+
createRow({
475+
id: `addon-${addon.resourceId}`,
476+
label:
477+
addon.name ||
478+
billingAddonNamesFallback[addon.resourceId] ||
479+
addon.resourceId,
480+
resource: addon,
481+
usageFormatter: ({ value }) => formatNum(value),
482+
priceFormatter: ({ amount }) => formatCurrency(amount),
483+
includeProgress: false
484+
})
485+
),
469486
createRow({
470487
id: 'usage-details',
471488
label: `<a href="${base}/project-${String(projectData.region || 'default')}-${projectData.$id}/settings/usage" style="text-decoration: underline; color: var(--fgcolor-accent-neutral);">Usage details</a>`,

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818
import UpdateVariables from '../updateVariables.svelte';
1919
import { page } from '$app/state';
2020
import UpdateLabels from './updateLabels.svelte';
21+
import PremiumGeoDB from './premiumGeoDB.svelte';
2122
import UpdateOAuth2Server from './updateOAuth2Server.svelte';
23+
import { isCloud } from '$lib/system';
2224
import type { PageData } from './$types';
2325
import { Alert } from '@appwrite.io/pink-svelte';
2426
import { flags } from '$lib/flags';
@@ -104,6 +106,9 @@
104106
{/if}
105107
<UpdateServices />
106108
<UpdateInstallations {...data.installations} limit={data.limit} offset={data.offset} />
109+
{#if isCloud && $canWriteProjects}
110+
<PremiumGeoDB addons={data.addons} addonPrice={data.addonPrice} />
111+
{/if}
107112
<UpdateVariables
108113
{sdkCreateVariable}
109114
{sdkUpdateVariable}
Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
2+
import { isCloud } from '$lib/system';
23
import { sdk } from '$lib/stores/sdk';
3-
import { Query } from '@appwrite.io/console';
4+
import { Addon, Query } from '@appwrite.io/console';
45
import type { PageLoad } from './$types';
56

67
function isReadonlySettingsPermissionError(error: unknown): boolean {
@@ -11,26 +12,41 @@ function isReadonlySettingsPermissionError(error: unknown): boolean {
1112
export const load: PageLoad = async ({ depends, url, params }) => {
1213
depends(Dependencies.PROJECT_VARIABLES);
1314
depends(Dependencies.PROJECT_INSTALLATIONS);
15+
depends(Dependencies.ADDONS);
1416

1517
const limit = PAGE_LIMIT;
1618
const offset = Number(url.searchParams.get('offset') ?? 0);
1719
const variablesOffset = Number(url.searchParams.get('variablesOffset') ?? 0);
1820
const projectSdk = sdk.forProject(params.region, params.project);
19-
const [variablesResult, installationsResult] = await Promise.allSettled([
20-
projectSdk.projectApi.listVariables({
21-
queries: [Query.limit(limit), Query.offset(variablesOffset)]
22-
}),
23-
projectSdk.vcs.listInstallations({
24-
queries: [Query.limit(limit), Query.offset(offset)]
25-
})
26-
]);
21+
const [variablesResult, installationsResult, addonsResult, addonPriceResult] =
22+
await Promise.allSettled([
23+
projectSdk.projectApi.listVariables({
24+
queries: [Query.limit(limit), Query.offset(variablesOffset)]
25+
}),
26+
projectSdk.vcs.listInstallations({
27+
queries: [Query.limit(limit), Query.offset(offset)]
28+
}),
29+
isCloud
30+
? sdk
31+
.forConsoleIn(params.region)
32+
.projects.listAddons({ projectId: params.project })
33+
.catch(() => null)
34+
: Promise.resolve(null),
35+
isCloud
36+
? sdk
37+
.forConsoleIn(params.region)
38+
.projects.getAddonPrice({
39+
projectId: params.project,
40+
addon: Addon.Premiumgeodb
41+
})
42+
.catch(() => null)
43+
: Promise.resolve(null)
44+
]);
2745

2846
const variables =
2947
variablesResult.status === 'fulfilled'
3048
? variablesResult.value
3149
: (() => {
32-
// Read-only users can be blocked from write-adjacent settings APIs.
33-
// Only silence those permission errors so genuine load failures still surface.
3450
if (!isReadonlySettingsPermissionError(variablesResult.reason)) {
3551
throw variablesResult.reason;
3652
}
@@ -45,8 +61,6 @@ export const load: PageLoad = async ({ depends, url, params }) => {
4561
installationsResult.status === 'fulfilled'
4662
? installationsResult.value
4763
: (() => {
48-
// Read-only users can be blocked from write-adjacent settings APIs.
49-
// Only silence those permission errors so genuine load failures still surface.
5064
if (!isReadonlySettingsPermissionError(installationsResult.reason)) {
5165
throw installationsResult.reason;
5266
}
@@ -57,11 +71,16 @@ export const load: PageLoad = async ({ depends, url, params }) => {
5771
};
5872
})();
5973

74+
const addons = addonsResult.status === 'fulfilled' ? addonsResult.value : null;
75+
const addonPrice = addonPriceResult.status === 'fulfilled' ? addonPriceResult.value : null;
76+
6077
return {
6178
limit,
6279
offset,
6380
variablesOffset,
6481
variables,
65-
installations
82+
installations,
83+
addons,
84+
addonPrice
6685
};
6786
};

0 commit comments

Comments
 (0)