diff --git a/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts b/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts
index 0011e6dc0d1..7a71e6e25f3 100644
--- a/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts
+++ b/apps/studio/components/interfaces/Billing/Subscription/Subscription.utils.ts
@@ -1,6 +1,5 @@
import { IS_PLATFORM } from 'lib/constants'
-import { OrgSubscription } from 'data/subscriptions/org-subscription-query'
-import { ProjectSelectedAddon } from 'data/subscriptions/project-addons-query'
+import { OrgSubscription, ProjectSelectedAddon } from 'data/subscriptions/types'
export const getAddons = (selectedAddons: ProjectSelectedAddon[]) => {
const computeInstance = selectedAddons.find((addon) => addon.type === 'compute_instance')
diff --git a/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts b/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts
index 878c553fd9e..a380e8c86d4 100644
--- a/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts
+++ b/apps/studio/components/interfaces/Database/Backups/PITR/PITR.utils.ts
@@ -1,7 +1,7 @@
import dayjs from 'dayjs'
import { ALL_TIMEZONES } from './PITR.constants'
-import { Time, Timezone } from './PITR.types'
-import { ProjectSelectedAddon } from 'data/subscriptions/project-addons-query'
+import { Time } from './PITR.types'
+import { ProjectSelectedAddon } from 'data/subscriptions/types'
export const getPITRRetentionDuration = (addons: ProjectSelectedAddon[]) => {
const pitrAddon = addons.find((addon) => addon.type === 'pitr')
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx
index 591da335219..01706ebedb0 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/BillingBreakdown/BillingMetric.tsx
@@ -1,7 +1,7 @@
import * as Tooltip from '@radix-ui/react-tooltip'
import Link from 'next/link'
-import { OrgSubscription } from 'data/subscriptions/org-subscription-query'
+import { OrgSubscription } from 'data/subscriptions/types'
import { OrgUsageResponse } from 'data/usage/org-usage-query'
import { Button, IconChevronRight, IconPieChart } from 'ui'
import { Metric, USAGE_APPROACHING_THRESHOLD } from './BillingBreakdown.constants'
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx
index 707ab5c91c7..1b8e7a9f729 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/DowngradeModal.tsx
@@ -1,4 +1,4 @@
-import { OrgSubscription, ProjectAddon } from 'data/subscriptions/org-subscription-query'
+import { OrgSubscription, ProjectAddon } from 'data/subscriptions/types'
import { PricingInformation } from 'shared-data'
import { Alert, IconAlertOctagon, IconMinusCircle, IconPauseCircle, Modal } from 'ui'
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx
index f44ccfc31ac..29019f47d5c 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/ExitSurveyModal.tsx
@@ -4,7 +4,7 @@ import { useReducer, useRef, useState } from 'react'
import { useParams } from 'common'
import { useSendDowngradeFeedbackMutation } from 'data/feedback/exit-survey-send'
-import { OrgSubscription } from 'data/subscriptions/org-subscription-query'
+import { OrgSubscription } from 'data/subscriptions/types'
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
import { useFlag, useStore } from 'hooks'
import { Alert, Button, Input, Modal } from 'ui'
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx
index c3844d47c46..cfc042e5a11 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/Subscription/PlanUpdateSidePanel.tsx
@@ -10,7 +10,7 @@ import InformationBox from 'components/ui/InformationBox'
import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { useFreeProjectLimitCheckQuery } from 'data/organizations/free-project-limit-check-query'
import { useOrganizationBillingSubscriptionPreview } from 'data/organizations/organization-billing-subscription-preview'
-import { useOrgPlansQuery } from 'data/subscriptions/org-plans-query'
+import { OrgPlan } from 'data/subscriptions/types'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { useOrgSubscriptionUpdateMutation } from 'data/subscriptions/org-subscription-update-mutation'
import { SubscriptionTier } from 'data/subscriptions/types'
@@ -34,6 +34,7 @@ import EnterpriseCard from './EnterpriseCard'
import ExitSurveyModal from './ExitSurveyModal'
import MembersExceedLimitModal from './MembersExceedLimitModal'
import PaymentMethodSelection from './PaymentMethodSelection'
+import { useOrgPlansQuery } from 'data/subscriptions/org-plans-query'
const PlanUpdateSidePanel = () => {
const { ui } = useStore()
@@ -96,7 +97,7 @@ const PlanUpdateSidePanel = () => {
isSuccess: subscriptionPreviewInitialized,
} = useOrganizationBillingSubscriptionPreview({ tier: selectedTier, organizationSlug: slug })
- const availablePlans = plans ?? []
+ const availablePlans: OrgPlan[] = plans?.plans ?? []
const hasMembersExceedingFreeTierLimit = (membersExceededLimit || []).length > 0
const subscriptionPlanMeta = subscriptionsPlans.find((tier) => tier.id === selectedTier)
diff --git a/apps/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx b/apps/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx
index 5ae834caf3b..bad4868bcd6 100644
--- a/apps/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx
+++ b/apps/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx
@@ -104,12 +104,12 @@ const InvoicesSettings = () => {
{x.number}
-
+
{[InvoiceStatus.UNCOLLECTIBLE, InvoiceStatus.OPEN].includes(
- x.status as any
+ x.status as InvoiceStatus
) && (
- {computeInstance?.variant?.meta?.memory_gb ?? 1} GB
+ {meta?.memory_gb ?? 1} GB
@@ -276,21 +277,17 @@ const Addons = () => {
- {computeInstance?.variant?.meta?.cpu_cores ?? 2}-core {cpuArchitecture}{' '}
- {computeInstance?.variant?.meta?.cpu_dedicated ? '(Dedicated)' : '(Shared)'}
+ {meta?.cpu_cores ?? 2}-core {cpuArchitecture}{' '}
+ {meta?.cpu_dedicated ? '(Dedicated)' : '(Shared)'}
No. of direct connections
-
- {computeInstance?.variant?.meta?.connections_direct ?? 60}
-
+
{meta?.connections_direct ?? 60}
No. of pooler connections
-
- {computeInstance?.variant?.meta?.connections_pooler ?? 200}
-
+
{meta?.connections_pooler ?? 200}
@@ -306,9 +303,7 @@ const Addons = () => {
- {computeInstance?.variant?.meta?.max_disk_io_mbs?.toLocaleString() ??
- '2,085'}{' '}
- Mbps
+ {meta?.max_disk_io_mbs?.toLocaleString() ?? '2,085'} Mbps
@@ -325,9 +320,7 @@ const Addons = () => {
- {computeInstance?.variant?.meta?.baseline_disk_io_mbs?.toLocaleString() ??
- 87}{' '}
- Mbps
+ {meta?.baseline_disk_io_mbs?.toLocaleString() ?? 87} Mbps
diff --git a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx
index c324fa9a6cf..d23c3aaa614 100644
--- a/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx
+++ b/apps/studio/components/interfaces/Settings/Addons/ComputeInstanceSidePanel.tsx
@@ -32,6 +32,7 @@ import {
import * as Tooltip from '@radix-ui/react-tooltip'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
+import { AddonVariantId } from 'data/subscriptions/types'
const COMPUTE_CATEGORY_OPTIONS: {
id: 'micro' | 'optimized'
@@ -170,7 +171,11 @@ const ComputeInstanceSidePanel = () => {
if (selectedOption === 'ci_micro' && subscriptionCompute !== undefined) {
removeAddon({ projectRef, variant: subscriptionCompute.variant.identifier })
} else {
- updateAddon({ projectRef, type: 'compute_instance', variant: selectedOption })
+ updateAddon({
+ projectRef,
+ type: 'compute_instance',
+ variant: selectedOption as AddonVariantId,
+ })
}
}
diff --git a/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx
index 06a50441fb9..b1567c8d2e5 100644
--- a/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx
+++ b/apps/studio/components/interfaces/Settings/Addons/CustomDomainSidePanel.tsx
@@ -22,6 +22,7 @@ import {
SidePanel,
} from 'ui'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
+import { AddonVariantId } from 'data/subscriptions/types'
const CustomDomainSidePanel = () => {
const { ui } = useStore()
@@ -121,7 +122,7 @@ const CustomDomainSidePanel = () => {
if (selectedOption === 'cd_none' && subscriptionCDOption !== undefined) {
removeAddon({ projectRef, variant: subscriptionCDOption.variant.identifier })
} else {
- updateAddon({ projectRef, type: 'custom_domain', variant: selectedOption })
+ updateAddon({ projectRef, type: 'custom_domain', variant: selectedOption as AddonVariantId })
}
}
diff --git a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx
index 5101f044af8..75a2c7d898c 100644
--- a/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx
+++ b/apps/studio/components/interfaces/Settings/Addons/PITRSidePanel.tsx
@@ -26,6 +26,7 @@ import {
} from 'ui'
import { useOrgSubscriptionQuery } from 'data/subscriptions/org-subscription-query'
import { AlertTriangleIcon } from 'lucide-react'
+import { AddonVariantId } from 'data/subscriptions/types'
const PITR_CATEGORY_OPTIONS: {
id: 'off' | 'on'
@@ -149,7 +150,7 @@ const PITRSidePanel = () => {
if (selectedOption === 'pitr_0' && subscriptionPitr !== undefined) {
removeAddon({ projectRef, variant: subscriptionPitr.variant.identifier })
} else {
- updateAddon({ projectRef, type: 'pitr', variant: selectedOption })
+ updateAddon({ projectRef, type: 'pitr', variant: selectedOption as AddonVariantId })
}
}
diff --git a/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts b/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts
index bdabec39cc9..d500548f006 100644
--- a/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts
+++ b/apps/studio/components/interfaces/Settings/Logs/Logs.utils.ts
@@ -6,7 +6,7 @@ import logConstants from 'shared-data/logConstants'
import BackwardIterator from 'components/ui/CodeEditor/Providers/BackwardIterator'
import uniqBy from 'lodash/uniqBy'
import { useEffect } from 'react'
-import { PlanId } from 'data/subscriptions/org-subscription-query'
+import { PlanId } from 'data/subscriptions/types'
/**
* Convert a micro timestamp from number/string to iso timestamp
diff --git a/apps/studio/data/api.d.ts b/apps/studio/data/api.d.ts
index 9b86b55740c..85e1b46997a 100644
--- a/apps/studio/data/api.d.ts
+++ b/apps/studio/data/api.d.ts
@@ -236,7 +236,7 @@ export interface paths {
}
'/platform/organizations/{slug}/payments/setup-intent': {
/** Sets up a payment method */
- post: operations['SetupIntentController_setUpPaymentMethod']
+ post: operations['SetupIntentOrgController_setUpPaymentMethod']
}
'/platform/organizations/{slug}/billing/subscription': {
/** Gets the current subscription */
@@ -467,6 +467,10 @@ export interface paths {
/** Updates project's content */
patch: operations['ContentController_updateContent']
}
+ '/platform/projects/{ref}/daily-stats': {
+ /** Gets daily project stats */
+ get: operations['DailyStatsController_getDailyStats']
+ }
'/platform/projects/{ref}/databases': {
/** Gets non-removed databases of a specified project */
get: operations['DatabasesController_getDatabases']
@@ -1659,6 +1663,10 @@ export interface paths {
/** List members of an organization */
get: operations['V1OrganizationMembersController_v1ListOrganizationMembers']
}
+ '/v1/organizations/{slug}': {
+ /** Gets information about the organization */
+ get: operations['V1OrganizationSlugController_getOrganization']
+ }
'/v1/oauth/authorize': {
/** Authorize user through oauth */
get: operations['OAuthController_authorize']
@@ -2713,6 +2721,9 @@ export interface components {
stripeAccount?: string
}
}
+ HCaptchaBody: {
+ hcaptchaToken: string
+ }
SetupIntentResponse: {
id: string
object: string
@@ -2746,8 +2757,10 @@ export interface components {
stripeAccount?: string
}
}
+ /** @enum {string} */
+ BillingPlanId: 'free' | 'pro' | 'team' | 'enterprise'
BillingSubscriptionPlan: {
- id: Record
+ id: components['schemas']['BillingPlanId']
name: string
price: number
}
@@ -2756,18 +2769,38 @@ export interface components {
supabase_prod_id: string
price: number
}
+ /** @enum {string} */
+ ProjectAddonType: 'custom_domain' | 'compute_instance' | 'pitr'
+ /** @enum {string} */
+ AddonVariantId:
+ | 'ci_small'
+ | 'ci_medium'
+ | 'ci_large'
+ | 'ci_xlarge'
+ | 'ci_2xlarge'
+ | 'ci_4xlarge'
+ | 'ci_8xlarge'
+ | 'ci_12xlarge'
+ | 'ci_16xlarge'
+ | 'cd_default'
+ | 'pitr_7'
+ | 'pitr_14'
+ | 'pitr_28'
+ /** @enum {string} */
+ ProjectAddonVariantPricingType: 'fixed' | 'usage'
+ /** @enum {string} */
+ ProjectAddonPricingInterval: 'monthly' | 'hourly'
ProjectAddonVariantResponse: {
- identifier: string
+ identifier: components['schemas']['AddonVariantId']
+ price_type: components['schemas']['ProjectAddonVariantPricingType']
+ price_interval: components['schemas']['ProjectAddonPricingInterval']
name: string
price_description: string
- price_type: Record
- price_interval: Record
price: number
meta?: Record
}
SelectedAddonResponse: {
- /** @enum {string} */
- type: 'custom_domain' | 'compute_instance' | 'pitr'
+ type: components['schemas']['ProjectAddonType']
variant: components['schemas']['ProjectAddonVariantResponse']
}
BillingProjectAddonResponse: {
@@ -2827,9 +2860,9 @@ export interface components {
expiry_year: number
}
ScheduledPlanChange: {
+ target_plan: components['schemas']['BillingPlanId']
/** Format: date-time */
at: string
- target_plan: Record
usage_billing_enabled: boolean
}
GetSubscriptionResponse: {
@@ -2856,6 +2889,21 @@ export interface components {
/** @enum {string} */
tier: 'tier_payg' | 'tier_pro' | 'tier_free' | 'tier_team' | 'tier_enterprise'
}
+ /** @enum {string} */
+ BillingPlanChangeType: 'upgrade' | 'downgrade' | 'none'
+ /** @enum {string} */
+ BillingPlanEffectiveAt: 'now' | 'end_of_billing_period' | 'none'
+ PlanResponse: {
+ id: components['schemas']['BillingPlanId']
+ change_type: components['schemas']['BillingPlanChangeType']
+ effective_at: components['schemas']['BillingPlanEffectiveAt']
+ name: string
+ price: number
+ is_current: boolean
+ }
+ PlansResponse: {
+ plans: components['schemas']['PlanResponse'][]
+ }
UpcomingInvoice: Record
ColumnPrivilege: {
grantor: string
@@ -3749,6 +3797,8 @@ export interface components {
amount: number
}
PreviewProjectTransferResponse: {
+ source_subscription_plan: components['schemas']['BillingPlanId']
+ target_subscription_plan: components['schemas']['BillingPlanId']
valid: boolean
warnings: components['schemas']['PreviewTransferInfo'][]
errors: components['schemas']['PreviewTransferInfo'][]
@@ -3761,8 +3811,6 @@ export interface components {
credits_on_source_organization: number
costs_on_target_organization: number
charge_on_target_organization: number
- source_subscription_plan: Record
- target_subscription_plan: Record | null
source_invoice_items: components['schemas']['PreviewTransferInvoiceItem'][]
target_invoice_items: components['schemas']['PreviewTransferInvoiceItem'][]
}
@@ -3881,8 +3929,7 @@ export interface components {
fileSizeLimit: number
}
AvailableAddonResponse: {
- /** @enum {string} */
- type: 'custom_domain' | 'compute_instance' | 'pitr'
+ type: components['schemas']['ProjectAddonType']
name: string
variants: components['schemas']['ProjectAddonVariantResponse'][]
}
@@ -3892,9 +3939,8 @@ export interface components {
available_addons: components['schemas']['AvailableAddonResponse'][]
}
UpdateAddonBody: {
- addon_variant: Record
- /** @enum {string} */
- addon_type: 'custom_domain' | 'compute_instance' | 'pitr'
+ addon_variant: components['schemas']['AddonVariantId']
+ addon_type: components['schemas']['ProjectAddonType']
}
ServiceApiKey: {
api_key_encrypted?: string
@@ -4384,9 +4430,8 @@ export interface components {
expiry_time: string
}
UpdateAddonAdminBody: {
- addon_variant: Record
- /** @enum {string} */
- addon_type: 'custom_domain' | 'compute_instance' | 'pitr'
+ addon_variant: components['schemas']['AddonVariantId']
+ addon_type: components['schemas']['ProjectAddonType']
price_id?: string
}
DatabaseResponse: {
@@ -4775,6 +4820,12 @@ export interface components {
role_name: string
mfa_enabled: boolean
}
+ V1OrganizationSlugResponse: {
+ plan?: components['schemas']['BillingPlanId']
+ opt_in_tags: ('AI_SQL_GENERATOR_OPT_IN' | 'PREVIEW_BRANCHES_OPT_IN')[]
+ id: string
+ name: string
+ }
OAuthTokenBody: {
/** @enum {string} */
grant_type: 'authorization_code' | 'refresh_token'
@@ -4896,8 +4947,7 @@ export interface components {
supabase_org_id: string
}
FlyOrganization: {
- /** @enum {string} */
- plan: 'free' | 'pro' | 'team' | 'enterprise'
+ plan: components['schemas']['BillingPlanId']
id: string
supabase_org_id: string
name: string
@@ -6381,13 +6431,27 @@ export interface operations {
}
}
/** Sets up a payment method */
- SetupIntentController_setUpPaymentMethod: {
+ SetupIntentOrgController_setUpPaymentMethod: {
+ parameters: {
+ path: {
+ /** @description Organization slug */
+ slug: string
+ }
+ }
+ requestBody: {
+ content: {
+ 'application/json': components['schemas']['HCaptchaBody']
+ }
+ }
responses: {
201: {
content: {
'application/json': components['schemas']['SetupIntentResponse']
}
}
+ 403: {
+ content: never
+ }
/** @description Failed to set up a payment method */
500: {
content: never
@@ -6501,7 +6565,7 @@ export interface operations {
responses: {
200: {
content: {
- 'application/json': Record
+ 'application/json': components['schemas']['PlansResponse']
}
}
403: {
@@ -8461,6 +8525,32 @@ export interface operations {
}
}
}
+ /** Gets daily project stats */
+ DailyStatsController_getDailyStats: {
+ parameters: {
+ query: {
+ attribute: string
+ interval: string
+ endDate: string
+ startDate: string
+ }
+ path: {
+ /** @description Project ref */
+ ref: string
+ }
+ }
+ responses: {
+ 200: {
+ content: {
+ 'application/json': Record
+ }
+ }
+ /** @description Failed to get daily project stats */
+ 500: {
+ content: never
+ }
+ }
+ }
/** Gets non-removed databases of a specified project */
DatabasesController_getDatabases: {
parameters: {
@@ -9328,6 +9418,7 @@ export interface operations {
path: {
/** @description Project ref */
ref: string
+ addon_variant: components['schemas']['AddonVariantId']
}
}
responses: {
@@ -9843,6 +9934,25 @@ export interface operations {
}
}
}
+ /** Sets up a payment method */
+ SetupIntentController_setUpPaymentMethod: {
+ requestBody: {
+ content: {
+ 'application/json': components['schemas']['HCaptchaBody']
+ }
+ }
+ responses: {
+ 201: {
+ content: {
+ 'application/json': components['schemas']['SetupIntentResponse']
+ }
+ }
+ /** @description Failed to set up a payment method */
+ 500: {
+ content: never
+ }
+ }
+ }
/** Sends analytics server event */
TelemetryEventController_sendServerEvent: {
requestBody: {
@@ -10871,6 +10981,7 @@ export interface operations {
path: {
/** @description Project ref */
ref: string
+ addon_variant: components['schemas']['AddonVariantId']
}
}
responses: {
@@ -12398,6 +12509,21 @@ export interface operations {
}
}
}
+ /** Gets information about the organization */
+ V1OrganizationSlugController_getOrganization: {
+ parameters: {
+ path: {
+ slug: string
+ }
+ }
+ responses: {
+ 200: {
+ content: {
+ 'application/json': components['schemas']['V1OrganizationSlugResponse']
+ }
+ }
+ }
+ }
/** Authorize user through oauth */
OAuthController_authorize: {
parameters: {
diff --git a/apps/studio/data/invoices/invoices-overdue-query.ts b/apps/studio/data/invoices/invoices-overdue-query.ts
index 4cc20b8a736..a34b563e09f 100644
--- a/apps/studio/data/invoices/invoices-overdue-query.ts
+++ b/apps/studio/data/invoices/invoices-overdue-query.ts
@@ -1,22 +1,19 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
-import { get } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { get } from 'data/fetchers'
import { invoicesKeys } from './keys'
+import { components } from 'data/api'
-export type OverdueInvoicesResponse = {
- id: string
- organization_id: number
-}
+export type OverdueInvoicesResponse = components['schemas']['OverdueInvoiceCount']
export async function getOverdueInvoices(signal?: AbortSignal) {
- const response = await get(`${API_URL}/stripe/invoices/overdue`, {
+ const { data, error } = await get('/platform/stripe/invoices/overdue', {
signal,
})
- if (response.error) {
- throw response.error
+ if (error) {
+ throw error
}
- return response as OverdueInvoicesResponse[]
+ return data
}
export type OverdueInvoicesData = Awaited>
diff --git a/apps/studio/data/stripe/setup-intent-mutation.ts b/apps/studio/data/stripe/setup-intent-mutation.ts
index e6fab19727f..cad5489d964 100644
--- a/apps/studio/data/stripe/setup-intent-mutation.ts
+++ b/apps/studio/data/stripe/setup-intent-mutation.ts
@@ -10,7 +10,6 @@ export type SetupIntentVariables = {
export async function setupIntent({ hcaptchaToken }: SetupIntentVariables) {
const { data, error } = await post('/platform/stripe/setup-intent', {
- // @ts-ignore [Joshen] API seems to be having the wrong spec
body: { hcaptchaToken },
})
if (error) throw error
diff --git a/apps/studio/data/subscriptions/keys.ts b/apps/studio/data/subscriptions/keys.ts
index 91986c7dde9..956211a7a85 100644
--- a/apps/studio/data/subscriptions/keys.ts
+++ b/apps/studio/data/subscriptions/keys.ts
@@ -1,5 +1,3 @@
-// [Joshen TODO] To remove subscription V2 after v2 is launched and stable to deprecate old billing ui + endpoints
-
export const subscriptionKeys = {
orgSubscription: (orgSlug: string | undefined) =>
['organizations', orgSlug, 'subscription'] as const,
diff --git a/apps/studio/data/subscriptions/org-plans-query.ts b/apps/studio/data/subscriptions/org-plans-query.ts
index 1cfd667e528..a3cb6ea3b9e 100644
--- a/apps/studio/data/subscriptions/org-plans-query.ts
+++ b/apps/studio/data/subscriptions/org-plans-query.ts
@@ -1,28 +1,21 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
-import { get } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { get } from 'data/fetchers'
import { subscriptionKeys } from './keys'
export type OrgPlansVariables = {
orgSlug?: string
}
-export type OrgPlansResponse = {
- id: 'free' | 'pro' | 'team' | 'enterprise'
- name: string
- price: number
- is_current: boolean
- change_type: 'downgrade' | 'upgrade' | 'none'
- effective_at: string
-}[]
-
export async function getOrgPlans({ orgSlug }: OrgPlansVariables, signal?: AbortSignal) {
if (!orgSlug) throw new Error('orgSlug is required')
- const response = await get(`${API_URL}/organizations/${orgSlug}/billing/plans`, { signal })
- if (response.error) throw response.error
+ const { error, data } = await get('/platform/organizations/{slug}/billing/plans', {
+ params: { path: { slug: orgSlug } },
+ signal,
+ })
+ if (error) throw error
- return response.plans as OrgPlansResponse
+ return data
}
export type OrgPlansData = Awaited>
diff --git a/apps/studio/data/subscriptions/org-subscription-query.ts b/apps/studio/data/subscriptions/org-subscription-query.ts
index 75c5f6526cb..ce4078a0087 100644
--- a/apps/studio/data/subscriptions/org-subscription-query.ts
+++ b/apps/studio/data/subscriptions/org-subscription-query.ts
@@ -1,6 +1,5 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
-import { get } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { get } from 'data/fetchers'
import { subscriptionKeys } from './keys'
import { ResponseError } from 'types'
@@ -8,77 +7,19 @@ export type OrgSubscriptionVariables = {
orgSlug?: string
}
-export type PlanId = 'free' | 'pro' | 'team' | 'enterprise'
-
-export type ProjectAddon = {
- addons: {
- type: 'custom_domain' | 'compute_instance' | 'pitr'
- variant: {
- identifier: string
- name: string
- price: number
- price_description: string
- price_interval: string
- price_type: string
- }
- }[]
- name: string
- ref: string
-}
-
-export type OrgSubscription = {
- billing_cycle_anchor: number
- current_period_start: number
- current_period_end: number
- next_invoice_at: number
- usage_billing_enabled: boolean
- plan: {
- id: PlanId
- name: string
- price: number
- }
- addons: {
- name: string
- supabase_prod_id: string
- price: number
- }[]
- usage_fees: {
- metric: string
- pricingStrategy: 'UNIT' | 'PACKAGE'
- pricingOptions: {
- perUnitPrice?: number
- packagePrice?: number
- packageSize?: number
- freeUnits: number
- }
- }[]
- payment_method_id?: string
- payment_method_type: 'invoice' | 'card' | 'none'
- payment_method_card_details?: {
- last_4_digits: string
- brand: string
- expiry_month: number
- expiry_year: number
- }
- project_addons: ProjectAddon[]
- billing_via_partner?: boolean
- scheduled_plan_change: {
- at: string
- target_plan: PlanId
- usage_billing_enabled: boolean
- } | null
-}
-
export async function getOrgSubscription(
{ orgSlug }: OrgSubscriptionVariables,
signal?: AbortSignal
) {
if (!orgSlug) throw new Error('orgSlug is required')
- const response = await get(`${API_URL}/organizations/${orgSlug}/billing/subscription`, { signal })
- if (response.error) throw response.error
+ const { error, data } = await get('/platform/organizations/{slug}/billing/subscription', {
+ params: { path: { slug: orgSlug } },
+ signal,
+ })
+ if (error) throw error
- return response as OrgSubscription
+ return data
}
export type OrgSubscriptionData = Awaited>
diff --git a/apps/studio/data/subscriptions/org-subscription-update-mutation.ts b/apps/studio/data/subscriptions/org-subscription-update-mutation.ts
index 464dbe8c88d..da5490d4db4 100644
--- a/apps/studio/data/subscriptions/org-subscription-update-mutation.ts
+++ b/apps/studio/data/subscriptions/org-subscription-update-mutation.ts
@@ -1,6 +1,5 @@
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
-import { isResponseOk, put } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { put } from 'data/fetchers'
import { toast } from 'react-hot-toast'
import { ResponseError } from 'types/base'
import { subscriptionKeys } from './keys'
@@ -22,15 +21,22 @@ export async function updateOrgSubscription({
if (!slug) throw new Error('slug is required')
if (!tier) throw new Error('tier is required')
- const payload: { tier: string; payment_method?: string } = { tier }
+ const payload: { tier: SubscriptionTier; payment_method?: string } = { tier }
if (paymentMethod !== undefined) payload.payment_method = paymentMethod
- const response = await put(`${API_URL}/organizations/${slug}/billing/subscription`, payload)
- if (!isResponseOk(response)) {
- throw response.error
+ const { error, data } = await put(`/platform/organizations/{slug}/billing/subscription`, {
+ body: {
+ payment_method: payload.payment_method,
+ tier: payload.tier,
+ },
+ params: { path: { slug } },
+ })
+
+ if (error) {
+ throw error
}
- return response
+ return data
}
type OrgSubscriptionUpdateData = Awaited>
diff --git a/apps/studio/data/subscriptions/project-addon-remove-mutation.ts b/apps/studio/data/subscriptions/project-addon-remove-mutation.ts
index 75a930727fe..5c0bcf06b87 100644
--- a/apps/studio/data/subscriptions/project-addon-remove-mutation.ts
+++ b/apps/studio/data/subscriptions/project-addon-remove-mutation.ts
@@ -1,18 +1,14 @@
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'react-hot-toast'
-import { delete_ } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { del } from 'data/fetchers'
import { ResponseError } from 'types'
import { subscriptionKeys } from './keys'
+import { AddonVariantId } from './types'
export type ProjectAddonRemoveVariables = {
projectRef: string
- variant: string
-}
-
-export type ProjectAddonRemoveResponse = {
- error?: any
+ variant: AddonVariantId
}
export async function removeSubscriptionAddon({
@@ -22,12 +18,18 @@ export async function removeSubscriptionAddon({
if (!projectRef) throw new Error('projectRef is required')
if (!variant) throw new Error('variant is required')
- const response = (await delete_(
- `${API_URL}/projects/${projectRef}/billing/addons/${variant}`
- )) as ProjectAddonRemoveResponse
- if (response.error) throw response.error
+ const { data, error } = await del(`/platform/projects/{ref}/billing/addons/{addon_variant}`, {
+ params: {
+ path: {
+ ref: projectRef,
+ addon_variant: variant,
+ },
+ },
+ })
- return response
+ if (error) throw error
+
+ return data
}
type ProjectAddonRemoveData = Awaited>
diff --git a/apps/studio/data/subscriptions/project-addon-update-mutation.ts b/apps/studio/data/subscriptions/project-addon-update-mutation.ts
index e8ad01d8ebe..d135b153ff1 100644
--- a/apps/studio/data/subscriptions/project-addon-update-mutation.ts
+++ b/apps/studio/data/subscriptions/project-addon-update-mutation.ts
@@ -1,19 +1,15 @@
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'react-hot-toast'
-import { post } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { post } from 'data/fetchers'
import { ResponseError } from 'types'
import { subscriptionKeys } from './keys'
+import { AddonVariantId, ProjectAddonType } from './types'
export type ProjectAddonUpdateVariables = {
projectRef: string
- variant: string
- type: 'custom_domain' | 'compute_instance' | 'pitr'
-}
-
-export type ProjectAddonUpdateResponse = {
- error?: any
+ variant: AddonVariantId
+ type: ProjectAddonType
}
export async function updateSubscriptionAddon({
@@ -25,13 +21,21 @@ export async function updateSubscriptionAddon({
if (!variant) throw new Error('variant is required')
if (!type) throw new Error('type is required')
- const response = (await post(`${API_URL}/projects/${projectRef}/billing/addons`, {
- addon_type: type,
- addon_variant: variant,
- })) as ProjectAddonUpdateResponse
- if (response.error) throw response.error
+ const { data, error } = await post(`/platform/projects/{ref}/billing/addons`, {
+ params: {
+ path: {
+ ref: projectRef,
+ },
+ },
+ body: {
+ addon_type: type,
+ addon_variant: variant,
+ },
+ })
- return response
+ if (error) throw error
+
+ return data
}
type ProjectAddonUpdateData = Awaited>
diff --git a/apps/studio/data/subscriptions/project-addons-query.ts b/apps/studio/data/subscriptions/project-addons-query.ts
index f5f38058d40..7d8533562f8 100644
--- a/apps/studio/data/subscriptions/project-addons-query.ts
+++ b/apps/studio/data/subscriptions/project-addons-query.ts
@@ -1,6 +1,5 @@
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
-import { get } from 'lib/common/fetch'
-import { API_URL } from 'lib/constants'
+import { get } from 'data/fetchers'
import { subscriptionKeys } from './keys'
import { ResponseError } from 'types'
@@ -8,54 +7,20 @@ export type ProjectAddonsVariables = {
projectRef?: string
}
-export type ProjectAddonType = 'compute_instance' | 'pitr' | 'custom_domain'
-
-export type ProjectAddonVariant = {
- identifier: string
- name: string
- price: number
- price_description: string
- price_interval: 'monthly' | 'hourly'
- price_type: 'fixed' | 'usage'
- meta?: ProjectAddonVariantMeta
-}
-
-export interface ProjectAddonVariantMeta {
- cpu_cores?: number
- cpu_dedicated?: boolean
- baseline_disk_io_mbs?: number
- max_disk_io_mbs?: number
- memory_gb?: number
- connections_direct?: number
- connections_pooler?: number
- backup_duration_days?: number
-}
-
-export type ProjectSelectedAddon = {
- type: ProjectAddonType
- variant: ProjectAddonVariant
-}
-
-export type ProjectAddonsResponse = {
- ref: string
- selected_addons: ProjectSelectedAddon[]
- available_addons: {
- name: string
- type: ProjectAddonType
- variants: ProjectAddonVariant[]
- }[]
-}
-
export async function getProjectAddons(
{ projectRef }: ProjectAddonsVariables,
signal?: AbortSignal
) {
if (!projectRef) throw new Error('projectRef is required')
- const response = await get(`${API_URL}/projects/${projectRef}/billing/addons`, { signal })
- if (response.error) throw response.error
+ const { error, data } = await get(`/platform/projects/{ref}/billing/addons`, {
+ params: { path: { ref: projectRef } },
+ signal,
+ })
- return response as ProjectAddonsResponse
+ if (error) throw error
+
+ return data
}
export type ProjectAddonsData = Awaited>
diff --git a/apps/studio/data/subscriptions/types.ts b/apps/studio/data/subscriptions/types.ts
index d0755cb9406..e4ec4475247 100644
--- a/apps/studio/data/subscriptions/types.ts
+++ b/apps/studio/data/subscriptions/types.ts
@@ -1,6 +1,34 @@
+import { components } from 'data/api'
+
export type SubscriptionTier =
| 'tier_free'
| 'tier_pro'
| 'tier_payg'
| 'tier_team'
| 'tier_enterprise'
+
+export type AddonVariantId = components['schemas']['AddonVariantId']
+
+export type OrgSubscription = components['schemas']['GetSubscriptionResponse']
+
+export type ProjectAddon = components['schemas']['BillingProjectAddonResponse']
+
+export type PlanId = components['schemas']['BillingPlanId']
+
+export type OrgPlan = components['schemas']['PlanResponse']
+
+export type ProjectAddonType = components['schemas']['ProjectAddonType']
+
+export interface ProjectAddonVariantMeta {
+ cpu_cores?: number
+ cpu_dedicated?: boolean
+ baseline_disk_io_mbs?: number
+ max_disk_io_mbs?: number
+ memory_gb?: number
+ connections_direct?: number
+ connections_pooler?: number
+ backup_duration_days?: number
+}
+
+export type ProjectSelectedAddon = components['schemas']['SelectedAddonResponse']
+export type ProjectAvailableAddon = components['schemas']['AvailableAddonResponse']