Skip to content

Commit

Permalink
feat(core): catch unsupported client version error
Browse files Browse the repository at this point in the history
  • Loading branch information
JimmFly committed Dec 23, 2024
1 parent c24e1bb commit 41cea88
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 37 deletions.
43 changes: 37 additions & 6 deletions packages/frontend/core/src/components/sign-in/sign-in.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ import { OAuth } from '@affine/core/components/affine/auth/oauth';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { AuthService, ServerService } from '@affine/core/modules/cloud';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { ServerDeploymentType } from '@affine/graphql';
import {
ErrorNames,
ServerDeploymentType,
UserFriendlyError,
} from '@affine/graphql';
import { Trans, useI18n } from '@affine/i18n';
import { ArrowRightBigIcon, PublishIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
Expand Down Expand Up @@ -120,14 +124,41 @@ export const SignInStep = ({
} catch (err) {
console.error(err);

// TODO(@eyhn): better error handling
notify.error({
title: 'Failed to send email. Please try again.',
});
const userFriendlyError = UserFriendlyError.fromAnyError(err);
if (userFriendlyError.name === ErrorNames.UNSUPPORTED_CLIENT_VERSION) {
const { action } = userFriendlyError.args;
notify.error({
title: t['com.affine.minimum-client.title'](),
message:
t[
`com.affine.minimum-client.${action === 'upgrade' ? 'outdated' : 'advanced'}.message`
](),
action: {
label:
t[
`com.affine.minimum-client.${action === 'upgrade' ? 'outdated' : 'advanced'}.button`
](),
onClick: () =>
window.open(
BUILD_CONFIG.downloadUrl,
'_blank',
'noreferrer noopener'
),
buttonProps: {
variant: 'primary',
},
},
});
} else {
// TODO(@eyhn): better error handling
notify.error({
title: 'Failed to send email. Please try again.',
});
}
}

setIsMutating(false);
}, [authService, changeState, email]);
}, [authService, changeState, email, t]);

const onAddSelfhosted = useCallback(() => {
changeState(prev => ({
Expand Down
14 changes: 2 additions & 12 deletions packages/frontend/core/src/desktop/pages/auth/magic-link.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { ErrorNames, UserFriendlyError } from '@affine/graphql';
import { useService } from '@toeverything/infra';
import { useEffect, useRef } from 'react';
import {
type LoaderFunction,
redirect,
useLoaderData,
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
useNavigate,
} from 'react-router-dom';

Expand Down Expand Up @@ -79,16 +77,8 @@ export const Component = () => {
}
});
})
.catch(err => {
const userFriendlyError = UserFriendlyError.fromAnyError(err);
if (userFriendlyError.name === ErrorNames.UNSUPPORTED_CLIENT_VERSION) {
const { action } = userFriendlyError.args;
nav(
`/sign-in?error=${encodeURIComponent(userFriendlyError.message)}&action=${encodeURIComponent(action as string)}`
);
return;
}
nav(`/sign-in?error=${encodeURIComponent(err.message)}`);
.catch(e => {
nav(`/sign-in?error=${encodeURIComponent(e.message)}`);
});
}, [auth, data, data.email, data.redirectUri, data.token, nav]);

Expand Down
15 changes: 2 additions & 13 deletions packages/frontend/core/src/desktop/pages/auth/oauth-callback.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { ErrorNames, UserFriendlyError } from '@affine/graphql';
import { useService } from '@toeverything/infra';
import { useEffect, useRef } from 'react';
import {
type LoaderFunction,
redirect,
useLoaderData,
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
useNavigate,
} from 'react-router-dom';

Expand Down Expand Up @@ -81,17 +79,8 @@ export const Component = () => {
// TODO(@forehalo): need a good way to go back to previous tab and close current one
nav(redirectUri ?? '/');
})
.catch(err => {
const userFriendlyError = UserFriendlyError.fromAnyError(err);
if (userFriendlyError.name === ErrorNames.UNSUPPORTED_CLIENT_VERSION) {
const { action } = userFriendlyError.args;
nav(
`/sign-in?error=${encodeURIComponent(userFriendlyError.message)}&action=${encodeURIComponent(action as string)}`
);
return;
}
nav(`/sign-in?error=${encodeURIComponent(err.message)}`);
return;
.catch(e => {
nav(`/sign-in?error=${encodeURIComponent(e.message)}`);
});
}, [data, auth, nav]);

Expand Down
9 changes: 9 additions & 0 deletions packages/frontend/core/src/modules/cloud/stores/auth.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import {
ErrorNames,
removeAvatarMutation,
updateUserProfileMutation,
uploadAvatarMutation,
UserFriendlyError,
} from '@affine/graphql';
import { Store } from '@toeverything/infra';

import type { GlobalState } from '../../storage';
import type { AuthSessionInfo } from '../entities/session';
import { BackendError } from '../error';
import type { FetchService } from '../services/fetch';
import type { GraphQLService } from '../services/graphql';
import type { ServerService } from '../services/server';
Expand Down Expand Up @@ -99,6 +102,12 @@ export class AuthStore extends Store {
});

if (!res.ok) {
const error = await res.json();

const userFriendlyError = UserFriendlyError.fromAnyError(error);
if (userFriendlyError.name === ErrorNames.UNSUPPORTED_CLIENT_VERSION) {
throw new BackendError(userFriendlyError, res.status);
}
throw new Error(`Failed to check user by email: ${email}`);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { notify } from '@affine/component';
import { ErrorNames, UserFriendlyError } from '@affine/graphql';
import { I18n } from '@affine/i18n';
import {
init,
Expand Down Expand Up @@ -173,10 +174,37 @@ export class DesktopApiService extends Service {
}
}
})().catch(e => {
notify.error({
title: I18n['com.affine.auth.toast.title.failed'](),
message: (e as any).message,
});
const userFriendlyError = UserFriendlyError.fromAnyError(e);
if (userFriendlyError.name === ErrorNames.UNSUPPORTED_CLIENT_VERSION) {
const { action } = userFriendlyError.args;
notify.error({
title: I18n['com.affine.minimum-client.title'](),
message:
I18n[
`com.affine.minimum-client.${action === 'upgrade' ? 'outdated' : 'advanced'}.message`
](),
action: {
label:
I18n[
`com.affine.minimum-client.${action === 'upgrade' ? 'outdated' : 'advanced'}.button`
](),
onClick: () =>
window.open(
BUILD_CONFIG.downloadUrl,
'_blank',
'noreferrer noopener'
),
buttonProps: {
variant: 'primary',
},
},
});
} else {
notify.error({
title: I18n['com.affine.auth.toast.title.failed'](),
message: (e as any).message,
});
}
});
});
}
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/graphql/src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface UserFriendlyErrorResponse {
type: string;
name: ErrorNames;
message: string;
args?: any;
data?: any;
stacktrace?: string;
}

Expand All @@ -21,7 +21,7 @@ export class UserFriendlyError
readonly type = this.response.type;
override readonly name = this.response.name;
override readonly message = this.response.message;
readonly args = this.response.args;
readonly args = this.response.data;
readonly stacktrace = this.response.stacktrace;

static fromAnyError(response: any) {
Expand Down

0 comments on commit 41cea88

Please sign in to comment.