Bettertyping (#10725)
To get better at catching errors on providers (It will ease also my coming PR to send microsoft messages using workflow)
This commit is contained in:
@ -0,0 +1 @@
|
|||||||
|
export const MICROSOFT_SEND_SCOPE = 'Mail.Send';
|
||||||
@ -1,11 +1,12 @@
|
|||||||
import { CalendarChannel } from '@/accounts/types/CalendarChannel';
|
import { CalendarChannel } from '@/accounts/types/CalendarChannel';
|
||||||
|
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
import { MessageChannel } from './MessageChannel';
|
import { MessageChannel } from './MessageChannel';
|
||||||
|
|
||||||
export type ConnectedAccount = {
|
export type ConnectedAccount = {
|
||||||
id: string;
|
id: string;
|
||||||
handle: string;
|
handle: string;
|
||||||
provider: string;
|
provider: ConnectedAccountProvider;
|
||||||
accessToken: string;
|
accessToken: string;
|
||||||
refreshToken: string;
|
refreshToken: string;
|
||||||
accountOwnerId: string;
|
accountOwnerId: string;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { useTriggerApisOAuth } from '@/settings/accounts/hooks/useTriggerApiOAut
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@ -60,7 +61,7 @@ export const SettingsAccountsListEmptyStateCard = ({
|
|||||||
Icon={IconGoogle}
|
Icon={IconGoogle}
|
||||||
title={t`Connect with Google`}
|
title={t`Connect with Google`}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() => triggerApisOAuth('google')}
|
onClick={() => triggerApisOAuth(ConnectedAccountProvider.GOOGLE)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ export const SettingsAccountsListEmptyStateCard = ({
|
|||||||
Icon={IconMicrosoft}
|
Icon={IconMicrosoft}
|
||||||
title={t`Connect with Microsoft`}
|
title={t`Connect with Microsoft`}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
onClick={() => triggerApisOAuth('microsoft')}
|
onClick={() => triggerApisOAuth(ConnectedAccountProvider.MICROSOFT)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</StyledBody>
|
</StyledBody>
|
||||||
|
|||||||
@ -1,19 +1,20 @@
|
|||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||||
import {
|
import {
|
||||||
CalendarChannelVisibility,
|
CalendarChannelVisibility,
|
||||||
MessageChannelVisibility,
|
MessageChannelVisibility,
|
||||||
useGenerateTransientTokenMutation,
|
useGenerateTransientTokenMutation,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
import { useRedirect } from '@/domain-manager/hooks/useRedirect';
|
|
||||||
|
|
||||||
const getProviderUrl = (provider: string) => {
|
const getProviderUrl = (provider: ConnectedAccountProvider) => {
|
||||||
switch (provider) {
|
switch (provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return 'google-apis';
|
return 'google-apis';
|
||||||
case 'microsoft':
|
case ConnectedAccountProvider.MICROSOFT:
|
||||||
return 'microsoft-apis';
|
return 'microsoft-apis';
|
||||||
default:
|
default:
|
||||||
throw new Error(`Provider ${provider} is not supported`);
|
throw new Error(`Provider ${provider} is not supported`);
|
||||||
@ -26,7 +27,7 @@ export const useTriggerApisOAuth = () => {
|
|||||||
|
|
||||||
const triggerApisOAuth = useCallback(
|
const triggerApisOAuth = useCallback(
|
||||||
async (
|
async (
|
||||||
provider: string,
|
provider: ConnectedAccountProvider,
|
||||||
{
|
{
|
||||||
redirectLocation,
|
redirectLocation,
|
||||||
messageVisibility,
|
messageVisibility,
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil';
|
import { useRecoilState, useRecoilValue } from 'recoil';
|
||||||
import { capitalize } from 'twenty-shared';
|
import { capitalize, ConnectedAccountProvider } from 'twenty-shared';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
IconGoogle,
|
IconGoogle,
|
||||||
@ -136,7 +136,9 @@ export const SettingsSecurityAuthProvidersOptionsList = () => {
|
|||||||
checked={currentWorkspace.isGoogleAuthEnabled}
|
checked={currentWorkspace.isGoogleAuthEnabled}
|
||||||
advancedMode
|
advancedMode
|
||||||
divider
|
divider
|
||||||
onChange={() => toggleAuthMethod('google')}
|
onChange={() =>
|
||||||
|
toggleAuthMethod(ConnectedAccountProvider.GOOGLE)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{authProviders.microsoft === true && (
|
{authProviders.microsoft === true && (
|
||||||
@ -147,7 +149,9 @@ export const SettingsSecurityAuthProvidersOptionsList = () => {
|
|||||||
checked={currentWorkspace.isMicrosoftAuthEnabled}
|
checked={currentWorkspace.isMicrosoftAuthEnabled}
|
||||||
advancedMode
|
advancedMode
|
||||||
divider
|
divider
|
||||||
onChange={() => toggleAuthMethod('microsoft')}
|
onChange={() =>
|
||||||
|
toggleAuthMethod(ConnectedAccountProvider.MICROSOFT)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{authProviders.password === true && (
|
{authProviders.password === true && (
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { WorkflowVariablePicker } from '@/workflow/workflow-variables/components
|
|||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { isDefined } from 'twenty-shared';
|
import { ConnectedAccountProvider, isDefined } from 'twenty-shared';
|
||||||
import { IconPlus, useIcons } from 'twenty-ui';
|
import { IconPlus, useIcons } from 'twenty-ui';
|
||||||
import { JsonValue } from 'type-fest';
|
import { JsonValue } from 'type-fest';
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
@ -71,7 +71,7 @@ export const WorkflowEditActionFormSendEmail = ({
|
|||||||
!isDefined(scopes) ||
|
!isDefined(scopes) ||
|
||||||
!isDefined(scopes.find((scope) => scope === GMAIL_SEND_SCOPE))
|
!isDefined(scopes.find((scope) => scope === GMAIL_SEND_SCOPE))
|
||||||
) {
|
) {
|
||||||
await triggerApisOAuth('google', {
|
await triggerApisOAuth(ConnectedAccountProvider.GOOGLE, {
|
||||||
redirectLocation: redirectUrl,
|
redirectLocation: redirectUrl,
|
||||||
loginHint: connectedAccount.handle,
|
loginHint: connectedAccount.handle,
|
||||||
});
|
});
|
||||||
@ -200,7 +200,7 @@ export const WorkflowEditActionFormSendEmail = ({
|
|||||||
options={connectedAccountOptions}
|
options={connectedAccountOptions}
|
||||||
callToActionButton={{
|
callToActionButton={{
|
||||||
onClick: () =>
|
onClick: () =>
|
||||||
triggerApisOAuth('google', {
|
triggerApisOAuth(ConnectedAccountProvider.GOOGLE, {
|
||||||
redirectLocation: redirectUrl,
|
redirectLocation: redirectUrl,
|
||||||
}),
|
}),
|
||||||
Icon: IconPlus,
|
Icon: IconPlus,
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
|
|
||||||
import { GoogleCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/services/google-calendar-get-events.service';
|
import { GoogleCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/google-calendar/services/google-calendar-get-events.service';
|
||||||
import { MicrosoftCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/services/microsoft-calendar-get-events.service';
|
import { MicrosoftCalendarGetEventsService } from 'src/modules/calendar/calendar-event-import-manager/drivers/microsoft-calendar/services/microsoft-calendar-get-events.service';
|
||||||
import {
|
import {
|
||||||
@ -31,12 +33,12 @@ export class CalendarGetCalendarEventsService {
|
|||||||
syncCursor?: string,
|
syncCursor?: string,
|
||||||
): Promise<GetCalendarEventsResponse> {
|
): Promise<GetCalendarEventsResponse> {
|
||||||
switch (connectedAccount.provider) {
|
switch (connectedAccount.provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return this.googleCalendarGetEventsService.getCalendarEvents(
|
return this.googleCalendarGetEventsService.getCalendarEvents(
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
syncCursor,
|
syncCursor,
|
||||||
);
|
);
|
||||||
case 'microsoft':
|
case ConnectedAccountProvider.MICROSOFT:
|
||||||
return this.microsoftCalendarGetEventsService.getCalendarEvents(
|
return this.microsoftCalendarGetEventsService.getCalendarEvents(
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
syncCursor,
|
syncCursor,
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { assertUnreachable, ConnectedAccountProvider } from 'twenty-shared';
|
||||||
|
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service';
|
import { GoogleEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/google/google-email-alias-manager.service';
|
||||||
import { MicrosoftEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/microsoft/microsoft-email-alias-manager.service';
|
import { MicrosoftEmailAliasManagerService } from 'src/modules/connected-account/email-alias-manager/drivers/microsoft/microsoft-email-alias-manager.service';
|
||||||
@ -19,20 +21,21 @@ export class EmailAliasManagerService {
|
|||||||
let handleAliases: string[];
|
let handleAliases: string[];
|
||||||
|
|
||||||
switch (connectedAccount.provider) {
|
switch (connectedAccount.provider) {
|
||||||
case 'microsoft':
|
case ConnectedAccountProvider.MICROSOFT:
|
||||||
handleAliases =
|
handleAliases =
|
||||||
await this.microsoftEmailAliasManagerService.getHandleAliases(
|
await this.microsoftEmailAliasManagerService.getHandleAliases(
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
handleAliases =
|
handleAliases =
|
||||||
await this.googleEmailAliasManagerService.getHandleAliases(
|
await this.googleEmailAliasManagerService.getHandleAliases(
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(
|
assertUnreachable(
|
||||||
|
connectedAccount.provider,
|
||||||
`Email alias manager for provider ${connectedAccount.provider} is not implemented`,
|
`Email alias manager for provider ${connectedAccount.provider} is not implemented`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { OAuth2Client } from 'google-auth-library';
|
import { OAuth2Client } from 'google-auth-library';
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
|
|
||||||
import { GoogleOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service';
|
import { GoogleOAuth2ClientManagerService } from 'src/modules/connected-account/oauth2-client-manager/drivers/google/google-oauth2-client-manager.service';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
@ -20,7 +21,7 @@ export class OAuth2ClientManagerService {
|
|||||||
const { refreshToken } = connectedAccount;
|
const { refreshToken } = connectedAccount;
|
||||||
|
|
||||||
switch (connectedAccount.provider) {
|
switch (connectedAccount.provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return this.googleOAuth2ClientManagerService.getOAuth2Client(
|
return this.googleOAuth2ClientManagerService.getOAuth2Client(
|
||||||
refreshToken,
|
refreshToken,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
|
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
@ -24,9 +26,9 @@ export class MessagingCursorService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
switch (connectedAccount.provider) {
|
switch (connectedAccount.provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return messageChannel.syncCursor;
|
return messageChannel.syncCursor;
|
||||||
case 'microsoft': {
|
case ConnectedAccountProvider.MICROSOFT: {
|
||||||
const folder = await folderRepository.findOne({
|
const folder = await folderRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: folderId,
|
id: folderId,
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
|
|
||||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||||
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||||
import { MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
|
import { MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
|
||||||
@ -46,7 +48,7 @@ export class MessagingGetMessageListService {
|
|||||||
messageChannel: MessageChannelWorkspaceEntity,
|
messageChannel: MessageChannelWorkspaceEntity,
|
||||||
): Promise<GetFullMessageListForFoldersResponse[]> {
|
): Promise<GetFullMessageListForFoldersResponse[]> {
|
||||||
switch (messageChannel.connectedAccount.provider) {
|
switch (messageChannel.connectedAccount.provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
...(await this.gmailGetMessageListService.getFullMessageList(
|
...(await this.gmailGetMessageListService.getFullMessageList(
|
||||||
@ -55,7 +57,7 @@ export class MessagingGetMessageListService {
|
|||||||
folderId: undefined,
|
folderId: undefined,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
case 'microsoft': {
|
case ConnectedAccountProvider.MICROSOFT: {
|
||||||
const folderRepository =
|
const folderRepository =
|
||||||
await this.twentyORMManager.getRepository<MessageFolderWorkspaceEntity>(
|
await this.twentyORMManager.getRepository<MessageFolderWorkspaceEntity>(
|
||||||
'messageFolder',
|
'messageFolder',
|
||||||
@ -84,7 +86,7 @@ export class MessagingGetMessageListService {
|
|||||||
messageChannel: MessageChannelWorkspaceEntity,
|
messageChannel: MessageChannelWorkspaceEntity,
|
||||||
): Promise<GetPartialMessageListForFoldersResponse[]> {
|
): Promise<GetPartialMessageListForFoldersResponse[]> {
|
||||||
switch (messageChannel.connectedAccount.provider) {
|
switch (messageChannel.connectedAccount.provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
...(await this.gmailGetMessageListService.getPartialMessageList(
|
...(await this.gmailGetMessageListService.getPartialMessageList(
|
||||||
@ -94,7 +96,7 @@ export class MessagingGetMessageListService {
|
|||||||
folderId: undefined,
|
folderId: undefined,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
case 'microsoft':
|
case ConnectedAccountProvider.MICROSOFT:
|
||||||
return this.microsoftGetMessageListService.getPartialMessageListForFolders(
|
return this.microsoftGetMessageListService.getPartialMessageListForFolders(
|
||||||
messageChannel.connectedAccount,
|
messageChannel.connectedAccount,
|
||||||
messageChannel,
|
messageChannel,
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import { ConnectedAccountProvider } from 'twenty-shared';
|
||||||
|
|
||||||
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
|
||||||
import { GmailGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-messages.service';
|
import { GmailGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/gmail/services/gmail-get-messages.service';
|
||||||
import { MicrosoftGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service';
|
import { MicrosoftGetMessagesService } from 'src/modules/messaging/message-import-manager/drivers/microsoft/services/microsoft-get-messages.service';
|
||||||
@ -32,13 +34,13 @@ export class MessagingGetMessagesService {
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
): Promise<GetMessagesResponse> {
|
): Promise<GetMessagesResponse> {
|
||||||
switch (connectedAccount.provider) {
|
switch (connectedAccount.provider) {
|
||||||
case 'google':
|
case ConnectedAccountProvider.GOOGLE:
|
||||||
return this.gmailGetMessagesService.getMessages(
|
return this.gmailGetMessagesService.getMessages(
|
||||||
messageIds,
|
messageIds,
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
workspaceId,
|
workspaceId,
|
||||||
);
|
);
|
||||||
case 'microsoft':
|
case ConnectedAccountProvider.MICROSOFT:
|
||||||
return this.microsoftGetMessagesService.getMessages(
|
return this.microsoftGetMessagesService.getMessages(
|
||||||
messageIds,
|
messageIds,
|
||||||
connectedAccount,
|
connectedAccount,
|
||||||
|
|||||||
Reference in New Issue
Block a user