Skip to main content
Glama

mcp-google-sheets

app-connections-hooks.ts8.22 kB
import { useMutation, useQuery } from '@tanstack/react-query'; import { t } from 'i18next'; import { UseFormReturn } from 'react-hook-form'; import { useEmbedding } from '@/components/embed-provider'; import { INTERNAL_ERROR_TOAST, toast } from '@/components/ui/use-toast'; import { projectMembersApi } from '@/features/team/lib/project-members-api'; import { api } from '@/lib/api'; import { authenticationSession } from '@/lib/authentication-session'; import { ApErrorParams, AppConnectionScope, AppConnectionWithoutSensitiveData, ErrorCode, isNil, ListAppConnectionsRequestQuery, ReplaceAppConnectionsRequestBody, UpsertAppConnectionRequestBody, } from '@activepieces/shared'; import { appConnectionsApi } from './api/app-connections'; import { globalConnectionsApi } from './api/global-connections'; import { ConnectionNameAlreadyExists, NoProjectSelected, isConnectionNameUnique, } from './utils'; type UseReplaceConnectionsProps = { setDialogOpen: (isOpen: boolean) => void; refetch: () => void; }; type UseRenameAppConnectionProps = { currentName: string; setIsRenameDialogOpen: (isOpen: boolean) => void; renameConnectionForm: UseFormReturn<{ displayName: string; }>; refetch: () => void; }; type UseUpsertAppConnectionProps = { isGlobalConnection: boolean; reconnectConnection: AppConnectionWithoutSensitiveData | null; externalIdComingFromSdk?: string | null; setErrorMessage: (message: string) => void; form: UseFormReturn<{ request: UpsertAppConnectionRequestBody & { projectIds: string[]; }; }>; setOpen: ( open: boolean, connection?: AppConnectionWithoutSensitiveData, ) => void; }; export const appConnectionsMutations = { useUpsertAppConnection: ({ isGlobalConnection, reconnectConnection, externalIdComingFromSdk, setErrorMessage, form, setOpen, }: UseUpsertAppConnectionProps) => { return useMutation({ mutationFn: async () => { setErrorMessage(''); const formValues = form.getValues().request; const isNameUnique = await isConnectionNameUnique( isGlobalConnection, formValues.displayName, ); if ( !isNameUnique && reconnectConnection?.displayName !== formValues.displayName && (isNil(externalIdComingFromSdk) || externalIdComingFromSdk === '') ) { throw new ConnectionNameAlreadyExists(); } if (isGlobalConnection) { if (formValues.projectIds.length === 0) { throw new NoProjectSelected(); } return globalConnectionsApi.upsert({ ...formValues, projectIds: formValues.projectIds, scope: AppConnectionScope.PLATFORM, }); } return appConnectionsApi.upsert(formValues); }, onSuccess: (connection) => { setOpen(false, connection); setErrorMessage(''); }, onError: (err) => { if (err instanceof ConnectionNameAlreadyExists) { form.setError('request.displayName', { message: err.message, }); } else if (err instanceof NoProjectSelected) { form.setError('request.projectIds', { message: err.message, }); } else if (api.isError(err)) { const apError = err.response?.data as ApErrorParams; switch (apError.code) { case ErrorCode.INVALID_CLOUD_CLAIM: { setErrorMessage( t( 'Could not claim the authorization code, make sure you have correct settings and try again.', ), ); break; } case ErrorCode.INVALID_CLAIM: { setErrorMessage( t('Connection failed with error {msg}', { msg: apError.params.message, }), ); break; } case ErrorCode.INVALID_APP_CONNECTION: { setErrorMessage( t('Connection failed with error {msg}', { msg: apError.params.error, }), ); break; } // can happen in embedding sdk connect method case ErrorCode.PERMISSION_DENIED: { setErrorMessage( t(`You don't have the permission to create a connection.`), ); break; } default: { setErrorMessage('Unexpected error, please contact support'); toast(INTERNAL_ERROR_TOAST); console.error(err); } } } }, }); }, useBulkDeleteAppConnections: (refetch: () => void) => { return useMutation({ mutationFn: async (ids: string[]) => { await Promise.all(ids.map((id) => appConnectionsApi.delete(id))); }, onSuccess: () => { refetch(); }, onError: () => { toast({ title: t('Error deleting connections'), variant: 'destructive', }); }, }); }, useRenameAppConnection: ({ currentName, setIsRenameDialogOpen, renameConnectionForm, refetch, }: UseRenameAppConnectionProps) => { return useMutation({ mutationFn: async ({ connectionId, displayName, }: { connectionId: string; displayName: string; }) => { const existingConnection = await isConnectionNameUnique( false, displayName, ); if (!existingConnection && displayName !== currentName) { throw new ConnectionNameAlreadyExists(); } return appConnectionsApi.update(connectionId, { displayName }); }, onSuccess: () => { refetch(); toast({ title: t('Success'), description: t('Connection has been renamed.'), duration: 3000, }); setIsRenameDialogOpen(false); }, onError: (error) => { if (error instanceof ConnectionNameAlreadyExists) { renameConnectionForm.setError('displayName', { message: error.message, }); } else { toast(INTERNAL_ERROR_TOAST); } }, }); }, useReplaceConnections: ({ setDialogOpen, refetch, }: UseReplaceConnectionsProps) => { return useMutation({ mutationFn: async (request: ReplaceAppConnectionsRequestBody) => { await appConnectionsApi.replace(request); }, onSuccess: () => { toast({ title: t('Success'), description: t('Connections replaced successfully'), }); setDialogOpen(false); refetch(); }, onError: () => { toast({ title: t('Error'), description: t('Failed to replace connections'), variant: 'destructive', }); }, }); }, }; type UseConnectionsProps = { request: ListAppConnectionsRequestQuery; extraKeys: any[]; enabled?: boolean; staleTime?: number; }; export const appConnectionsQueries = { useAppConnections: ({ request, extraKeys, enabled, staleTime, }: UseConnectionsProps) => { return useQuery({ queryKey: ['app-connections', ...extraKeys], queryFn: () => appConnectionsApi.list(request), enabled, staleTime, }); }, useConnectionsOwners: () => { const projectId = authenticationSession.getProjectId() ?? ''; const isEmbedding = useEmbedding().embedState.isEmbedded; return useQuery({ queryKey: ['app-connections-owners', projectId], queryFn: async () => { const { data: owners } = await appConnectionsApi.getOwners({ projectId, }); const { data: projectMembers } = await projectMembersApi.list({ projectId, }); if (isEmbedding) { return owners.filter( (owner) => !isNil( projectMembers.find( (member) => member.user.email === owner.email, ), ), ); } return owners; }, }); }, };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/activepieces/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server