Update console URL from pkg.pr.new to try-module.cloud and migrate billing API calls

This commit is contained in:
Torsten Dittmann
2025-05-20 00:42:56 +02:00
parent 7939bbc565
commit 3d85c759ec
78 changed files with 378 additions and 374 deletions
+1 -1
View File
@@ -22,7 +22,7 @@
},
"dependencies": {
"@ai-sdk/svelte": "^1.1.24",
"@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959",
"@appwrite.io/console": "https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7",
"@appwrite.io/pink": "0.25.0",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "^2.0.0-RC.1",
+5 -5
View File
@@ -12,8 +12,8 @@ importers:
specifier: ^1.1.24
version: 1.1.24(svelte@5.25.3)(zod@3.24.3)
'@appwrite.io/console':
specifier: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959
version: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959
specifier: https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7
version: https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7
'@appwrite.io/pink':
specifier: 0.25.0
version: 0.25.0
@@ -254,8 +254,8 @@ packages:
'@analytics/type-utils@0.6.2':
resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==}
'@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959':
resolution: {tarball: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959}
'@appwrite.io/console@https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7':
resolution: {tarball: https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7}
version: 1.5.2
'@appwrite.io/pink-icons-svelte@2.0.0-RC.1':
@@ -3615,7 +3615,7 @@ snapshots:
'@analytics/type-utils@0.6.2': {}
'@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959': {}
'@appwrite.io/console@https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7': {}
'@appwrite.io/pink-icons-svelte@2.0.0-RC.1(svelte@5.25.3)':
dependencies:
@@ -7,7 +7,7 @@ import { isCloud } from '$lib/system';
export const orgSearcher = (async (query: string) => {
const { teams } = !isCloud
? await sdk.forConsole.teams.list()
: await sdk.forConsole.billing.listOrganization();
: await sdk.forConsole.organizations.list();
return teams
.filter((organization) => organization.name.toLowerCase().includes(query.toLowerCase()))
@@ -8,8 +8,7 @@
import { confirmSetup } from '$lib/stores/stripe';
async function verifyPaymentMethod() {
const method = await sdk.forConsole.billing.setupPaymentMandate(
$organization.$id,
const method = await sdk.forConsole.account.updatePaymentMethodMandateOptions(
$paymentMissingMandate.$id
);
await confirmSetup(method.clientSecret, method.$id);
@@ -18,7 +18,7 @@
async function addCoupon() {
try {
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
const response = await sdk.forConsole.account.getCoupon(coupon);
couponData = response;
dispatch('validation', couponData);
coupon = null;
@@ -2,15 +2,16 @@
import { InputChoice, InputNumber } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import type { Coupon, PlansMap } from '$lib/sdk/billing';
import type { Coupon } from '$lib/sdk/billing';
import { type Tier } from '$lib/stores/billing';
import { Card, Divider, Layout, Typography } from '@appwrite.io/pink-svelte';
import { CreditsApplied } from '.';
import type { Models } from '@appwrite.io/console';
export let billingPlan: Tier;
export let collaborators: string[];
export let couponData: Partial<Coupon>;
export let plans: PlansMap;
export let plans: Map<Tier, Models.BillingPlan>;
export let billingBudget: number;
export let fixedCoupon = false; // If true, the coupon cannot be removed
export let isDowngrade = false;
@@ -29,9 +30,7 @@
? grossCost - couponData.credits
: 0
: grossCost;
$: trialEndDate = new Date(
billingPayDate.getTime() + currentPlan.trialDays * 24 * 60 * 60 * 1000
);
$: trialEndDate = new Date(billingPayDate.getTime() + currentPlan.trial * 24 * 60 * 60 * 1000);
</script>
<Card.Base padding="s">
@@ -54,7 +53,7 @@
<Layout.Stack direction="row" justifyContent="space-between">
<Typography.Text>
Upcoming charge<br />
Due on {!currentPlan.trialDays
Due on {!currentPlan.trial
? toLocaleDate(billingPayDate.toString())
: toLocaleDate(trialEndDate.toString())}</Typography.Text>
<Typography.Text>{formatCurrency(estimatedTotal)}</Typography.Text>
@@ -64,7 +63,7 @@
You'll pay <b>{formatCurrency(estimatedTotal)}</b> now, with your first billing cycle
starting on
<b
>{!currentPlan.trialDays
>{!currentPlan.trial
? toLocaleDate(billingPayDate.toString())
: toLocaleDate(trialEndDate.toString())}</b
>. {#if couponData?.status === 'active'}Once your credits run out, you'll be charged
@@ -1,12 +1,12 @@
<script lang="ts">
import { BillingPlan } from '$lib/constants';
import { formatNum } from '$lib/helpers/string';
import { plansInfo, tierFree, tierPro, tierScale, type Tier } from '$lib/stores/billing';
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
import { Card, Layout, Tabs, Typography } from '@appwrite.io/pink-svelte';
export let downgrade = false;
let selectedTab: Tier = BillingPlan.FREE;
let selectedTab: BillingPlan = BillingPlan.FREE;
$: plan = $plansInfo.get(selectedTab);
</script>
+5 -5
View File
@@ -1,18 +1,18 @@
<script lang="ts">
import { calculateExcess, plansInfo, tierToPlan, type Tier } from '$lib/stores/billing';
import { calculateExcess, plansInfo, tierToPlan } from '$lib/stores/billing';
import { organization } from '$lib/stores/organization';
import { toLocaleDate } from '$lib/helpers/date';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
import { abbreviateNumber } from '$lib/helpers/numbers';
import { formatNum } from '$lib/helpers/string';
import { onMount } from 'svelte';
import type { Aggregation } from '$lib/sdk/billing';
import { sdk } from '$lib/stores/sdk';
import { BillingPlan } from '$lib/constants';
import { Alert, Icon, Table, Tooltip } from '@appwrite.io/pink-svelte';
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
import type { Models } from '@appwrite.io/console';
export let tier: Tier;
export let tier: BillingPlan;
const plan = $plansInfo?.get(tier);
let excess: {
@@ -22,11 +22,11 @@
executions?: number;
members?: number;
} = null;
let aggregation: Aggregation = null;
let aggregation: Models.AggregationTeam = null;
let showExcess = false;
onMount(async () => {
aggregation = await sdk.forConsole.billing.getAggregation(
aggregation = await sdk.forConsole.organizations.getAggregation(
$organization.$id,
$organization.billingAggregationId
);
@@ -19,8 +19,7 @@
async function addCoupon() {
try {
// const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.billing.getCouponAccount(coupon); //TODO: double check that this is the correct method
const response = await sdk.forConsole.account.getCoupon(coupon);
if (response.onlyNewOrgs && !isNewOrg) {
show = false;
+3
View File
@@ -521,6 +521,9 @@ export const eventServices: Array<EventService> = [
];
export enum BillingPlan {
Tier0 = 'tier-0',
Tier1 = 'tier-1',
Tier2 = 'tier-2',
FREE = 'tier-0',
PRO = 'tier-1',
SCALE = 'tier-2',
+4 -6
View File
@@ -5,22 +5,20 @@
import AppwriteLogoLight from '$lib/images/appwrite-logo-light.svg';
import LoginDark from '$lib/images/login/login-dark-mode.png';
import LoginLight from '$lib/images/login/login-light-mode.png';
import type { Coupon } from '$lib/sdk/billing';
import { app } from '$lib/stores/app';
import type { Campaign } from '$lib/stores/campaigns';
import { Typography, Layout, Avatar } from '@appwrite.io/pink-svelte';
import { getCampaignImageUrl } from '$routes/(public)/card/helpers';
import type { Models } from '@appwrite.io/console';
export const imgLight = LoginLight;
export const imgDark = LoginDark;
export let campaign: Campaign = null;
export let coupon: Coupon = null;
export let campaign: Models.Campaign = null;
export let coupon: Models.Coupon = null;
export let align: 'start' | 'center' | 'end' = 'start';
$: variation = ((coupon?.campaign ?? campaign) ? campaign?.template : 'default') as
| 'default'
| Campaign['template'];
| Models.Campaign['template'];
let currentReviewNumber = 0;
$: currentReview = campaign?.reviews?.[currentReviewNumber];
+6 -2
View File
@@ -3,6 +3,7 @@ import type { Campaign } from '$lib/stores/campaigns';
import type { Client, Models } from '@appwrite.io/console';
import type { PaymentMethod } from '@stripe/stripe-js';
import type { Organization, OrganizationError, OrganizationList } from '../stores/organization';
import type { BillingPlan } from '$lib/constants';
export type PaymentMethodData = {
$id: string;
@@ -345,7 +346,7 @@ export type PlanList = {
total: number;
};
export type PlansMap = Map<Tier, Plan>;
export type PlansMap = Map<BillingPlan, Models.BillingPlan>;
export type Roles = {
scopes: string[];
@@ -375,7 +376,10 @@ export class Billing {
);
}
async validateOrganization(organizationId: string, invites: string[]): Promise<Organization> {
async validateOrganization(
organizationId: string,
invites: string[]
): Promise<Models.Organization<Record<string, unknown>>> {
const path = `/organizations/${organizationId}/validate`;
const params = {
organizationId,
+53 -50
View File
@@ -12,19 +12,10 @@ import PaymentMandate from '$lib/components/billing/alerts/paymentMandate.svelte
import { BillingPlan, NEW_DEV_PRO_UPGRADE_COUPON } from '$lib/constants';
import { cachedStore } from '$lib/helpers/cache';
import { sizeToBytes, type Size } from '$lib/helpers/sizeConvertion';
import type {
AddressesList,
Aggregation,
Invoice,
InvoiceList,
PaymentList,
PaymentMethodData,
Plan,
PlansMap
} from '$lib/sdk/billing';
import type { AddressesList, PaymentList, PaymentMethodData, PlansMap } from '$lib/sdk/billing';
import { isCloud } from '$lib/system';
import { activeHeaderAlert, orgMissingPaymentMethod } from '$routes/(console)/store';
import { Query } from '@appwrite.io/console';
import { Query, type Models } from '@appwrite.io/console';
import { derived, get, writable } from 'svelte/store';
import { headerAlert } from './headerAlert';
import { addNotification, notifications } from './notifications';
@@ -78,13 +69,13 @@ export function getRoleLabel(role: string) {
return roles.find((r) => r.value === role)?.label ?? role;
}
export function tierToPlan(tier: Tier) {
export function tierToPlan(tier: string) {
switch (tier) {
case BillingPlan.FREE:
case BillingPlan.Tier0:
return tierFree;
case BillingPlan.PRO:
case BillingPlan.Tier1:
return tierPro;
case BillingPlan.SCALE:
case BillingPlan.Tier2:
return tierScale;
case BillingPlan.GITHUB_EDUCATION:
return tierGitHubEducation;
@@ -99,23 +90,23 @@ export function tierToPlan(tier: Tier) {
export function getNextTier(tier: Tier) {
switch (tier) {
case BillingPlan.FREE:
return BillingPlan.PRO;
case BillingPlan.PRO:
return BillingPlan.SCALE;
case BillingPlan.Tier0:
return BillingPlan.Tier1;
case BillingPlan.Tier1:
return BillingPlan.Tier2;
default:
return BillingPlan.PRO;
return BillingPlan.Tier1;
}
}
export function getPreviousTier(tier: Tier) {
switch (tier) {
case BillingPlan.PRO:
return BillingPlan.FREE;
case BillingPlan.SCALE:
return BillingPlan.PRO;
case BillingPlan.Tier1:
return BillingPlan.Tier0;
case BillingPlan.Tier2:
return BillingPlan.Tier1;
default:
return BillingPlan.FREE;
return BillingPlan.Tier0;
}
}
@@ -144,12 +135,16 @@ export type PlanServices =
| 'authPhone'
| 'imageTransformations';
export function getServiceLimit(serviceId: PlanServices, tier: Tier = null, plan?: Plan): number {
export function getServiceLimit(
serviceId: PlanServices,
tier: BillingPlan = null,
plan?: Models.BillingPlan
): number {
if (!isCloud) return 0;
if (!serviceId) return 0;
const info = get(plansInfo);
if (!info) return 0;
plan ??= info.get(tier ?? get(organization)?.billingPlan);
plan ??= info.get(tier ?? (get(organization)?.billingPlan as unknown as BillingPlan));
// members are no longer a variable on plan itself!
// the correct info for members/seats, resides in `addons`.
// plan > addons > seats/others
@@ -162,7 +157,7 @@ export function getServiceLimit(serviceId: PlanServices, tier: Tier = null, plan
}
export const failedInvoice = cachedStore<
Invoice,
Models.Invoice,
{
load: (orgId: string) => Promise<void>;
}
@@ -171,7 +166,7 @@ export const failedInvoice = cachedStore<
load: async (orgId) => {
if (!isCloud) set(null);
if (!get(canSeeBilling)) set(null);
const failedInvoices = await sdk.forConsole.billing.listInvoices(orgId, [
const failedInvoices = await sdk.forConsole.organizations.listInvoices(orgId, [
Query.equal('status', 'failed')
]);
// const failedInvoices = invoices.invoices;
@@ -188,7 +183,7 @@ export const failedInvoice = cachedStore<
};
});
export const actionRequiredInvoices = writable<InvoiceList>(null);
export const actionRequiredInvoices = writable<Models.InvoiceList>(null);
export type TierData = {
name: string;
@@ -229,7 +224,7 @@ export const tierEnterprise: TierData = {
export const showUsageRatesModal = writable<boolean>(false);
export function checkForUsageFees(plan: Tier, id: PlanServices) {
if (plan === BillingPlan.PRO || plan === BillingPlan.SCALE) {
if (plan === BillingPlan.Tier2 || plan === BillingPlan.Tier1) {
switch (id) {
case 'bandwidth':
case 'storage':
@@ -260,7 +255,7 @@ export function checkForProjectLimitation(id: PlanServices) {
}
}
export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: number) {
export function isServiceLimited(serviceId: PlanServices, plan: BillingPlan, total: number) {
if (!total) return false;
const limit = getServiceLimit(serviceId) || Infinity;
const isLimited = limit !== 0 && limit < Infinity;
@@ -269,7 +264,7 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num
}
export function calculateTrialDay(org: Organization) {
if (org?.billingPlan === BillingPlan.FREE) return false;
if (org?.billingPlan === BillingPlan.Tier0) return false;
const endDate = new Date(org?.billingStartDate);
const today = new Date();
@@ -297,7 +292,7 @@ export async function checkForUsageLimit(org: Organization) {
readOnly.set(false);
return;
}
if (org?.billingPlan !== BillingPlan.FREE) {
if (org?.billingPlan !== BillingPlan.Tier0) {
const { budgetLimit } = org?.billingLimits ?? {};
if (budgetLimit && budgetLimit >= 100) {
@@ -323,7 +318,7 @@ export async function checkForUsageLimit(org: Organization) {
];
const members = org.total;
const plan = get(plansInfo)?.get(org.billingPlan);
const plan = get(plansInfo)?.get(org.billingPlan as BillingPlan);
const membersOverflow =
members > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0;
@@ -342,9 +337,9 @@ export async function checkForUsageLimit(org: Organization) {
if (now - lastNotification < 1000 * 60 * 60 * 24) return;
localStorage.setItem('limitReachedNotification', now.toString());
let message = `<b>${org.name}</b> has reached <b>75%</b> of the ${tierToPlan(BillingPlan.FREE).name} plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
let message = `<b>${org.name}</b> has reached <b>75%</b> of the ${tierToPlan(BillingPlan.Tier0).name} plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
if (resources.filter((r) => r.value >= 75)?.length > 1) {
message = `Usage for <b>${org.name}</b> has reached 75% of the ${tierToPlan(BillingPlan.FREE).name} plan limit. Upgrade to ensure there are no service disruptions.`;
message = `Usage for <b>${org.name}</b> has reached 75% of the ${tierToPlan(BillingPlan.Tier0).name} plan limit. Upgrade to ensure there are no service disruptions.`;
}
addNotification({
type: 'warning',
@@ -376,9 +371,9 @@ export async function checkForUsageLimit(org: Organization) {
}
export async function checkPaymentAuthorizationRequired(org: Organization) {
if (org.billingPlan === BillingPlan.FREE) return;
if (org.billingPlan === BillingPlan.Tier0) return;
const invoices = await sdk.forConsole.billing.listInvoices(org.$id, [
const invoices = await sdk.forConsole.organizations.listInvoices(org.$id, [
Query.equal('status', 'requires_authentication')
]);
@@ -397,7 +392,7 @@ export async function checkPaymentAuthorizationRequired(org: Organization) {
export async function paymentExpired(org: Organization) {
if (!org?.paymentMethodId) return;
const payment = await sdk.forConsole.billing.getOrganizationPaymentMethod(
const payment = await sdk.forConsole.organizations.getPaymentMethod(
org.$id,
org.paymentMethodId
);
@@ -460,7 +455,7 @@ export const paymentMissingMandate = writable<PaymentMethodData>(null);
export async function checkForMandate(org: Organization) {
const paymentId = org.paymentMethodId ?? org.backupPaymentMethodId;
if (!paymentId) return;
const paymentMethod = await sdk.forConsole.billing.getPaymentMethod(paymentId);
const paymentMethod = await sdk.forConsole.account.getPaymentMethod(paymentId);
if (paymentMethod?.mandateId === null && paymentMethod?.country.toLowerCase() === 'in') {
headerAlert.add({
id: 'paymentMandate',
@@ -474,8 +469,8 @@ export async function checkForMandate(org: Organization) {
}
export async function checkForMissingPaymentMethod() {
const orgs = await sdk.forConsole.billing.listOrganization([
Query.notEqual('billingPlan', BillingPlan.FREE),
const orgs = await sdk.forConsole.organizations.list([
Query.notEqual('billingPlan', BillingPlan.Tier0),
Query.isNull('paymentMethodId'),
Query.isNull('backupPaymentMethodId')
]);
@@ -492,10 +487,10 @@ export async function checkForMissingPaymentMethod() {
// Display upgrade banner for new users after 1 week for 30 days
export async function checkForNewDevUpgradePro(org: Organization) {
if (org?.billingPlan !== BillingPlan.FREE || !browser) return;
if (org?.billingPlan !== BillingPlan.Tier0 || !browser) return;
const orgs = await sdk.forConsole.billing.listOrganization([
Query.notEqual('billingPlan', BillingPlan.FREE)
const orgs = await sdk.forConsole.organizations.list([
Query.notEqual('billingPlan', BillingPlan.Tier0)
]);
if (orgs?.total) return;
@@ -507,7 +502,7 @@ export async function checkForNewDevUpgradePro(org: Organization) {
if (isDismissed) return;
// check if coupon already applied
try {
await sdk.forConsole.billing.getCouponAccount(NEW_DEV_PRO_UPGRADE_COUPON);
await sdk.forConsole.account.getCoupon(NEW_DEV_PRO_UPGRADE_COUPON);
} catch (e) {
return;
}
@@ -529,7 +524,7 @@ export const billingURL = derived(
export const hideBillingHeaderRoutes = ['/console/create-organization', '/console/account'];
export function calculateExcess(addon: Aggregation, plan: Plan) {
export function calculateExcess(addon: Models.AggregationTeam, plan: Models.BillingPlan) {
return {
bandwidth: calculateResourceSurplus(addon.usageBandwidth, plan.bandwidth),
storage: calculateResourceSurplus(addon.usageStorage, plan.storage, 'GB'),
@@ -544,6 +539,14 @@ export function calculateResourceSurplus(total: number, limit: number, limitUnit
return total > realLimit ? total - realLimit : 0;
}
export function isOrganization(org: Organization | OrganizationError): org is Organization {
return (org as Organization).$id !== undefined;
export function isOrganization(
org: Models.Organization<Record<string, unknown>> | OrganizationError
): org is Models.Organization<Record<string, unknown>> {
return '$id' in org && org.$id !== undefined;
}
export function isOrganizationError(
org: Models.Organization<Record<string, unknown>> | OrganizationError
): org is OrganizationError {
return !('$id' in org);
}
+1 -1
View File
@@ -1,4 +1,4 @@
import type { BillingPlan } from '$lib/constants';
import type { BillingPlan } from '@appwrite.io/console';
export type Campaign = {
$id: string;
+5 -25
View File
@@ -1,8 +1,7 @@
import { page } from '$app/stores';
import { derived, writable } from 'svelte/store';
import type { Models } from '@appwrite.io/console';
import type { Tier } from './billing';
import type { Plan } from '$lib/sdk/billing';
import type { BillingPlan } from '$lib/constants';
export type OrganizationError = {
status: number;
@@ -13,27 +12,8 @@ export type OrganizationError = {
type: string;
};
export type Organization = Models.Team<Record<string, unknown>> & {
billingBudget: number;
billingPlan: Tier;
budgetAlerts: number[];
paymentMethodId: string;
backupPaymentMethodId: string;
markedForDeletion: boolean;
billingLimits: BillingLimits;
billingCurrentInvoiceDate: string;
billingNextInvoiceDate: string;
billingTrialStartDate?: string;
billingStartDate?: string;
billingTrialDays?: number;
billingAddressId?: string;
amount: number;
billingTaxId?: string;
billingPlanDowngrade?: Tier;
billingAggregationId: string;
billingInvoiceId: string;
status: string;
remarks: string;
export type Organization = Omit<Models.Organization<Record<string, unknown>>, 'billingPlan'> & {
billingPlan: BillingPlan;
};
export type OrganizationList = {
@@ -54,11 +34,11 @@ export const newOrgModal = writable<boolean>(false);
export const newMemberModal = writable<boolean>(false);
export const organizationList = derived(
page,
($page) => $page.data.organizations as Models.TeamList<Record<string, unknown>>
($page) => $page.data.organizations as Models.OrganizationList<Record<string, unknown>>
);
export const organization = derived(page, ($page) => $page.data?.organization as Organization);
export const currentPlan = derived(page, ($page) => $page.data?.currentPlan as Plan);
export const currentPlan = derived(page, ($page) => $page.data?.currentPlan as Models.BillingPlan);
export const members = derived(page, ($page) => $page.data.members as Models.MembershipList);
export const regions = writable<Models.ConsoleRegionList | undefined>(undefined);
+3 -1
View File
@@ -20,7 +20,8 @@ import {
Users,
Vcs,
Sites,
Tokens
Tokens,
Organizations
} from '@appwrite.io/console';
import { Billing } from '../sdk/billing';
import { Backups } from '../sdk/backups';
@@ -121,6 +122,7 @@ export const sdk = {
teams: new Teams(clientConsole),
users: new Users(clientConsole),
migrations: new Migrations(clientConsole),
organizations: new Organizations(clientConsole),
console: new Console(clientConsole),
assistant: new Assistant(clientConsole),
billing: new Billing(clientConsole),
+6 -6
View File
@@ -21,7 +21,7 @@ export async function initializeStripe(node: HTMLElement) {
if (!get(stripe)) return;
isStripeInitialized.set(true);
const methods = await sdk.forConsole.billing.listPaymentMethods();
const methods = await sdk.forConsole.account.listPaymentMethods();
// Get the client secret from empty payment method if available
clientSecret = methods.paymentMethods?.filter(
@@ -30,7 +30,7 @@ export async function initializeStripe(node: HTMLElement) {
// If there is no payment method, create an empty one and get the client secret
if (!clientSecret) {
paymentMethod = await sdk.forConsole.billing.createPaymentMethod();
paymentMethod = await sdk.forConsole.account.createPaymentMethod();
clientSecret = paymentMethod.clientSecret;
}
@@ -57,7 +57,7 @@ export async function submitStripeCard(name: string, organizationId?: string) {
try {
// If a payment method was created during initialization, use it, otherwise create a new one
if (!paymentMethod) {
paymentMethod = await sdk.forConsole.billing.createPaymentMethod();
paymentMethod = await sdk.forConsole.account.createPaymentMethod();
clientSecret = paymentMethod.clientSecret;
}
@@ -94,9 +94,9 @@ export async function submitStripeCard(name: string, organizationId?: string) {
}
if (setupIntent && setupIntent.status === 'succeeded') {
const method = await sdk.forConsole.billing.setPaymentMethod(
const method = await sdk.forConsole.account.updatePaymentMethodProvider(
paymentMethod.$id,
setupIntent.payment_method,
setupIntent.payment_method.toString(),
name
);
paymentElement.destroy();
@@ -124,7 +124,7 @@ export async function confirmPayment(
const url =
window.location.origin + (route ? route : `${base}/organization-${orgId}/billing`);
const paymentMethod = await sdk.forConsole.billing.getPaymentMethod(paymentMethodId);
const paymentMethod = await sdk.forConsole.account.getPaymentMethod(paymentMethodId);
const { error } = await get(stripe).confirmPayment({
clientSecret: clientSecret,
+1 -1
View File
@@ -310,7 +310,7 @@
await checkPaymentAuthorizationRequired(org);
await checkForMandate(org);
if ($plansInfo.get(org.billingPlan)?.trialDays) {
if ($plansInfo.get(org.billingPlan)?.trial) {
calculateTrialDay(org);
}
}
+5 -6
View File
@@ -1,10 +1,9 @@
import { Dependencies } from '$lib/constants';
import type { Plan } from '$lib/sdk/billing';
import type { Tier } from '$lib/stores/billing';
import { sdk } from '$lib/stores/sdk';
import { isCloud } from '$lib/system';
import type { LayoutLoad } from './$types';
import { Query } from '@appwrite.io/console';
import { Query, type Models } from '@appwrite.io/console';
export const load: LayoutLoad = async ({ params, fetch, depends, parent }) => {
await parent();
@@ -25,18 +24,18 @@ export const load: LayoutLoad = async ({ params, fetch, depends, parent }) => {
const [data, variables] = await Promise.all([versionPromise, variablesPromise]);
let plansInfo = new Map<Tier, Plan>();
let plansInfo = new Map<Tier, Models.BillingPlan>();
if (isCloud) {
const plansArray = await sdk.forConsole.billing.getPlansInfo();
const plansArray = await sdk.forConsole.console.plans();
plansInfo = plansArray.plans.reduce((map, plan) => {
map.set(plan.$id as Tier, plan);
return map;
}, new Map<Tier, Plan>());
}, new Map<Tier, Models.BillingPlan>());
}
const organizations = !isCloud
? await sdk.forConsole.teams.list()
: await sdk.forConsole.billing.listOrganization();
: await sdk.forConsole.organizations.list();
let projects = [];
let currentOrgId = params.organization ? params.organization : prefs.organization;
@@ -82,7 +82,7 @@
>You are limited to 1 free organization per account</span>
</Tooltip>
{/if}
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.FREE && $plansInfo.get(organization.billingPlan)?.trialDays}
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.FREE && $plansInfo.get(organization.billingPlan)?.trial}
<Tooltip>
<div class="u-flex u-cross-center">
<Pill class="eyebrow-heading-3">TRIAL</Pill>
@@ -14,7 +14,7 @@ export const load: PageLoad = async ({ url, route }) => {
const organizations = !isCloud
? await sdk.forConsole.teams.list(queries)
: await sdk.forConsole.billing.listOrganization(queries);
: await sdk.forConsole.organizations.list(queries);
return {
offset,
@@ -7,8 +7,8 @@ export const load: PageLoad = async ({ depends }) => {
depends(Dependencies.ADDRESS);
const [paymentMethods, addressList] = await Promise.all([
sdk.forConsole.billing.listPaymentMethods(),
sdk.forConsole.billing.listAddresses()
sdk.forConsole.account.listPaymentMethods(),
sdk.forConsole.account.listBillingAddresses()
]);
return {
paymentMethods,
@@ -6,8 +6,8 @@
import { Dependencies } from '$lib/constants';
import { Button, InputSelect, InputText } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import type { Organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import type { Models } from '@appwrite.io/console';
import { onMount } from 'svelte';
export let show = false;
@@ -45,7 +45,7 @@
async function handleSubmit() {
try {
const response = await sdk.forConsole.billing.createAddress(
const response = await sdk.forConsole.account.createBillingAddress(
country,
address,
city,
@@ -54,9 +54,12 @@
address2 ? address2 : undefined
);
trackEvent(Submit.BillingAddressCreate);
let org: Organization = null;
let org: Models.Organization<Record<string, unknown>> = null;
if (organization) {
org = await sdk.forConsole.billing.setBillingAddress(organization, response.$id);
org = await sdk.forConsole.organizations.setBillingAddress(
organization,
response.$id
);
trackEvent(Submit.OrganizationBillingAddressUpdate);
await invalidate(Dependencies.ORGANIZATION);
}
@@ -17,7 +17,7 @@
async function handleDelete() {
try {
await sdk.forConsole.billing.deleteAddress(selectedAddress.$id);
await sdk.forConsole.account.deleteBillingAddress(selectedAddress.$id);
await invalidate(Dependencies.PAYMENT_METHODS);
showDelete = false;
addNotification({
@@ -17,7 +17,7 @@
async function handleDelete() {
try {
await sdk.forConsole.billing.deletePaymentMethod(method);
await sdk.forConsole.account.deletePaymentMethod(method);
await invalidate(Dependencies.PAYMENT_METHODS);
showDelete = false;
addNotification({
@@ -35,7 +35,7 @@
async function handleSubmit() {
try {
await sdk.forConsole.billing.updateAddress(
await sdk.forConsole.account.updateBillingAddress(
selectedAddress.$id,
selectedAddress.country,
selectedAddress.streetAddress,
@@ -14,15 +14,15 @@
export let isLinked = false;
const currentYear = new Date().getFullYear();
let error: string;
let month: string;
let month: number;
let year: number;
async function handleSubmit() {
try {
await sdk.forConsole.billing.updatePaymentMethod(
await sdk.forConsole.account.updatePaymentMethod(
selectedPaymentMethod.$id,
month,
year?.toString()
year
);
trackEvent(Submit.PaymentMethodUpdate);
invalidate(Dependencies.PAYMENT_METHODS);
@@ -39,23 +39,23 @@
function createMonthOptions(year: number) {
const months = [
{ value: '01', label: '01' },
{ value: '02', label: '02' },
{ value: '03', label: '03' },
{ value: '04', label: '04' },
{ value: '05', label: '05' },
{ value: '06', label: '06' },
{ value: '07', label: '07' },
{ value: '08', label: '08' },
{ value: '09', label: '09' },
{ value: '10', label: '10' },
{ value: '11', label: '11' },
{ value: '12', label: '12' }
{ value: 1, label: '01' },
{ value: 2, label: '02' },
{ value: 3, label: '03' },
{ value: 4, label: '04' },
{ value: 5, label: '05' },
{ value: 6, label: '06' },
{ value: 7, label: '07' },
{ value: 8, label: '08' },
{ value: 9, label: '09' },
{ value: 10, label: '10' },
{ value: 11, label: '11' },
{ value: 12, label: '12' }
];
if (!year) return months;
if (year === currentYear) {
const currentMonth = new Date().getMonth() + 1;
return months.filter((option) => parseInt(option.value) >= currentMonth);
return months.filter((option) => option.value >= currentMonth);
} else {
return months;
}
+33 -37
View File
@@ -4,23 +4,19 @@
import { page } from '$app/state';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { CreditsApplied, SelectPaymentMethod } from '$lib/components/billing';
import { BillingPlan, Dependencies } from '$lib/constants';
import { Dependencies } from '$lib/constants';
import { Button, Form, InputSelect, InputTags, InputText } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { Wizard } from '$lib/layout';
import { type PaymentList, type Plan } from '$lib/sdk/billing';
import { type PaymentList } from '$lib/sdk/billing';
import { addNotification } from '$lib/stores/notifications';
import {
organizationList,
type Organization,
type OrganizationError
} from '$lib/stores/organization';
import { organizationList, type OrganizationError } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { confirmPayment } from '$lib/stores/stripe.js';
import { ID } from '@appwrite.io/console';
import { BillingPlan, ID, type Models } from '@appwrite.io/console';
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import { isOrganization, plansInfo, type Tier } from '$lib/stores/billing';
import { isOrganization, isOrganizationError, plansInfo } from '$lib/stores/billing';
import { Fieldset, Icon, Layout, Tooltip } from '@appwrite.io/pink-svelte';
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
import EstimatedTotalBox from '$lib/components/billing/estimatedTotalBox.svelte';
@@ -68,9 +64,9 @@
let coupon: string;
let couponData = data?.couponData;
let campaign = data?.campaign;
let billingPlan: Tier = BillingPlan.PRO;
let billingPlan: BillingPlan = BillingPlan.Tier1;
let tempOrgId = null;
let currentPlan: Plan;
let currentPlan: Models.BillingPlan;
$: onlyNewOrgs = (campaign && campaign.onlyNewOrgs) || (couponData && couponData.onlyNewOrgs);
@@ -91,7 +87,7 @@
canSelectOrg = false;
}
if (campaign?.plan) {
billingPlan = campaign.plan;
billingPlan = campaign.plan as BillingPlan;
}
if ($organizationList.total > 0 && tempOrgId === null) {
@@ -113,7 +109,7 @@
});
async function loadPaymentMethods() {
const methodList = await sdk.forConsole.billing.listPaymentMethods();
const methodList = await sdk.forConsole.account.listPaymentMethods();
const filteredMethods = methodList.paymentMethods.filter((method) => !!method?.last4);
methods = { paymentMethods: filteredMethods, total: filteredMethods.length };
paymentMethodId =
@@ -126,40 +122,40 @@
if (!couponForm.checkValidity()) return;
isSubmitting.set(true);
try {
let org: Organization | OrganizationError;
let org: Models.Organization<Record<string, unknown>> | OrganizationError;
// Create new org
if (selectedOrgId === newOrgId) {
org = await sdk.forConsole.billing.createOrganization(
org = await sdk.forConsole.organizations.create(
newOrgId,
name,
billingPlan,
paymentMethodId,
null,
couponData.code ? couponData.code : null,
collaborators,
billingBudget,
taxId
couponData.code ? couponData.code : null,
taxId,
billingBudget
);
}
// Upgrade existing org
else if (selectedOrg?.billingPlan !== billingPlan && isUpgrade()) {
org = await sdk.forConsole.billing.updatePlan(
org = await sdk.forConsole.organizations.updatePlan(
selectedOrg.$id,
billingPlan,
paymentMethodId,
null,
couponData.code ? couponData.code : null,
collaborators
collaborators,
couponData.code ? couponData.code : null
);
}
// Existing pro org, apply credits
else {
org = selectedOrg;
await sdk.forConsole.billing.addCredit(org.$id, couponData.code);
await sdk.forConsole.organizations.addCredit(org.$id, couponData.code);
}
if (!isOrganization(org) && org.status === 402) {
if (isOrganizationError(org) && org.status === 402) {
let clientSecret = org.clientSecret;
let params = new URLSearchParams();
params.append('type', 'payment_confirmed');
@@ -205,7 +201,7 @@
async function addCoupon() {
try {
const response = await sdk.forConsole.billing.getCoupon(coupon);
const response = await sdk.forConsole.console.getCoupon(coupon);
couponData = response;
coupon = null;
addNotification({
@@ -220,23 +216,23 @@
}
}
$: selectedOrg = $organizationList?.teams?.find(
(team) => team.$id === selectedOrgId
) as Organization;
$: selectedOrg = $organizationList?.teams?.find((team) => team.$id === selectedOrgId);
function getBillingPlan(): Tier | undefined {
const campaignPlan =
campaign?.plan && $plansInfo.get(campaign.plan) ? $plansInfo.get(campaign.plan) : null;
function getBillingPlan(): BillingPlan | undefined {
const plan = campaign.plan as BillingPlan;
const campaignPlan = campaign?.plan && $plansInfo.get(plan) ? $plansInfo.get(plan) : null;
const orgPlan =
selectedOrg?.billingPlan && $plansInfo.get(selectedOrg.billingPlan)
? $plansInfo.get(selectedOrg.billingPlan)
selectedOrg?.billingPlan && $plansInfo.get(selectedOrg.billingPlan as BillingPlan)
? $plansInfo.get(selectedOrg.billingPlan as BillingPlan)
: null;
if (!campaignPlan || !orgPlan) {
return;
}
return campaignPlan.order > orgPlan.order ? campaign.plan : selectedOrg?.billingPlan;
return campaignPlan.order > orgPlan.order
? plan
: (selectedOrg?.billingPlan as BillingPlan);
}
$: if (selectedOrg) {
@@ -246,7 +242,7 @@
$: {
if (selectedOrgId) {
(async () => {
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(selectedOrgId);
currentPlan = await sdk.forConsole.organizations.getPlan(selectedOrgId);
})();
}
}
@@ -271,7 +267,7 @@
placeholder="Select organization"
id="organization" />
{/if}
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.PRO || !selectedOrg?.paymentMethodId)}
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.Tier1 || !selectedOrg?.paymentMethodId)}
{#if selectedOrgId === newOrgId}
<InputText
label="Organization name"
@@ -297,10 +293,10 @@
{/if}
</Layout.Stack>
</Fieldset>
{#if (selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.PRO || !selectedOrg?.paymentMethodId)) || (!data?.couponData?.code && selectedOrgId)}
{#if (selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.Tier1 || !selectedOrg?.paymentMethodId)) || (!data?.couponData?.code && selectedOrgId)}
<Fieldset legend="Payment">
<Layout.Stack gap="xl">
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.PRO || !selectedOrg?.paymentMethodId)}
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.Tier1 || !selectedOrg?.paymentMethodId)}
<SelectPaymentMethod
bind:methods
bind:value={paymentMethodId}
+6 -6
View File
@@ -1,19 +1,19 @@
import { base } from '$app/paths';
import type { Coupon } from '$lib/sdk/billing.js';
import type { Campaign } from '$lib/stores/campaigns.js';
import { sdk } from '$lib/stores/sdk.js';
import type { Models } from '@appwrite.io/console';
import { redirect } from '@sveltejs/kit';
export const load = async ({ url }) => {
// Has promo code
if (url.searchParams.has('code')) {
let couponData: Coupon;
let campaign: Campaign;
let campaign: Models.Campaign;
const code = url.searchParams.get('code');
try {
couponData = await sdk.forConsole.billing.getCouponAccount(code);
couponData = await sdk.forConsole.account.getCoupon(code);
if (couponData.campaign) {
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
campaign = await sdk.forConsole.console.getCampaign(couponData.campaign);
}
return { couponData, campaign };
} catch (e) {
@@ -23,9 +23,9 @@ export const load = async ({ url }) => {
// Has campaign
else if (url.searchParams.has('campaign')) {
const campaignId = url.searchParams.get('campaign');
let campaign: Campaign;
let campaign: Models.Campaign;
try {
campaign = await sdk.forConsole.billing.getCampaign(campaignId);
campaign = await sdk.forConsole.console.getCampaign(campaignId);
return { campaign };
} catch (e) {
redirect(303, base);
@@ -5,16 +5,16 @@
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { PlanComparisonBox, PlanSelection, SelectPaymentMethod } from '$lib/components/billing';
import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte';
import { BillingPlan, Dependencies } from '$lib/constants';
import { Dependencies } from '$lib/constants';
import { Button, Form, InputTags, InputText } from '$lib/elements/forms';
import { Wizard } from '$lib/layout';
import type { Coupon } from '$lib/sdk/billing';
import { isOrganization, tierToPlan } from '$lib/stores/billing';
import { isOrganization, isOrganizationError, tierToPlan } from '$lib/stores/billing';
import { addNotification } from '$lib/stores/notifications';
import { type OrganizationError, type Organization } from '$lib/stores/organization';
import { type OrganizationError } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { confirmPayment } from '$lib/stores/stripe';
import { ID } from '@appwrite.io/console';
import { BillingPlan, ID, type Models } from '@appwrite.io/console';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { Divider, Fieldset, Icon, Layout, Link, Typography } from '@appwrite.io/pink-svelte';
import { writable } from 'svelte/store';
@@ -23,7 +23,7 @@
export let data;
let selectedPlan: BillingPlan = data.plan as BillingPlan;
let selectedPlan: BillingPlan = data.plan;
let selectedCoupon: Partial<Coupon> | null = data.coupon;
let previousPage: string = base;
let showExitModal = false;
@@ -32,7 +32,7 @@
let isSubmitting = writable(false);
let name: string;
let billingPlan: BillingPlan = BillingPlan.FREE;
let billingPlan: BillingPlan = BillingPlan.Tier0;
let paymentMethodId: string;
let collaborators: string[] = [];
let couponData: Partial<Coupon> = {
@@ -53,7 +53,7 @@
if (page.url.searchParams.has('coupon')) {
const coupon = page.url.searchParams.get('coupon');
try {
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
const response = await sdk.forConsole.account.getCoupon(coupon);
couponData = response;
} catch (e) {
couponData = {
@@ -76,7 +76,7 @@
data?.hasFreeOrganizations ||
(page.url.searchParams.has('type') && page.url.searchParams.get('type') === 'createPro')
) {
billingPlan = BillingPlan.PRO;
billingPlan = BillingPlan.Tier1;
}
if (page.url.searchParams.has('type')) {
const type = page.url.searchParams.get('type');
@@ -110,32 +110,26 @@
async function create() {
try {
let org: Organization | OrganizationError;
let org: Models.Organization<Record<string, unknown>> | OrganizationError;
if (selectedPlan === BillingPlan.FREE) {
org = await sdk.forConsole.billing.createOrganization(
ID.unique(),
name,
BillingPlan.FREE,
null,
null
);
if (selectedPlan === BillingPlan.Tier0) {
org = await sdk.forConsole.organizations.create(ID.unique(), name, selectedPlan);
} else {
org = await sdk.forConsole.billing.createOrganization(
org = await sdk.forConsole.organizations.create(
ID.unique(),
name,
selectedPlan,
paymentMethodId,
null,
couponData.code ? couponData.code : null,
collaborators,
billingBudget,
taxId
couponData.code ? couponData.code : null,
taxId,
billingBudget
);
if (!isOrganization(org) && org.status === 402) {
let clientSecret = org.clientSecret;
let params = new URLSearchParams();
if (isOrganizationError(org) && org.status === 402) {
const clientSecret = org.clientSecret;
const params = new URLSearchParams();
params.append('type', 'payment_confirmed');
params.append('id', org.teamId);
for (const [key, value] of page.url.searchParams.entries()) {
@@ -208,7 +202,7 @@
anyOrgFree={data.hasFreeOrganizations}
isNewOrg />
</Fieldset>
{#if selectedPlan !== BillingPlan.FREE}
{#if selectedPlan !== BillingPlan.Tier0}
<Fieldset legend="Payment">
<SelectPaymentMethod
methods={data.paymentMethods}
@@ -236,7 +230,7 @@
</Layout.Stack>
</Form>
<svelte:fragment slot="aside">
{#if selectedPlan !== BillingPlan.FREE}
{#if selectedPlan !== BillingPlan.Tier0}
<EstimatedTotalBox
billingPlan={selectedPlan}
{collaborators}
@@ -1,21 +1,21 @@
import { BillingPlan } from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
import type { PageLoad } from './$types';
import type { Coupon } from '$lib/sdk/billing';
import type { Organization } from '$lib/stores/organization';
import { BillingPlan } from '@appwrite.io/console';
export const load: PageLoad = async ({ url, parent }) => {
const { organizations } = await parent();
const [coupon, paymentMethods] = await Promise.all([
getCoupon(url),
sdk.forConsole.billing.listPaymentMethods()
sdk.forConsole.account.listPaymentMethods()
]);
let plan = getPlanFromUrl(url);
const hasFreeOrganizations = organizations.teams?.some(
(org) => (org as Organization)?.billingPlan === BillingPlan.FREE
(org) => (org as Organization)?.billingPlan === BillingPlan.Tier0
);
if (plan === BillingPlan.FREE && hasFreeOrganizations) {
plan = BillingPlan.PRO;
if (plan === BillingPlan.Tier0 && hasFreeOrganizations) {
plan = BillingPlan.Tier1;
}
return {
@@ -34,14 +34,14 @@ function getPlanFromUrl(url: URL): BillingPlan | null {
return plan as BillingPlan;
}
}
return BillingPlan.FREE;
return BillingPlan.Tier0;
}
async function getCoupon(url: URL): Promise<Coupon | null> {
if (url.searchParams.has('code')) {
const coupon = url.searchParams.get('code');
try {
return sdk.forConsole.billing.getCoupon(coupon);
return sdk.forConsole.console.getCoupon(coupon);
} catch (e) {
return null;
}
@@ -2,9 +2,8 @@ import type { PageLoad } from './$types';
import { isCloud } from '$lib/system';
import { sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { isOrganization, tierToPlan } from '$lib/stores/billing';
import { ID, Query } from '@appwrite.io/console';
import { BillingPlan } from '$lib/constants';
import { isOrganization, isOrganizationError, tierToPlan } from '$lib/stores/billing';
import { BillingPlan, ID, Query } from '@appwrite.io/console';
import { redirect } from '@sveltejs/kit';
import { base } from '$app/paths';
@@ -14,15 +13,13 @@ export const load: PageLoad = async ({ parent }) => {
if (!organizations?.total) {
try {
if (isCloud) {
const org = await sdk.forConsole.billing.createOrganization(
const org = await sdk.forConsole.organizations.create(
ID.unique(),
'Personal projects',
BillingPlan.FREE,
null,
null
BillingPlan.Tier0
);
trackEvent(Submit.OrganizationCreate, {
plan: tierToPlan(BillingPlan.FREE)?.name,
plan: tierToPlan(BillingPlan.Tier0)?.name,
budget_cap_enabled: false,
members_invited: 0
});
@@ -32,7 +29,7 @@ export const load: PageLoad = async ({ parent }) => {
organization: org,
regions: await sdk.forConsole.billing.listRegions(org.$id)
};
} else {
} else if (isOrganizationError(org)) {
const e = new Error(org.message, {
cause: org
});
@@ -12,8 +12,8 @@ import { get } from 'svelte/store';
import { preferences } from '$lib/stores/preferences';
import type { Organization } from '$lib/stores/organization';
import { defaultRoles, defaultScopes } from '$lib/constants';
import type { Plan } from '$lib/sdk/billing';
import { loadAvailableRegions } from '$routes/(console)/regions';
import type { Models } from '@appwrite.io/console';
export const load: LayoutLoad = async ({ params, depends }) => {
depends(Dependencies.ORGANIZATION);
@@ -21,14 +21,14 @@ export const load: LayoutLoad = async ({ params, depends }) => {
depends(Dependencies.PAYMENT_METHODS);
let roles = isCloud ? [] : defaultRoles;
let scopes = isCloud ? [] : defaultScopes;
let currentPlan: Plan = null;
let currentPlan: Models.BillingPlan = null;
try {
if (isCloud) {
const res = await sdk.forConsole.billing.getRoles(params.organization);
const res = await sdk.forConsole.organizations.getScopes(params.organization);
roles = res.roles;
scopes = res.scopes;
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(params.organization);
currentPlan = await sdk.forConsole.organizations.getPlan(params.organization);
if (scopes.includes('billing.read')) {
await failedInvoice.load(params.organization);
if (get(failedInvoice)) {
@@ -44,7 +44,7 @@
page.url.searchParams.get('type') === 'confirmation'
) {
const invoiceId = page.url.searchParams.get('invoice');
const invoice = await sdk.forConsole.billing.getInvoice(
const invoice = await sdk.forConsole.organizations.getInvoice(
page.params.organization,
invoiceId
);
@@ -62,7 +62,7 @@
page.url.searchParams.get('type') === 'validate-invoice'
) {
const invoiceId = page.url.searchParams.get('invoice');
await sdk.forConsole.billing.updateInvoiceStatus($organization.$id, invoiceId);
await sdk.forConsole.organizations.validateInvoice($organization.$id, invoiceId);
invalidate(Dependencies.INVOICES);
invalidate(Dependencies.ORGANIZATION);
}
@@ -72,7 +72,7 @@
page.url.searchParams.get('type') === 'retry'
) {
const invoiceId = page.url.searchParams.get('invoice');
const invoice = await sdk.forConsole.billing.getInvoice(
const invoice = await sdk.forConsole.organizations.getInvoice(
page.params.organization,
invoiceId
);
@@ -120,9 +120,13 @@
{/if}
{#if $organization?.billingPlanDowngrade}
<Alert.Inline status="info">
Your organization has changed to {tierToPlan($organization?.billingPlanDowngrade).name} plan.
You will continue to have access to {tierToPlan($organization?.billingPlan).name} plan features
until your billing period ends on {toLocaleDate($organization.billingNextInvoiceDate)}.
Your organization has changed to {tierToPlan(
$organization?.billingPlanDowngrade as unknown as string
).name} plan. You will continue to have access to {tierToPlan(
$organization?.billingPlan
).name} plan features until your billing period ends on {toLocaleDate(
$organization.billingNextInvoiceDate
)}.
</Alert.Inline>
{/if}
<Typography.Title>Billing</Typography.Title>
@@ -31,7 +31,7 @@ export const load: PageLoad = async ({ parent, depends }) => {
*/
let billingAggregation = null;
try {
billingAggregation = await sdk.forConsole.billing.getAggregation(
billingAggregation = await sdk.forConsole.organizations.getAggregation(
organization.$id,
(organization as Organization)?.billingAggregationId
);
@@ -41,7 +41,7 @@ export const load: PageLoad = async ({ parent, depends }) => {
let billingInvoice = null;
try {
billingInvoice = await sdk.forConsole.billing.getInvoice(
billingInvoice = await sdk.forConsole.organizations.getInvoice(
organization.$id,
(organization as Organization)?.billingInvoiceId
);
@@ -51,10 +51,10 @@ export const load: PageLoad = async ({ parent, depends }) => {
const [paymentMethods, addressList, billingAddress, creditList, aggregationBillingPlan] =
await Promise.all([
sdk.forConsole.billing.listPaymentMethods(),
sdk.forConsole.billing.listAddresses(),
sdk.forConsole.account.listPaymentMethods(),
sdk.forConsole.account.listBillingAddresses(),
billingAddressPromise,
sdk.forConsole.billing.listCredits(organization.$id),
sdk.forConsole.organizations.listCredits(organization.$id),
sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan)
]);
@@ -16,7 +16,7 @@
async function redeem() {
try {
await sdk.forConsole.billing.addCredit($organization.$id, coupon);
await sdk.forConsole.organizations.addCredit($organization.$id, coupon);
show = false;
await invalidate(Dependencies.CREDIT);
await invalidate(Dependencies.ORGANIZATION);
@@ -18,12 +18,15 @@
async function create() {
try {
await sdk.forConsole.billing.setOrganizationPaymentMethod(
await sdk.forConsole.organizations.setDefaultPaymentMethod(
$organization.$id,
$addCreditWizardStore.paymentMethodId
);
await sdk.forConsole.billing.addCredit($organization.$id, $addCreditWizardStore.coupon);
await sdk.forConsole.organizations.addCredit(
$organization.$id,
$addCreditWizardStore.coupon
);
addNotification({
type: 'success',
message: `Credit has been added to ${$organization.name}`
@@ -42,7 +42,7 @@
async function request() {
if (!$organization?.$id) return;
creditList = await sdk.forConsole.billing.listCredits($organization.$id, [
creditList = await sdk.forConsole.organizations.listCredits($organization.$id, [
Query.limit(limit),
Query.offset(offset)
]);
@@ -32,7 +32,7 @@
async function addAddress(addressId: string) {
try {
await sdk.forConsole.billing.setBillingAddress($organization.$id, addressId);
await sdk.forConsole.organizations.setBillingAddress($organization.$id, addressId);
await invalidate(Dependencies.ADDRESS);
await invalidate(Dependencies.ORGANIZATION);
@@ -49,7 +49,7 @@
async function updateBudget() {
try {
await sdk.forConsole.billing.updateBudget(
await sdk.forConsole.organizations.updateBudget(
$organization.$id,
$organization.billingBudget,
alerts
@@ -22,7 +22,7 @@
async function updateBudget() {
try {
await sdk.forConsole.billing.updateBudget(
await sdk.forConsole.organizations.updateBudget(
$organization.$id,
budget,
$organization.budgetAlerts
@@ -31,7 +31,7 @@
<Modal title="Cancel plan change" onSubmit={cancelDowngrade} bind:show={showCancel} bind:error>
<p>
Your organization is set to change to <strong>
{tierToPlan($organization?.billingPlanDowngrade).name}</strong>
{tierToPlan($organization?.billingPlanDowngrade as unknown as string).name}</strong>
plan on <strong> {toLocaleDate($organization.billingNextInvoiceDate)}</strong>. Are you sure
you want to cancel this change and keep your current plan?
</p>
@@ -19,7 +19,7 @@
if ($organization?.billingPlan !== BillingPlan.FREE && !hasOtherMethod) return;
try {
await sdk.forConsole.billing.removeOrganizationPaymentMethod($organization.$id);
await sdk.forConsole.organizations.deleteDefaultPaymentMethod($organization.$id);
addNotification({
type: 'success',
message: `The payment method has been removed from ${$organization.name}`
@@ -39,7 +39,7 @@
showDelete = false;
try {
await sdk.forConsole.billing.removeOrganizationPaymentMethodBackup($organization.$id);
await sdk.forConsole.organizations.deleteBackupPaymentMethod($organization.$id);
addNotification({
type: 'success',
message: `The payment method has been removed from ${$organization.name}`
@@ -4,9 +4,8 @@
import { Button } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
import { formatCurrency } from '$lib/helpers/numbers';
import type { Invoice, InvoiceList } from '$lib/sdk/billing';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import { Query, type Models } from '@appwrite.io/console';
import { onMount } from 'svelte';
import { trackEvent } from '$lib/actions/analytics';
import { selectedInvoice, showRetryModal } from './store';
@@ -30,7 +29,7 @@
import { base } from '$app/paths';
let offset = 0;
let invoiceList: InvoiceList = {
let invoiceList: Models.InvoiceList = {
invoices: [],
total: 0
};
@@ -41,7 +40,7 @@
async function request() {
// isLoadingInvoices = true;
invoiceList = await sdk.forConsole.billing.listInvoices(page.params.organization, [
invoiceList = await sdk.forConsole.organizations.listInvoices(page.params.organization, [
Query.limit(limit),
Query.offset(offset),
Query.orderDesc('$createdAt')
@@ -53,7 +52,7 @@
request();
}
function retryPayment(invoice: Invoice) {
function retryPayment(invoice: Models.Invoice) {
$selectedInvoice = invoice;
$showRetryModal = true;
}
@@ -45,7 +45,7 @@
async function addPaymentMethod(paymentMethodId: string) {
try {
await sdk.forConsole.billing.setOrganizationPaymentMethod(
await sdk.forConsole.organizations.setDefaultPaymentMethod(
$organization.$id,
paymentMethodId
);
@@ -66,7 +66,7 @@
async function addBackupPaymentMethod(paymentMethodId: string) {
try {
await sdk.forConsole.billing.setOrganizationPaymentMethodBackup(
await sdk.forConsole.organizations.setBackupPaymentMethod(
$organization.$id,
paymentMethodId
);
@@ -33,7 +33,7 @@
const today = new Date();
const isTrial =
new Date($organization?.billingStartDate).getTime() - today.getTime() > 0 &&
$plansInfo.get($organization.billingPlan)?.trialDays;
$plansInfo.get($organization.billingPlan)?.trial;
const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0;
function usageNameToLabel(name: string): string {
@@ -14,7 +14,7 @@
async function removeAddress() {
try {
await sdk.forConsole.billing.removeBillingAddress($organization.$id);
await sdk.forConsole.organizations.deleteBillingAddress($organization.$id);
addNotification({
type: 'success',
message: `The billing address has been removed from ${$organization.name}`
@@ -33,7 +33,7 @@
onMount(async () => {
loading = true;
addresses = await sdk.forConsole.billing.listAddresses();
addresses = await sdk.forConsole.account.listBillingAddresses();
const firstNonCurrentAddress = addresses?.billingAddresses?.find(
(address) => address.$id !== $organization?.billingAddressId
@@ -65,7 +65,7 @@
if (selectedAddress === $organization.billingAddressId) {
show = false;
} else if (selectedAddress === '$new') {
const address = await sdk.forConsole.billing.createAddress(
const address = await sdk.forConsole.account.createBillingAddress(
country,
streetAddress,
city,
@@ -73,7 +73,10 @@
postalCode ? postalCode : undefined,
addressLine2 ? postalCode : undefined
);
await sdk.forConsole.billing.setBillingAddress($organization.$id, address.$id);
await sdk.forConsole.organizations.setBillingAddress(
$organization.$id,
address.$id
);
invalidate(Dependencies.ORGANIZATION);
invalidate(Dependencies.ADDRESS);
@@ -88,7 +91,10 @@
message: `Your billing address has been updated`
});
} else {
await sdk.forConsole.billing.setBillingAddress($organization.$id, selectedAddress);
await sdk.forConsole.organizations.setBillingAddress(
$organization.$id,
selectedAddress
);
invalidate(Dependencies.ORGANIZATION);
invalidate(Dependencies.ADDRESS);
@@ -20,7 +20,7 @@
let error: string;
onMount(async () => {
methods = await sdk.forConsole.billing.listPaymentMethods();
methods = await sdk.forConsole.account.listPaymentMethods();
if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) {
selectedPaymentMethodId = methods?.total ? methods.paymentMethods[0].$id : null;
@@ -68,7 +68,7 @@
async function addPaymentMethod(paymentMethodId: string) {
try {
await sdk.forConsole.billing.setOrganizationPaymentMethod(
await sdk.forConsole.organizations.setDefaultPaymentMethod(
$organization.$id,
paymentMethodId
);
@@ -79,7 +79,7 @@
async function addBackupPaymentMethod(paymentMethodId: string) {
try {
await sdk.forConsole.billing.setOrganizationPaymentMethodBackup(
await sdk.forConsole.organizations.setBackupPaymentMethod(
$organization.$id,
paymentMethodId
);
@@ -3,7 +3,6 @@
import { FakeModal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { Dependencies } from '$lib/constants';
import type { Invoice } from '$lib/sdk/billing';
import { addNotification } from '$lib/stores/notifications';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { page } from '$app/state';
@@ -16,9 +15,10 @@
import { getApiEndpoint, sdk } from '$lib/stores/sdk';
import { formatCurrency } from '$lib/helpers/numbers';
import { base } from '$app/paths';
import type { Models } from '@appwrite.io/console';
export let show = false;
export let invoice: Invoice;
export let invoice: Models.Invoice;
let error: string = null;
let isButtonDisabled = false;
let name: string;
@@ -49,7 +49,7 @@
if (paymentMethodId === null) {
try {
const method = await submitStripeCard(name, $organization.$id);
const card = await sdk.forConsole.billing.getPaymentMethod(method.$id);
const card = await sdk.forConsole.account.getPaymentMethod(method.$id);
if (card?.last4) {
paymentMethodId = card.$id;
} else {
@@ -66,11 +66,12 @@
if (setAsDefault) {
await sdk.forConsole.billing.setDefaultPaymentMethod(paymentMethodId);
}
const { clientSecret, status } = await sdk.forConsole.billing.retryPayment(
$organization.$id,
invoice.$id,
paymentMethodId
);
const { clientSecret, status } =
await sdk.forConsole.organizations.createInvoicePayment(
$organization.$id,
invoice.$id,
paymentMethodId
);
if (status !== 'succeeded' && status !== 'cancelled') {
// probably still pending, confirm via stripe!
@@ -81,7 +82,7 @@
`${base}/organization-${$organization.$id}/billing?type=validate-invoice&invoice=${invoice.$id}`
);
await sdk.forConsole.billing.updateInvoiceStatus($organization.$id, invoice.$id);
await sdk.forConsole.organizations.validateInvoice($organization.$id, invoice.$id);
}
invalidate(Dependencies.ORGANIZATION);
@@ -1,6 +1,7 @@
import { page } from '$app/stores';
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
import type { AggregationList, Invoice } from '$lib/sdk/billing';
import type { AggregationList } from '$lib/sdk/billing';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
export const aggregationList = derived(
@@ -14,5 +15,5 @@ export const addCreditWizardStore = writable<{ coupon: string; paymentMethodId:
paymentMethodId: null
});
export const selectedInvoice = writable<Invoice>(null);
export const selectedInvoice = writable<Models.Invoice>(null);
export const showRetryModal = writable(false);
@@ -17,7 +17,7 @@
async function updateTaxId() {
try {
await sdk.forConsole.billing.updateTaxId($organization.$id, taxId);
await sdk.forConsole.organizations.setBillingTaxId($organization.$id, taxId);
await invalidate(Dependencies.ORGANIZATION);
addNotification({
type: 'success',
@@ -17,7 +17,7 @@
async function validateCoupon() {
if (couponData?.status === 'active') return;
try {
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
const response = await sdk.forConsole.account.getCoupon(coupon);
couponData = response;
$addCreditWizardStore.coupon = coupon;
coupon = null;
@@ -14,7 +14,7 @@
let name: string;
onMount(async () => {
methods = await sdk.forConsole.billing.listPaymentMethods();
methods = await sdk.forConsole.account.listPaymentMethods();
$addCreditWizardStore.paymentMethodId =
methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null;
});
@@ -11,7 +11,12 @@
import { formatCurrency } from '$lib/helpers/numbers.js';
import { Wizard } from '$lib/layout';
import { type Coupon } from '$lib/sdk/billing';
import { isOrganization, plansInfo, tierToPlan } from '$lib/stores/billing';
import {
isOrganization,
isOrganizationError,
plansInfo,
tierToPlan
} from '$lib/stores/billing';
import { addNotification } from '$lib/stores/notifications';
import { currentPlan, organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
@@ -31,10 +36,11 @@
import { writable } from 'svelte/store';
import { onMount } from 'svelte';
import EstimatedTotalBox from '$lib/components/billing/estimatedTotalBox.svelte';
import { isValueOfStringEnum } from '$lib/helpers/types.js';
export let data;
let selectedPlan: BillingPlan = data.plan as BillingPlan;
let selectedPlan: BillingPlan = data.plan;
let selectedCoupon: Partial<Coupon> | null = data.coupon;
let previousPage: string = base;
let showExitModal = false;
@@ -63,7 +69,7 @@
if (page.url.searchParams.has('code')) {
const coupon = page.url.searchParams.get('code');
try {
couponData = await sdk.forConsole.billing.getCouponAccount(coupon);
couponData = await sdk.forConsole.account.getCoupon(coupon);
} catch (e) {
couponData = {
code: null,
@@ -74,7 +80,7 @@
}
if (page.url.searchParams.has('plan')) {
const plan = page.url.searchParams.get('plan');
if (plan && plan in BillingPlan) {
if (plan && isValueOfStringEnum(BillingPlan, plan)) {
selectedPlan = plan as BillingPlan;
}
}
@@ -87,10 +93,10 @@
await validate(organizationId, invites);
}
}
if ($currentPlan?.$id === BillingPlan.SCALE) {
selectedPlan = BillingPlan.SCALE;
if ($currentPlan?.$id === BillingPlan.Tier2) {
selectedPlan = BillingPlan.Tier2;
} else {
selectedPlan = BillingPlan.PRO;
selectedPlan = BillingPlan.Tier1;
}
});
@@ -104,7 +110,7 @@
async function downgrade() {
try {
await sdk.forConsole.billing.updatePlan(
await sdk.forConsole.organizations.updatePlan(
data.organization.$id,
selectedPlan,
paymentMethodId,
@@ -186,18 +192,18 @@
!data?.members?.memberships?.find((m) => m.userEmail === collaborator)
);
}
const org = await sdk.forConsole.billing.updatePlan(
const org = await sdk.forConsole.organizations.updatePlan(
data.organization.$id,
selectedPlan,
paymentMethodId,
null,
couponData?.code,
newCollaborators,
billingBudget,
taxId ? taxId : null
couponData?.code,
taxId ? taxId : null,
billingBudget
);
if (!isOrganization(org) && org.status == 402) {
if (isOrganizationError(org) && org.status == 402) {
let clientSecret = org.clientSecret;
let params = new URLSearchParams();
for (const [key, value] of page.url.searchParams.entries()) {
@@ -1,8 +1,9 @@
import { BillingPlan, Dependencies } from '$lib/constants';
import { Dependencies } from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
import type { PageLoad } from './$types';
import type { Coupon } from '$lib/sdk/billing';
import type { Organization } from '$lib/stores/organization';
import { BillingPlan } from '@appwrite.io/console';
export const load: PageLoad = async ({ depends, parent, url }) => {
const { members, organization, currentPlan, organizations } = await parent();
@@ -10,20 +11,20 @@ export const load: PageLoad = async ({ depends, parent, url }) => {
const [coupon, paymentMethods] = await Promise.all([
getCoupon(url),
sdk.forConsole.billing.listPaymentMethods()
sdk.forConsole.account.listPaymentMethods()
]);
let plan = getPlanFromUrl(url);
if (organization?.billingPlan === BillingPlan.SCALE) {
plan = BillingPlan.SCALE;
if (organization?.billingPlan === BillingPlan.Tier2) {
plan = BillingPlan.Tier2;
} else {
plan = BillingPlan.PRO;
plan = BillingPlan.Tier1;
}
const selfService = currentPlan?.selfService ?? true;
const hasFreeOrgs = organizations.teams?.some(
(org) => (org as Organization)?.billingPlan === BillingPlan.FREE
(org) => (org as Organization)?.billingPlan === BillingPlan.Tier0
);
return {
@@ -49,7 +50,7 @@ async function getCoupon(url: URL): Promise<Coupon | null> {
if (url.searchParams.has('code')) {
const coupon = url.searchParams.get('code');
try {
return sdk.forConsole.billing.getCoupon(coupon);
return sdk.forConsole.console.getCoupon(coupon);
} catch (e) {
return null;
}
@@ -7,7 +7,7 @@ export const load = async ({ parent, depends }) => {
const organizations = !isCloud
? await sdk.forConsole.teams.list()
: await sdk.forConsole.billing.listOrganization();
: await sdk.forConsole.organizations.list();
const { domain } = await parent();
return {
@@ -91,7 +91,7 @@
{:else if isCloud && $organization?.billingPlan === BillingPlan.FREE}
<Badge variant="secondary" content="Free"></Badge>
{/if}
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.FREE && $plansInfo.get($organization.billingPlan)?.trialDays}
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.FREE && $plansInfo.get($organization.billingPlan)?.trial}
<Tooltip>
<Badge variant="secondary" content="Trial" />
<svelte:fragment slot="tooltip">
@@ -4,7 +4,10 @@ import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params }) => {
// verify invoice exists
const invoice = await sdk.forConsole.billing.getInvoice(params.organization, params.invoiceId);
const invoice = await sdk.forConsole.organizations.getInvoice(
params.organization,
params.invoiceId
);
const endpoint = getApiEndpoint();
return redirect(
@@ -4,7 +4,10 @@ import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params }) => {
// verify invoice exists
const invoice = await sdk.forConsole.billing.getInvoice(params.organization, params.invoiceId);
const invoice = await sdk.forConsole.organizations.getInvoice(
params.organization,
params.invoiceId
);
const endpoint = getApiEndpoint();
return redirect(
@@ -9,7 +9,7 @@ export const load: PageLoad = async ({ depends, params }) => {
const [projects, invoices] = await Promise.all([
sdk.forConsole.projects.list([Query.equal('teamId', params.organization)]),
isCloud ? sdk.forConsole.billing.listInvoices(params.organization) : undefined
isCloud ? sdk.forConsole.organizations.listInvoices(params.organization) : undefined
]);
return {
@@ -16,10 +16,11 @@
import { Table, Tabs, Alert } from '@appwrite.io/pink-svelte';
import DeleteOrganizationEstimation from './deleteOrganizationEstimation.svelte';
import { onMount } from 'svelte';
import type { EstimationDeleteOrganization, InvoiceList } from '$lib/sdk/billing';
import type { EstimationDeleteOrganization } from '$lib/sdk/billing';
import type { Models } from '@appwrite.io/console';
export let showDelete = false;
export let invoices: InvoiceList;
export let invoices: Models.InvoiceList;
let error: string = null;
let selectedTab = 'projects';
@@ -29,7 +30,7 @@
async function deleteOrg() {
try {
if (isCloud) {
await sdk.forConsole.billing.deleteOrganization($organization.$id);
await sdk.forConsole.organizations.delete($organization.$id);
} else {
await sdk.forConsole.teams.delete($organization.$id);
}
@@ -1,5 +1,4 @@
<script lang="ts">
import type { Invoice } from '$lib/sdk/billing';
import { getApiEndpoint } from '$lib/stores/sdk';
import { selectedInvoice, showRetryModal } from '../billing/store';
import { toLocaleDate } from '$lib/helpers/date';
@@ -14,13 +13,14 @@
IconRefresh
} from '@appwrite.io/pink-icons-svelte';
import { page } from '$app/state';
import type { Models } from '@appwrite.io/console';
const endpoint = getApiEndpoint();
export let invoices: Invoice[];
export let invoices: Models.Invoice[];
export let showActions = true;
function retryPayment(invoice: Invoice) {
function retryPayment(invoice: Models.Invoice) {
$selectedInvoice = invoice;
$showRetryModal = true;
}
@@ -4,12 +4,7 @@
import { BarChart, Legend } from '$lib/charts';
import { Button } from '$lib/elements/forms';
import { bytesToSize, humanFileSize, mbSecondsToGBHours } from '$lib/helpers/sizeConvertion';
import {
getServiceLimit,
showUsageRatesModal,
type Tier,
upgradeURL
} from '$lib/stores/billing';
import { getServiceLimit, showUsageRatesModal, upgradeURL } from '$lib/stores/billing';
import { organization } from '$lib/stores/organization';
import ProjectBreakdown from './ProjectBreakdown.svelte';
import { formatNum } from '$lib/helpers/string';
@@ -25,8 +20,9 @@
export let data;
const tier = data?.plan
? (data.plan.$id as Tier)
: (data?.currentInvoice?.plan ?? $organization?.billingPlan);
? (data.plan.$id as BillingPlan)
: ((data?.currentInvoice?.plan as BillingPlan) ??
($organization?.billingPlan as BillingPlan));
const plan = data?.plan ?? undefined;
$: projects = (data.organizationUsage as OrganizationUsage).projects;
@@ -1,4 +1,3 @@
import type { Invoice } from '$lib/sdk/billing';
import { type Organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { Query, type Models } from '@appwrite.io/console';
@@ -42,18 +41,18 @@ export const load: PageLoad = async ({ params, parent }) => {
let startDate: string = org.billingCurrentInvoiceDate;
let endDate: string = org.billingNextInvoiceDate;
let currentInvoice: Invoice = undefined;
let currentInvoice: Models.Invoice = undefined;
if (invoice) {
currentInvoice = await sdk.forConsole.billing.getInvoice(org.$id, invoice);
currentInvoice = await sdk.forConsole.organizations.getInvoice(org.$id, invoice);
startDate = currentInvoice.from;
endDate = currentInvoice.to;
}
const [invoices, usage, organizationMembers, plan] = await Promise.all([
sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]),
sdk.forConsole.organizations.listInvoices(org.$id, [Query.orderDesc('from')]),
sdk.forConsole.billing.listUsage(params.organization, startDate, endDate),
sdk.forConsole.teams.listMemberships(params.organization, [Query.limit(100)]),
sdk.forConsole.billing.getOrganizationPlan(org.$id)
sdk.forConsole.organizations.getPlan(org.$id)
]);
const projects: { [key: string]: Models.Project } = {};
@@ -14,7 +14,7 @@
export let members: Models.MembershipList;
$: total = members?.total ?? 0;
$: plan = $plansInfo?.get($organization?.billingPlan);
$: plan = $plansInfo?.get($organization?.billingPlan as BillingPlan);
</script>
<CardGrid>
@@ -6,16 +6,16 @@ import { preferences } from '$lib/stores/preferences';
import { failedInvoice } from '$lib/stores/billing';
import { isCloud } from '$lib/system';
import { defaultRoles, defaultScopes } from '$lib/constants';
import type { Plan } from '$lib/sdk/billing';
import { get } from 'svelte/store';
import { headerAlert } from '$lib/stores/headerAlert';
import PaymentFailed from '$lib/components/billing/alerts/paymentFailed.svelte';
import { loadAvailableRegions } from '$routes/(console)/regions';
import type { Organization } from '$lib/stores/organization';
import type { Models } from '@appwrite.io/console';
export const load: LayoutLoad = async ({ params, depends }) => {
depends(Dependencies.PROJECT);
let currentPlan: Plan = null;
let currentPlan: Models.BillingPlan = null;
try {
const project = await sdk.forConsole.projects.get(params.project);
@@ -34,8 +34,8 @@ export const load: LayoutLoad = async ({ params, depends }) => {
let roles = isCloud ? [] : defaultRoles;
let scopes = isCloud ? [] : defaultScopes;
if (isCloud) {
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(project.teamId);
const res = await sdk.forConsole.billing.getRoles(project.teamId);
currentPlan = await sdk.forConsole.organizations.getPlan(project.teamId);
const res = await sdk.forConsole.organizations.getScopes(project.teamId);
roles = res.roles;
scopes = res.scopes;
if (scopes.includes('billing.read')) {
@@ -7,7 +7,6 @@ import type { PageLoad, RouteParams } from './$types';
import type { BackupPolicy } from '$lib/sdk/backups';
import { isSelfHosted } from '$lib/system';
import { isCloud } from '$lib/system';
import type { Plan } from '$lib/sdk/billing';
export const load: PageLoad = async ({ url, route, depends, params, parent }) => {
depends(Dependencies.DATABASES);
@@ -45,7 +44,7 @@ async function fetchDatabasesAndBackups(
offset: number,
params: RouteParams,
search?: string | undefined,
currentPlan?: Plan
currentPlan?: Models.BillingPlan
) {
const backupsEnabled = currentPlan?.backupsEnabled ?? true;
@@ -24,9 +24,15 @@
import { page } from '$app/state';
import { capitalize } from '$lib/helpers/string';
import { IconExternalLink } from '@appwrite.io/pink-icons-svelte';
import type { BillingPlan } from '$lib/constants';
$: buttonDisabled =
isCloud && isServiceLimited('functions', $organization?.billingPlan, $functionsList?.total);
isCloud &&
isServiceLimited(
'functions',
$organization?.billingPlan as BillingPlan,
$functionsList?.total
);
</script>
<Container>
@@ -1,7 +1,7 @@
import type { Aggregation, Invoice } from '$lib/sdk/billing';
import type { Aggregation } from '$lib/sdk/billing';
import { accumulateUsage } from '$lib/sdk/usage';
import { sdk } from '$lib/stores/sdk';
import { Query } from '@appwrite.io/console';
import { Query, type Models } from '@appwrite.io/console';
import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, parent }) => {
@@ -10,11 +10,11 @@ export const load: PageLoad = async ({ params, parent }) => {
let startDate: string = organization.billingCurrentInvoiceDate;
let endDate: string = organization.billingNextInvoiceDate;
let currentInvoice: Invoice = undefined;
let currentInvoice: Models.Invoice = undefined;
let currentAggregation: Aggregation = undefined;
if (invoice) {
currentInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, invoice);
currentInvoice = await sdk.forConsole.organizations.getInvoice(organization.$id, invoice);
currentAggregation = await sdk.forConsole.billing.getAggregation(
organization.$id,
currentInvoice.aggregationId
@@ -25,7 +25,7 @@ export const load: PageLoad = async ({ params, parent }) => {
}
const [invoices, usage] = await Promise.all([
sdk.forConsole.billing.listInvoices(organization.$id, [Query.orderDesc('from')]),
sdk.forConsole.organizations.listInvoices(organization.$id, [Query.orderDesc('from')]),
sdk.forProject(region, project).project.getUsage(startDate, endDate)
]);
@@ -24,7 +24,7 @@
import Table from './table.svelte';
import { onMount } from 'svelte';
import { invalidate } from '$app/navigation';
import { Dependencies } from '$lib/constants';
import { BillingPlan, Dependencies } from '$lib/constants';
import { sdk } from '$lib/stores/sdk';
export let data;
let show = false;
@@ -37,8 +37,11 @@
},
keys: ['c'],
disabled:
isServiceLimited('sites', $organization?.billingPlan, data.siteList?.total) ||
!$canWriteSites,
isServiceLimited(
'sites',
$organization?.billingPlan as BillingPlan,
data.siteList?.total
) || !$canWriteSites,
icon: IconPlus,
group: 'sites'
}
@@ -9,11 +9,10 @@
import { organization } from '$lib/stores/organization';
import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system';
import { updateBucket } from './+page.svelte';
import type { Plan } from '$lib/sdk/billing';
import type { Models } from '@appwrite.io/console';
export let bucket: Models.Bucket;
export let currentPlan: Plan | null;
export let currentPlan: Models.BillingPlan | null;
const service = currentPlan ? currentPlan['fileSize'] : null;
const { value, unit, baseValue, units } = createByteUnitPair(bucket.maximumFileSize, 1000);
+1 -2
View File
@@ -1,6 +1,5 @@
import { page } from '$app/stores';
import type { HeaderAlert } from '$lib/stores/headerAlert';
import type { Organization } from '$lib/stores/organization';
import type { Models } from '@appwrite.io/console';
import { derived, writable } from 'svelte/store';
@@ -16,4 +15,4 @@ export const protocol = derived(page, ($page) =>
);
export const activeHeaderAlert = writable<HeaderAlert>(null);
export const orgMissingPaymentMethod = writable<Organization>(null);
export const orgMissingPaymentMethod = writable<Models.Organization<Record<string, unknown>>>(null);
+6 -6
View File
@@ -1,17 +1,17 @@
import { base } from '$app/paths';
import type { Campaign } from '$lib/stores/campaigns';
import { sdk } from '$lib/stores/sdk';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import type { Models } from '@appwrite.io/console';
export const load: PageLoad = async ({ url }) => {
if (url.searchParams.has('code')) {
const code = url.searchParams.get('code');
let campaign: Campaign;
let campaign: Models.Campaign;
try {
const couponData = await sdk.forConsole.billing.getCoupon(code);
const couponData = await sdk.forConsole.console.getCoupon(code);
if (couponData.campaign) {
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
campaign = await sdk.forConsole.console.getCampaign(couponData.campaign);
return {
couponData,
campaign
@@ -23,9 +23,9 @@ export const load: PageLoad = async ({ url }) => {
}
if (url.searchParams.has('campaign')) {
const campaignId = url.searchParams.get('campaign');
let campaign: Campaign;
let campaign: Models.Campaign;
try {
campaign = await sdk.forConsole.billing.getCampaign(campaignId);
campaign = await sdk.forConsole.console.getCampaign(campaignId);
return { campaign };
} catch (e) {
redirect(303, `${base}/login`);
@@ -1,17 +1,17 @@
import { base } from '$app/paths';
import type { Campaign } from '$lib/stores/campaigns.js';
import { sdk } from '$lib/stores/sdk';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
import type { Models } from '@appwrite.io/console';
export const load: PageLoad = async ({ url }) => {
if (url.searchParams.has('code')) {
const code = url.searchParams.get('code');
let campaign: Campaign;
let campaign: Models.Campaign;
try {
const couponData = await sdk.forConsole.billing.getCoupon(code);
const couponData = await sdk.forConsole.console.getCoupon(code);
if (couponData.campaign) {
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
campaign = await sdk.forConsole.console.getCampaign(couponData.campaign);
return {
couponData,
campaign
@@ -23,9 +23,9 @@ export const load: PageLoad = async ({ url }) => {
}
if (url.searchParams.has('campaign')) {
const campaignId = url.searchParams.get('campaign');
let campaign: Campaign;
let campaign: Models.Campaign;
try {
campaign = await sdk.forConsole.billing.getCampaign(campaignId);
campaign = await sdk.forConsole.console.getCampaign(campaignId);
return { campaign };
} catch (e) {
redirect(303, `${base}/register`);
@@ -1,6 +1,5 @@
import { BillingPlan } from '$lib/constants.js';
import { sdk } from '$lib/stores/sdk.js';
import { ID, type Models } from '@appwrite.io/console';
import { BillingPlan, ID, type Models } from '@appwrite.io/console';
import { isCloud } from '$lib/system.js';
import { error, redirect } from '@sveltejs/kit';
import type { OrganizationList } from '$lib/stores/organization.js';
@@ -34,16 +33,16 @@ export const load = async ({ parent, url, params }) => {
let organizations: Models.TeamList<Record<string, unknown>> | OrganizationList | undefined;
if (isCloud) {
organizations = account?.$id ? await sdk.forConsole.billing.listOrganization() : undefined;
organizations = account?.$id ? await sdk.forConsole.organizations.list() : undefined;
} else {
organizations = account?.$id ? await sdk.forConsole.teams.list() : undefined;
}
if (!organizations?.total && account?.$id) {
await sdk.forConsole.billing.createOrganization(
await sdk.forConsole.organizations.create(
ID.unique(),
'Personal project',
BillingPlan.FREE,
BillingPlan.Tier0,
null,
null
);
+1 -1
View File
@@ -68,7 +68,7 @@
if (page.url.searchParams.has('code')) {
const code = page.url.searchParams.get('code');
const coupon = await sdk.forConsole.billing.getCoupon(code).catch<null>(() => null);
const coupon = await sdk.forConsole.console.getCoupon(code).catch<null>(() => null);
if (coupon?.campaign) {
const campaign = await sdk.forConsole.billing
.getCampaign(coupon.campaign)
+1 -1
View File
@@ -32,7 +32,7 @@ export const load: LayoutLoad = async ({ depends, url, route }) => {
account: account,
organizations: !isCloud
? await sdk.forConsole.teams.list()
: await sdk.forConsole.billing.listOrganization()
: await sdk.forConsole.organizations.list()
};
}