mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
refactor: listusage, budgets etc
This commit is contained in:
@@ -17,7 +17,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -257,14 +257,6 @@ export class Billing {
|
||||
});
|
||||
}
|
||||
|
||||
async getRoles(organizationId: string): Promise<Models.Roles> {
|
||||
const path = `/organizations/${organizationId}/roles`;
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call('get', uri, {
|
||||
'content-type': 'application/json'
|
||||
});
|
||||
}
|
||||
|
||||
async updatePlan(
|
||||
organizationId: string,
|
||||
billingPlan: string,
|
||||
@@ -328,98 +320,6 @@ export class Billing {
|
||||
});
|
||||
}
|
||||
|
||||
async updateBudget(
|
||||
organizationId: string,
|
||||
budget: number,
|
||||
alerts: number[]
|
||||
): Promise<Organization> {
|
||||
const path = `/organizations/${organizationId}/budget`;
|
||||
const params = {
|
||||
organizationId,
|
||||
budget,
|
||||
alerts
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'patch',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async setOrganizationPaymentMethod(
|
||||
organizationId: string,
|
||||
paymentMethodId: string
|
||||
): Promise<Organization> {
|
||||
const path = `/organizations/${organizationId}/payment-method`;
|
||||
const params = {
|
||||
organizationId,
|
||||
paymentMethodId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'patch',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async setOrganizationPaymentMethodBackup(
|
||||
organizationId: string,
|
||||
paymentMethodId: string
|
||||
): Promise<Organization> {
|
||||
const path = `/organizations/${organizationId}/payment-method/backup`;
|
||||
const params = {
|
||||
organizationId,
|
||||
paymentMethodId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'patch',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
async removeOrganizationPaymentMethod(organizationId: string): Promise<Organization> {
|
||||
const path = `/organizations/${organizationId}/payment-method`;
|
||||
const params = {
|
||||
organizationId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'DELETE',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
async removeOrganizationPaymentMethodBackup(organizationId: string): Promise<Organization> {
|
||||
const path = `/organizations/${organizationId}/payment-method/backup`;
|
||||
const params = {
|
||||
organizationId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'DELETE',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async listInvoices(organizationId: string, queries: string[] = []): Promise<InvoiceList> {
|
||||
const path = `/organizations/${organizationId}/invoices`;
|
||||
const params = {
|
||||
@@ -517,54 +417,6 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async listUsage(
|
||||
organizationId: string,
|
||||
startDate: string = undefined,
|
||||
endDate: string = undefined
|
||||
): Promise<Models.UsageOrganization> {
|
||||
const path = `/organizations/${organizationId}/usage`;
|
||||
const params = {
|
||||
organizationId
|
||||
};
|
||||
|
||||
if (startDate !== undefined) {
|
||||
params['startDate'] = startDate;
|
||||
}
|
||||
if (endDate !== undefined) {
|
||||
params['endDate'] = endDate;
|
||||
}
|
||||
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'get',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async listAggregation(
|
||||
organizationId: string,
|
||||
queries: string[] = []
|
||||
): Promise<Models.AggregationTeamList> {
|
||||
const path = `/organizations/${organizationId}/aggregations`;
|
||||
const params = {
|
||||
organizationId,
|
||||
queries
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'get',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async getAggregation(
|
||||
organizationId: string,
|
||||
aggregationId: string
|
||||
@@ -607,38 +459,6 @@ export class Billing {
|
||||
}
|
||||
}
|
||||
|
||||
async getCouponAccount(couponId: string): Promise<Models.Coupon> {
|
||||
const path = `/account/coupons/${couponId}`;
|
||||
const params = {
|
||||
couponId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'GET',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async getCoupon(couponId: string): Promise<Models.Coupon> {
|
||||
const path = `/console/coupons/${couponId}`;
|
||||
const params = {
|
||||
couponId
|
||||
};
|
||||
const uri = new URL(this.client.config.endpoint + path);
|
||||
return await this.client.call(
|
||||
'GET',
|
||||
uri,
|
||||
{
|
||||
'content-type': 'application/json'
|
||||
},
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
async setBillingAddress(
|
||||
organizationId: string,
|
||||
billingAddressId: string
|
||||
|
||||
@@ -461,7 +461,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;
|
||||
}
|
||||
|
||||
@@ -199,7 +199,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({
|
||||
|
||||
@@ -11,7 +11,7 @@ export const load = async ({ url }) => {
|
||||
let campaign: 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);
|
||||
}
|
||||
|
||||
@@ -61,7 +61,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 = {
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import ProjectsAtRisk from '$lib/components/billing/alerts/projectsAtRisk.svelte';
|
||||
import { defaultRoles, defaultScopes, Dependencies } from '$lib/constants';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import { failedInvoice } from '$lib/stores/billing';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { headerAlert } from '$lib/stores/headerAlert';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import Breadcrumbs from './breadcrumbs.svelte';
|
||||
import Header from './header.svelte';
|
||||
import { headerAlert } from '$lib/stores/headerAlert';
|
||||
import ProjectsAtRisk from '$lib/components/billing/alerts/projectsAtRisk.svelte';
|
||||
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';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.ORGANIZATION);
|
||||
@@ -24,7 +23,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
|
||||
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);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethod(
|
||||
await sdk.forConsole.organizations.setDefaultPaymentMethod(
|
||||
$organization.$id,
|
||||
$addCreditWizardStore.paymentMethodId
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Alert, CardGrid, Heading } from '$lib/components';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { tierToPlan, upgradeURL } from '$lib/stores/billing';
|
||||
import { Button, Form, FormList, InputSelectSearch } from '$lib/elements/forms';
|
||||
import {
|
||||
Table,
|
||||
@@ -15,6 +14,7 @@
|
||||
TableRow
|
||||
} from '$lib/elements/table';
|
||||
import { symmetricDifference } from '$lib/helpers/array';
|
||||
import { tierToPlan, upgradeURL } from '$lib/stores/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { currentPlan, organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
async function updateBudget() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updateBudget(
|
||||
await sdk.forConsole.organizations.updateBudget(
|
||||
$organization.$id,
|
||||
$organization.billingBudget,
|
||||
alerts
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { Button, Form, FormList, InputNumber, InputSwitch } from '$lib/elements/forms';
|
||||
import { showUsageRatesModal, upgradeURL } from '$lib/stores/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { organization, currentPlan } from '$lib/stores/organization';
|
||||
import { currentPlan, organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
async function updateBudget() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updateBudget(
|
||||
await sdk.forConsole.organizations.updateBudget(
|
||||
$organization.$id,
|
||||
budget,
|
||||
$organization.budgetAlerts
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { Modal } from '$lib/components';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
|
||||
export let showDelete = false;
|
||||
export let isBackup = false;
|
||||
@@ -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}`
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
async function addPaymentMethod(paymentMethodId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethod(
|
||||
await sdk.forConsole.organizations.setDefaultPaymentMethod(
|
||||
$organization.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
async function addBackupPaymentMethod(paymentMethodId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethodBackup(
|
||||
await sdk.forConsole.organizations.setBackupPaymentMethod(
|
||||
$organization.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
|
||||
@@ -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
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
if ($page.url.searchParams.has('code')) {
|
||||
const coupon = $page.url.searchParams.get('code');
|
||||
try {
|
||||
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
|
||||
const response = await sdk.forConsole.account.getCoupon(coupon);
|
||||
couponData = response;
|
||||
} catch (e) {
|
||||
couponData = {
|
||||
|
||||
@@ -51,7 +51,7 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
}
|
||||
const [invoices, usage, organizationMembers, plan] = await Promise.all([
|
||||
sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]),
|
||||
sdk.forConsole.billing.listUsage(params.organization, startDate, endDate),
|
||||
sdk.forConsole.organizations.getUsage(params.organization, startDate, endDate),
|
||||
sdk.forConsole.teams.listMemberships(params.organization),
|
||||
sdk.forConsole.billing.getOrganizationPlan(org.$id)
|
||||
]);
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import { failedInvoice } from '$lib/stores/billing';
|
||||
import { isCloud } from '$lib/system';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
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 { defaultRoles, defaultScopes, Dependencies } from '$lib/constants';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import { failedInvoice } from '$lib/stores/billing';
|
||||
import { headerAlert } from '$lib/stores/headerAlert';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import { get } from 'svelte/store';
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.PROJECT);
|
||||
@@ -33,7 +32,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
let scopes = isCloud ? [] : defaultScopes;
|
||||
if (isCloud) {
|
||||
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(project.teamId);
|
||||
const res = await sdk.forConsole.billing.getRoles(project.teamId);
|
||||
const res = await sdk.forConsole.organizations.getScopes(project.teamId);
|
||||
roles = res.roles;
|
||||
scopes = res.scopes;
|
||||
if (scopes.includes('billing.read')) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
|
||||
import type { PageLoad } from './$types';
|
||||
import { getLimit, getPage, getSearch, pageToOffset } from '$lib/helpers/load';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, depends, url, route, parent }) => {
|
||||
const { organization } = await parent();
|
||||
@@ -19,7 +19,9 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
|
||||
[Query.limit(limit), Query.offset(offset), Query.orderDesc('')],
|
||||
search
|
||||
),
|
||||
isCloud && organization?.$id ? sdk.forConsole.billing.listUsage(organization.$id) : null
|
||||
isCloud && organization?.$id
|
||||
? sdk.forConsole.organizations.getUsage(organization.$id)
|
||||
: null
|
||||
]);
|
||||
return {
|
||||
offset,
|
||||
|
||||
@@ -9,7 +9,7 @@ export const load: PageLoad = async ({ url }) => {
|
||||
const code = url.searchParams.get('code');
|
||||
let campaign: 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);
|
||||
return {
|
||||
|
||||
@@ -9,7 +9,7 @@ export const load: PageLoad = async ({ url }) => {
|
||||
const code = url.searchParams.get('code');
|
||||
let campaign: 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);
|
||||
return {
|
||||
|
||||
@@ -47,7 +47,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)
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { base } from '$app/paths';
|
||||
import type { PageLoad } from './$types';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { VARS } from '$lib/system';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
const handleGithubEducationMembership = async (name: string, email: string) => {
|
||||
const result = await sdk.forConsole.billing.setMembership('github-student-developer');
|
||||
|
||||
Reference in New Issue
Block a user