From 22dd096928128be82406002be45de0ecd952afcd Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Wed, 12 Feb 2025 17:12:05 +0800 Subject: [PATCH] Update several files to use data fetcher methods --- .../integrations-query-org-only.ts | 24 ++++----- ...el-installed-connection-delete-mutation.ts | 26 ++++----- .../data/integrations/integrations.types.ts | 5 -- .../vercel-integration-create-mutation.ts | 28 +++++----- .../oauth/authorized-app-revoke-mutation.ts | 12 +++-- .../data/oauth/authorized-apps-query.ts | 15 +++--- .../data/oauth/oauth-app-create-mutation.ts | 30 +++++------ .../data/oauth/oauth-app-delete-mutation.ts | 12 +++-- apps/studio/data/oauth/oauth-apps-query.ts | 27 ++++------ .../projects/project-transfer-mutation.ts | 22 ++++---- .../project-transfer-preview-query.ts | 54 ++++--------------- 11 files changed, 100 insertions(+), 155 deletions(-) diff --git a/apps/studio/data/integrations/integrations-query-org-only.ts b/apps/studio/data/integrations/integrations-query-org-only.ts index 93872903086..1f530765a1b 100644 --- a/apps/studio/data/integrations/integrations-query-org-only.ts +++ b/apps/studio/data/integrations/integrations-query-org-only.ts @@ -1,25 +1,21 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' +import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' -import type { Integration, IntegrationsVariables } from './integrations.types' import { integrationKeys } from './keys' -export type IntegrationsResponse = Integration[] +type IntegrationsVariables = { + orgSlug?: string +} export async function getIntegrations({ orgSlug }: IntegrationsVariables, signal?: AbortSignal) { - if (!orgSlug) { - throw new Error('orgSlug is required') - } - const response = await get(`${API_URL}/integrations/${orgSlug}?expand=true`, { - signal, - }) - if (response.error) { - throw response.error - } + if (!orgSlug) throw new Error('orgSlug is required') - return response as IntegrationsResponse + const { data, error } = await get('/platform/integrations/{slug}', { + params: { path: { slug: orgSlug } }, + }) + if (error) handleError(error) + return data } export type IntegrationsData = Awaited> diff --git a/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts b/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts index 2f98285d5ad..13c93f60cce 100644 --- a/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts +++ b/apps/studio/data/integrations/integrations-vercel-installed-connection-delete-mutation.ts @@ -1,8 +1,8 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { delete_, isResponseOk } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' import { toast } from 'sonner' -import type { ResponseError, UserContent } from 'types' + +import { del, handleError } from 'data/fetchers' +import type { ResponseError } from 'types' import { integrationKeys } from './keys' type DeleteVariables = { @@ -15,21 +15,15 @@ export async function deleteConnection( { organization_integration_id, id }: DeleteVariables, signal?: AbortSignal ) { - if (!organization_integration_id) { - throw new Error('organization_integration_id is required') - } + if (!organization_integration_id) throw new Error('organization_integration_id is required') - const response = await delete_( - `${API_URL}/integrations/vercel/connections/${id}`, - { organization_integration_id }, - { signal } - ) + const { data, error } = await del('/platform/integrations/vercel/connections/{connection_id}', { + params: { path: { connection_id: id } }, + signal, + }) - if (!isResponseOk(response)) { - throw response.error - } - - return response + if (error) handleError(error) + return data } type DeleteContentData = Awaited> diff --git a/apps/studio/data/integrations/integrations.types.ts b/apps/studio/data/integrations/integrations.types.ts index f79843b59e5..cc5c7f3ccce 100644 --- a/apps/studio/data/integrations/integrations.types.ts +++ b/apps/studio/data/integrations/integrations.types.ts @@ -160,10 +160,6 @@ export type IntegrationProjectConnection = { metadata: Imetadata } -export type IntegrationsVariables = { - orgSlug?: string -} - export type IntegrationProjectConnectionPayload = { foreignProjectId: string supabaseProjectId: string @@ -177,7 +173,6 @@ export type userDetails = { primary_email: string } type addedBy = userDetails -type updatedBy = userDetails export type IntegrationName = 'Vercel' | 'GitHub' // | 'Netlify' export type VercelAccountType = 'Team' | 'Personal' diff --git a/apps/studio/data/integrations/vercel-integration-create-mutation.ts b/apps/studio/data/integrations/vercel-integration-create-mutation.ts index 3d8b5c19c3e..f3d1315c29a 100644 --- a/apps/studio/data/integrations/vercel-integration-create-mutation.ts +++ b/apps/studio/data/integrations/vercel-integration-create-mutation.ts @@ -1,7 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' -import { post } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' import { toast } from 'sonner' + +import { handleError, post } from 'data/fetchers' import type { ResponseError } from 'types' import { integrationKeys } from './keys' @@ -24,19 +24,21 @@ export async function createVercelIntegration({ source, teamId, }: VercelIntegrationCreateVariables) { - const response = await post(`${API_URL}/integrations/vercel`, { - code, - configuration_id: configurationId, - organization_slug: orgSlug, - metadata, - source, - teamId, + const { data, error } = await post('/platform/integrations/vercel', { + body: { + code, + configuration_id: configurationId, + organization_slug: orgSlug, + metadata: metadata as Record, + source, + teamId, + }, }) - if (response.error) { - throw response.error - } - return response + if (error) handleError(error) + // [Joshen] API isn't typed on this endpoint + // https://github.com/supabase/infrastructure/blob/develop/api/src/routes/platform/integrations/vercel/vercel-integration.controller.ts#L50 + return data as { id: string } } type VercelIntegrationCreateData = Awaited> diff --git a/apps/studio/data/oauth/authorized-app-revoke-mutation.ts b/apps/studio/data/oauth/authorized-app-revoke-mutation.ts index 105f164afec..9077e1f550f 100644 --- a/apps/studio/data/oauth/authorized-app-revoke-mutation.ts +++ b/apps/studio/data/oauth/authorized-app-revoke-mutation.ts @@ -1,8 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { post } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' +import { handleError, post } from 'data/fetchers' import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' @@ -15,9 +14,12 @@ export async function revokeAuthorizedApp({ id, slug }: AuthorizedAppRevokeVaria if (!id) throw new Error('App ID is required') if (!slug) throw new Error('Organization slug is required') - const response = await post(`${API_URL}/organizations/${slug}/oauth/apps/${id}/revoke`, {}) - if (response.error) throw response.error - return response + const { data, error } = await post('/platform/organizations/{slug}/oauth/apps/{id}/revoke', { + params: { path: { slug, id } }, + }) + + if (error) handleError(error) + return data } type AuthorizedAppRevokeData = Awaited> diff --git a/apps/studio/data/oauth/authorized-apps-query.ts b/apps/studio/data/oauth/authorized-apps-query.ts index fcf8f11cf0d..7a9d254b117 100644 --- a/apps/studio/data/oauth/authorized-apps-query.ts +++ b/apps/studio/data/oauth/authorized-apps-query.ts @@ -1,8 +1,8 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' -import { oauthAppKeys } from './keys' + +import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' +import { oauthAppKeys } from './keys' export type AuthorizedAppsVariables = { slug?: string @@ -19,11 +19,12 @@ export type AuthorizedApp = { export async function getAuthorizedApps({ slug }: AuthorizedAppsVariables, signal?: AbortSignal) { if (!slug) throw new Error('Organization slug is required') - const response = await get(`${API_URL}/organizations/${slug}/oauth/apps?type=authorized`, { - signal, + const { data, error } = await get('/platform/organizations/{slug}/oauth/apps', { + params: { path: { slug }, query: { type: 'authorized' } }, }) - if (response.error) throw response.error - return response as AuthorizedApp[] + + if (error) handleError(error) + return data } export type AuthorizedAppsData = Awaited> diff --git a/apps/studio/data/oauth/oauth-app-create-mutation.ts b/apps/studio/data/oauth/oauth-app-create-mutation.ts index ee07dbfa183..6092b3f340d 100644 --- a/apps/studio/data/oauth/oauth-app-create-mutation.ts +++ b/apps/studio/data/oauth/oauth-app-create-mutation.ts @@ -2,8 +2,8 @@ import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { post } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' +import { components } from 'api-types' +import { handleError, post } from 'data/fetchers' import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' @@ -16,11 +16,7 @@ export type OAuthAppCreateVariables = { redirect_uris: string[] } -export type OAuthAppCreateResponse = { - id: string - client_id: string - client_secret: string -} +export type OAuthAppCreateResponse = components['schemas']['CreateOAuthAppResponse'] export async function createOAuthApp({ slug, @@ -30,15 +26,19 @@ export async function createOAuthApp({ scopes, redirect_uris, }: OAuthAppCreateVariables) { - const response = await post(`${API_URL}/organizations/${slug}/oauth/apps`, { - name, - website, - icon, - scopes, - redirect_uris, + const { data, error } = await post('/platform/organizations/{slug}/oauth/apps', { + params: { path: { slug } }, + body: { + name, + website, + icon, + scopes, + redirect_uris, + }, }) - if (response.error) throw response.error - return response as OAuthAppCreateResponse + + if (error) handleError(error) + return data } type OAuthAppCreateData = Awaited> diff --git a/apps/studio/data/oauth/oauth-app-delete-mutation.ts b/apps/studio/data/oauth/oauth-app-delete-mutation.ts index e0663b14984..4bf0ca78e47 100644 --- a/apps/studio/data/oauth/oauth-app-delete-mutation.ts +++ b/apps/studio/data/oauth/oauth-app-delete-mutation.ts @@ -1,8 +1,7 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { delete_ } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' +import { del, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' @@ -15,9 +14,12 @@ export async function deleteOAuthApp({ id, slug }: OAuthAppDeleteVariables) { if (!id) throw new Error('OAuth app ID is required') if (!slug) throw new Error('Organization slug is required') - const response = await delete_(`${API_URL}/organizations/${slug}/oauth/apps/${id}?type=published`) - if (response.error) throw response.error - return response + const { data, error } = await del('/platform/organizations/{slug}/oauth/apps/{id}', { + params: { path: { slug, id } }, + }) + + if (error) handleError(error) + return data } type OAuthAppDeleteData = Awaited> diff --git a/apps/studio/data/oauth/oauth-apps-query.ts b/apps/studio/data/oauth/oauth-apps-query.ts index 63ea17efcd4..e8acb2ea9c5 100644 --- a/apps/studio/data/oauth/oauth-apps-query.ts +++ b/apps/studio/data/oauth/oauth-apps-query.ts @@ -1,7 +1,7 @@ -import type { OAuthScope } from '@supabase/shared-types/out/constants' import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { get } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' + +import { components } from 'api-types' +import { get, handleError } from 'data/fetchers' import type { ResponseError } from 'types' import { oauthAppKeys } from './keys' @@ -9,26 +9,17 @@ export type OAuthAppsVariables = { slug?: string } -export type OAuthApp = { - id: string - icon: string | null - client_id: string - client_secret_alias: string - created_at: string - name: string - website: string - scopes: OAuthScope[] - redirect_uris: string[] -} +export type OAuthApp = components['schemas']['OAuthAppResponse'] export async function getOAuthApps({ slug }: OAuthAppsVariables, signal?: AbortSignal) { if (!slug) throw new Error('Organization slug is required') - const response = await get(`${API_URL}/organizations/${slug}/oauth/apps?type=published`, { - signal, + const { data, error } = await get('/platform/organizations/{slug}/oauth/apps', { + params: { path: { slug }, query: { type: 'published' } }, }) - if (response.error) throw response.error - return response as OAuthApp[] + + if (error) handleError(error) + return data } export type OAuthAppsData = Awaited> diff --git a/apps/studio/data/projects/project-transfer-mutation.ts b/apps/studio/data/projects/project-transfer-mutation.ts index 2a53c8ed3f3..8d9056c26db 100644 --- a/apps/studio/data/projects/project-transfer-mutation.ts +++ b/apps/studio/data/projects/project-transfer-mutation.ts @@ -1,8 +1,8 @@ import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' -import { post } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' +import { handleError, post } from 'data/fetchers' +import { ResponseError } from 'types' import { projectKeys } from './keys' export type ProjectTransferVariables = { @@ -10,10 +10,6 @@ export type ProjectTransferVariables = { targetOrganizationSlug?: string } -type ProjectTransferError = { - message: string -} - export async function transferProject({ projectRef, targetOrganizationSlug, @@ -25,10 +21,12 @@ export async function transferProject({ target_organization_slug: targetOrganizationSlug, } - const response = await post(`${API_URL}/projects/${projectRef}/transfer`, payload) - if (response.error) throw response.error - - return response + const { data, error } = await post('/platform/projects/{ref}/transfer', { + params: { path: { ref: projectRef } }, + body: payload, + }) + if (error) handleError(error) + return data } type ProjectTransferData = Awaited> @@ -38,12 +36,12 @@ export const useProjectTransferMutation = ({ onError, ...options }: Omit< - UseMutationOptions, + UseMutationOptions, 'mutationFn' > = {}) => { const queryClient = useQueryClient() - return useMutation( + return useMutation( (vars) => transferProject(vars), { async onSuccess(data, variables, context) { diff --git a/apps/studio/data/projects/project-transfer-preview-query.ts b/apps/studio/data/projects/project-transfer-preview-query.ts index 08bab5b916b..8e4f301b36b 100644 --- a/apps/studio/data/projects/project-transfer-preview-query.ts +++ b/apps/studio/data/projects/project-transfer-preview-query.ts @@ -1,6 +1,6 @@ import { useQuery, UseQueryOptions } from '@tanstack/react-query' -import { post } from 'lib/common/fetch' -import { API_URL } from 'lib/constants' + +import { handleError, post } from 'data/fetchers' import { projectKeys } from './keys' export type ProjectTransferPreviewVariables = { @@ -10,40 +10,6 @@ export type ProjectTransferPreviewVariables = { export type PlanId = 'free' | 'pro' | 'team' | 'enterprise' -type MemberExceedingFreeProjectLimit = { - name: string - limit: number -} - -type PreviewTransferInfo = { - key: string - message: string -} - -export type PreviewProjectTransferResponse = { - valid: boolean - - warnings: PreviewTransferInfo[] - errors: PreviewTransferInfo[] - - members_exceeding_free_project_limit: MemberExceedingFreeProjectLimit[] - - has_permissions_on_source_organization: boolean - has_access_to_target_organization: boolean - - source_project_eligible: boolean - - target_organization_eligible: boolean | null - target_organization_has_free_project_slots: boolean | null - - credits_on_source_organization: number - costs_on_target_organization: number - charge_on_target_organization: number - - source_subscription_plan: PlanId - target_subscription_plan: PlanId | null -} - export async function previewProjectTransfer( { projectRef, targetOrganizationSlug }: ProjectTransferPreviewVariables, signal?: AbortSignal @@ -51,16 +17,14 @@ export async function previewProjectTransfer( if (!projectRef) throw new Error('projectRef is required') if (!targetOrganizationSlug) throw new Error('targetOrganizationSlug is required') - const response = await post( - `${API_URL}/projects/${projectRef}/transfer/preview`, - { - target_organization_slug: targetOrganizationSlug, - }, - { signal } - ) - if (response.error) throw response.error + const { data, error } = await post('/platform/projects/{ref}/transfer/preview', { + params: { path: { ref: projectRef } }, + body: { target_organization_slug: targetOrganizationSlug }, + signal, + }) - return response as PreviewProjectTransferResponse + if (error) handleError(error) + return data } export type ProjectTransferPreviewData = Awaited>