From 06dcdc4a1ba17f2033d660fb13e92fc1b08653fd Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 18 Jan 2026 12:10:33 +0530 Subject: [PATCH] update: address comments. --- src/lib/helpers/billing.ts | 16 ++++++++++++ src/lib/stores/billing.ts | 12 ++++----- src/routes/(console)/+layout.ts | 43 +++++++++++++++------------------ src/routes/+layout.ts | 27 +++++++++++++++++---- 4 files changed, 62 insertions(+), 36 deletions(-) create mode 100644 src/lib/helpers/billing.ts diff --git a/src/lib/helpers/billing.ts b/src/lib/helpers/billing.ts new file mode 100644 index 000000000..de3c2f538 --- /dev/null +++ b/src/lib/helpers/billing.ts @@ -0,0 +1,16 @@ +import type { Models } from '@appwrite.io/console'; + +export function makePlansMap( + plansArray: Models.BillingPlanList | null +): Map { + const plansMap = new Map(); + if (!plansArray?.plans.length) return plansMap; + + const plans = plansArray.plans; + for (let index = 0; index < plans.length; index++) { + const plan = plans[index]; + plansMap.set(plan.$id, plan); + } + + return plansMap; +} diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts index 61608aa3c..a7f425f8d 100644 --- a/src/lib/stores/billing.ts +++ b/src/lib/stores/billing.ts @@ -88,12 +88,8 @@ export function planHasGroup(billingPlanId: string, group: BillingPlanGroup) { export function getBasePlanFromGroup(billingPlanGroup: BillingPlanGroup): Models.BillingPlan { const plansInfoStore = get(plansInfo); - // hot fix for now, starter doesn't have a group atm. - const correctBillingPlanGroup = - billingPlanGroup === BillingPlanGroup.Starter ? null : billingPlanGroup; - const proPlans = Array.from(plansInfoStore.values()).filter( - (plan) => plan.group === correctBillingPlanGroup + (plan) => plan.group === billingPlanGroup ); return proPlans.sort((a, b) => a.order - b.order)[0]; @@ -530,12 +526,14 @@ export function checkForMarkedForDeletion(org: Models.Organization) { } export async function checkForMissingPaymentMethod() { + const starterPlan = getBasePlanFromGroup(BillingPlanGroup.Starter); + const orgs = await sdk.forConsole.organizations.list({ queries: [ - Query.notEqual('billingPlan', getBasePlanFromGroup(BillingPlanGroup.Starter).$id), Query.isNull('paymentMethodId'), Query.isNull('backupPaymentMethodId'), - Query.equal('platform', Platform.Appwrite) + Query.equal('platform', Platform.Appwrite), + Query.notEqual('billingPlan', starterPlan.$id) ] }); diff --git a/src/routes/(console)/+layout.ts b/src/routes/(console)/+layout.ts index 73f3acde0..15861da69 100644 --- a/src/routes/(console)/+layout.ts +++ b/src/routes/(console)/+layout.ts @@ -2,30 +2,38 @@ import { sdk } from '$lib/stores/sdk'; import { isCloud } from '$lib/system'; import type { LayoutLoad } from './$types'; import { Dependencies } from '$lib/constants'; -import { type Models, Platform, Query } from '@appwrite.io/console'; +import { Platform, Query } from '@appwrite.io/console'; +import { makePlansMap } from '$lib/helpers/billing'; export const load: LayoutLoad = async ({ depends, parent }) => { - const { organizations } = await parent(); + const { organizations, plansInfo } = await parent(); depends(Dependencies.RUNTIMES); depends(Dependencies.CONSOLE_VARIABLES); depends(Dependencies.ORGANIZATION); const { endpoint, project } = sdk.forConsole.client.config; + + const plansArrayPromise = + plansInfo || !isCloud + ? null + : sdk.forConsole.console.getPlans({ + platform: Platform.Appwrite + }); + const [preferences, plansArray, versionData, consoleVariables] = await Promise.all([ sdk.forConsole.account.getPrefs(), - isCloud - ? sdk.forConsole.console.getPlans({ - platform: Platform.Appwrite - }) - : null, + plansArrayPromise, fetch(`${endpoint}/health/version`, { headers: { 'X-Appwrite-Project': project as string } }).then((response) => response.json() as { version?: string }), sdk.forConsole.console.variables() ]); - const plansInfo = toPlanMap(plansArray); + let fallbackPlansInfoArray = plansInfo; + if (!fallbackPlansInfoArray) { + fallbackPlansInfoArray = makePlansMap(plansArray); + } const currentOrgId = preferences.organization ?? @@ -50,27 +58,14 @@ export const load: LayoutLoad = async ({ depends, parent }) => { } return { - plansInfo, roles: [], scopes: [], preferences, currentOrgId, organizations, consoleVariables, - version: versionData?.version ?? null, - allProjectsCount: projectsCount + allProjectsCount: projectsCount, + plansInfo: fallbackPlansInfoArray, + version: versionData?.version ?? null }; }; - -function toPlanMap(plansArray: Models.BillingPlanList | null): Map { - const map = new Map(); - if (!plansArray?.plans.length) return map; - - const plans = plansArray.plans; - for (let i = 0; i < plans.length; i++) { - const plan = plans[i]; - map.set(plan.$id, plan); - } - - return map; -} diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index a80e909b9..b78f25390 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -6,12 +6,13 @@ import { redirect } from '@sveltejs/kit'; import { Dependencies } from '$lib/constants'; import type { LayoutLoad } from './$types'; import { redirectTo } from './store'; -import { base, resolve } from '$app/paths'; +import { resolve } from '$app/paths'; import type { Account } from '$lib/stores/user'; -import { type AppwriteException } from '@appwrite.io/console'; +import { type AppwriteException, Platform } from '@appwrite.io/console'; import { isCloud, VARS } from '$lib/system'; import { checkPricingRefAndRedirect } from '$lib/helpers/pricingRedirect'; import { getTeamOrOrganizationList } from '$lib/stores/organization'; +import { makePlansMap } from '$lib/helpers/billing'; export const ssr = false; @@ -39,7 +40,10 @@ export const load: LayoutLoad = async ({ depends, url, route }) => { } } + const plansInfo = await getPlatformPlans(); + return { + plansInfo, account: account, organizations: await getTeamOrOrganizationList() }; @@ -51,11 +55,13 @@ export const load: LayoutLoad = async ({ depends, url, route }) => { } if (error.type === 'user_more_factors_required') { - if (url.pathname === `${base}/mfa`) + const mfaUrl = resolve('/(authenticated)/mfa'); + + if (url.pathname === mfaUrl) return { mfaRequired: true }; - redirect(303, withParams(`${base}/mfa`, url.searchParams)); + redirect(303, withParams(mfaUrl, url.searchParams)); } if (!isPublicRoute) { @@ -63,7 +69,8 @@ export const load: LayoutLoad = async ({ depends, url, route }) => { checkPricingRefAndRedirect(url.searchParams, true); } - redirect(303, withParams(`${base}/login`, url.searchParams)); + const loginUrl = resolve('/(public)/(guest)/login'); + redirect(303, withParams(loginUrl, url.searchParams)); } }; @@ -71,3 +78,13 @@ function withParams(pathname: string, searchParams: URLSearchParams) { if (searchParams.size > 0) return `${pathname}?${searchParams.toString()}`; return pathname; } + +async function getPlatformPlans() { + if (!isCloud) return null; + + const plansArray = await sdk.forConsole.console.getPlans({ + platform: Platform.Appwrite + }); + + return makePlansMap(plansArray); +}