feat: add affine request error msg

This commit is contained in:
MingLiang Wang
2023-01-12 15:11:49 +08:00
parent 034e460701
commit 9ae9bb8092
9 changed files with 217 additions and 61 deletions

View File

@@ -23,7 +23,7 @@ export class DataCenter {
private readonly _workspaceUnitCollection = new WorkspaceUnitCollection();
private readonly _logger = getLogger('dc');
private _workspaceInstances: Map<string, BlocksuiteWorkspace> = new Map();
private _messageCenter = new MessageCenter();
private _messageCenter = MessageCenter.getInstance();
/**
* A mainProvider must exist as the only data trustworthy source.
*/

View File

@@ -1,3 +1,61 @@
export enum MessageCode {
loginError,
noPermission,
loadListFailed,
getDetailFailed,
createWorkspaceFailed,
getMembersFailed,
updateWorkspaceFailed,
deleteWorkspaceFailed,
inviteMemberFailed,
removeMemberFailed,
acceptInvitingFailed,
getBlobFailed,
leaveWorkspaceFailed,
downloadWorkspaceFailed,
}
export const messages = {
[MessageCode.loginError]: {
message: 'Login failed',
},
[MessageCode.noPermission]: {
message: 'No permission',
},
[MessageCode.loadListFailed]: {
message: 'Load list failed',
},
[MessageCode.getDetailFailed]: {
message: 'Get detail failed',
},
[MessageCode.createWorkspaceFailed]: {
message: 'Create workspace failed',
},
[MessageCode.getMembersFailed]: {
message: 'Get members failed',
},
[MessageCode.updateWorkspaceFailed]: {
message: 'Update workspace failed',
},
[MessageCode.deleteWorkspaceFailed]: {
message: 'Delete workspace failed',
},
[MessageCode.inviteMemberFailed]: {
message: 'Invite member failed',
},
[MessageCode.removeMemberFailed]: {
message: 'Remove member failed',
},
[MessageCode.acceptInvitingFailed]: {
message: 'Accept inviting failed',
},
[MessageCode.getBlobFailed]: {
message: 'Get blob failed',
},
[MessageCode.leaveWorkspaceFailed]: {
message: 'Leave workspace failed',
},
[MessageCode.downloadWorkspaceFailed]: {
message: 'Download workspace failed',
},
};

View File

@@ -1,24 +1,36 @@
import { Observable } from 'lib0/observable';
import { Message } from '../types';
import { MessageCode } from './code.js';
import { MessageCode, messages } from './code.js';
export class MessageCenter extends Observable<string> {
private _messages: Record<number, Omit<Message, 'provider' | 'code'>> =
messages;
constructor() {
super();
}
public send(message: MessageCode) {
this.emit('message', [message]);
static instance: MessageCenter;
static getInstance() {
if (!MessageCenter.instance) {
MessageCenter.instance = new MessageCenter();
}
return MessageCenter.instance;
}
static messageCode = MessageCode;
public getMessageSender(provider: string) {
return this._send.bind(this, provider);
}
private _send(provider: string, messageCode: MessageCode) {
this.emit('message', [
{ ...this._messages[messageCode], provider, code: messageCode },
]);
}
public onMessage(callback: (message: Message) => void) {
this.on('message', callback);
}
private messages: Record<number, Message> = {
[MessageCode.loginError]: {
code: MessageCode.loginError,
message: 'Login failed',
},
};
}

View File

@@ -2,7 +2,6 @@ import { BaseProvider } from '../base.js';
import type {
ProviderConstructorParams,
CreateWorkspaceInfoParams,
WorkspaceMeta0,
} from '../base';
import type { User } from '../../types';
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
@@ -12,8 +11,6 @@ import { WebsocketProvider } from './sync.js';
// import { IndexedDBProvider } from '../local/indexeddb';
import { getApis, Workspace } from './apis/index.js';
import type { Apis, WorkspaceDetail, Callback } from './apis';
import { setDefaultAvatar } from '../utils.js';
import { MessageCode } from '../../message/index.js';
import { token } from './apis/token.js';
import { WebsocketClient } from './channel';
import {
@@ -24,6 +21,7 @@ import {
import { WorkspaceUnit } from '../../workspace-unit.js';
import { createBlocksuiteWorkspace, applyUpdate } from '../../utils/index.js';
import type { SyncMode } from '../../workspace-unit';
import { MessageCenter } from 'src/message/message.js';
type ChannelMessage = {
ws_list: Workspace[];
@@ -42,7 +40,6 @@ const {
export class AffineProvider extends BaseProvider {
public id = 'affine';
private _workspacesCache: Map<string, BlocksuiteWorkspace> = new Map();
private _onTokenRefresh?: Callback = undefined;
private _wsMap: Map<string, WebsocketProvider> = new Map();
private _apis: Apis;
@@ -121,7 +118,7 @@ export class AffineProvider extends BaseProvider {
},
published: detail.public,
memberCount: detail.member_count,
provider: 'affine',
provider: this.id,
syncMode: 'core' as SyncMode,
};
if (this._workspaces.get(id)) {
@@ -207,7 +204,7 @@ export class AffineProvider extends BaseProvider {
owner: undefined,
published: w.public,
memberCount: 1,
provider: 'affine',
provider: this.id,
syncMode: 'core',
},
this._apis
@@ -232,7 +229,7 @@ export class AffineProvider extends BaseProvider {
this._connectChannel();
}
if (!user) {
this._messageCenter.send(MessageCode.loginError);
this._sendMessage(MessageCenter.messageCode.loginError);
}
}
@@ -257,17 +254,17 @@ export class AffineProvider extends BaseProvider {
}
public override async clear(): Promise<void> {
for (const w of this._workspacesCache.values()) {
if (w.room) {
for (const w of this._workspaces.list()) {
if (w.id) {
try {
await this.deleteWorkspace(w.room);
this._workspaces.remove(w.room);
await this.deleteWorkspace(w.id);
this._workspaces.remove(w.id);
} catch (e) {
this._logger('has a problem of delete workspace ', e);
}
}
}
this._workspacesCache.clear();
this._workspaces.clear();
}
public override async closeWorkspace(id: string) {
@@ -313,7 +310,7 @@ export class AffineProvider extends BaseProvider {
owner: await this.getUserInfo(),
published: false,
memberCount: 1,
provider: 'affine',
provider: this.id,
syncMode: 'core',
});
@@ -358,7 +355,7 @@ export class AffineProvider extends BaseProvider {
owner: await this.getUserInfo(),
published: false,
memberCount: 1,
provider: 'affine',
provider: this.id,
syncMode: 'core',
});

View File

@@ -1,7 +1,11 @@
import kyOrigin from 'ky';
import ky from 'ky-universal';
import { MessageCenter } from '../../../message/index.js';
import { token } from './token.js';
const messageCenter = MessageCenter.getInstance();
const _sendMessage = messageCenter.getMessageSender('affine');
export const bareClient = ky.extend({
prefixUrl: 'http://localhost:8080',
retry: 1,
@@ -41,5 +45,15 @@ export const client = bareClient.extend({
request.headers.set('Authorization', token.token);
},
],
beforeError: [
error => {
const { response } = error;
if (response.status === 401) {
_sendMessage(MessageCenter.messageCode.noPermission);
}
return error;
},
],
},
});

View File

@@ -1,6 +1,19 @@
import { MessageCenter } from 'src/message/message.js';
import { bareClient, client } from './request.js';
import type { User } from './user';
const messageCenter = MessageCenter.getInstance();
const sendMessage = messageCenter.getMessageSender('affine');
const { messageCode } = MessageCenter;
class RequestError extends Error {
constructor(message: string) {
super(message);
this.name = 'RequestError';
}
}
export interface GetWorkspaceDetailParams {
id: string;
}
@@ -26,13 +39,18 @@ export interface Workspace {
}
export async function getWorkspaces(): Promise<Workspace[]> {
return client
.get('api/workspace', {
headers: {
'Cache-Control': 'no-cache',
},
})
.json();
try {
return client
.get('api/workspace', {
headers: {
'Cache-Control': 'no-cache',
},
})
.json();
} catch (error) {
sendMessage(messageCode.loadListFailed);
throw new RequestError('load list failed');
}
}
export interface WorkspaceDetail extends Workspace {
@@ -43,7 +61,13 @@ export interface WorkspaceDetail extends Workspace {
export async function getWorkspaceDetail(
params: GetWorkspaceDetailParams
): Promise<WorkspaceDetail | null> {
return client.get(`api/workspace/${params.id}`).json();
try {
const response = client.get(`api/workspace/${params.id}`);
return response.json();
} catch (error) {
sendMessage(messageCode.getDetailFailed);
throw new RequestError('get detail failed');
}
}
export interface Permission {
@@ -74,7 +98,12 @@ export interface GetWorkspaceMembersParams {
export async function getWorkspaceMembers(
params: GetWorkspaceDetailParams
): Promise<Member[]> {
return client.get(`api/workspace/${params.id}/permission`).json();
try {
return client.get(`api/workspace/${params.id}/permission`).json();
} catch (error) {
sendMessage(messageCode.getMembersFailed);
throw new RequestError('get members failed');
}
}
export interface CreateWorkspaceParams {
@@ -84,7 +113,12 @@ export interface CreateWorkspaceParams {
export async function createWorkspace(
params: CreateWorkspaceParams
): Promise<{ id: string }> {
return client.post('api/workspace', { json: params }).json();
try {
return client.post('api/workspace', { json: params }).json();
} catch (error) {
sendMessage(messageCode.createWorkspaceFailed);
throw new RequestError('create workspace failed');
}
}
export interface UpdateWorkspaceParams {
@@ -95,13 +129,18 @@ export interface UpdateWorkspaceParams {
export async function updateWorkspace(
params: UpdateWorkspaceParams
): Promise<{ public: boolean | null }> {
return client
.post(`api/workspace/${params.id}`, {
json: {
public: params.public,
},
})
.json();
try {
return client
.post(`api/workspace/${params.id}`, {
json: {
public: params.public,
},
})
.json();
} catch (error) {
sendMessage(messageCode.updateWorkspaceFailed);
throw new RequestError('update workspace failed');
}
}
export interface DeleteWorkspaceParams {
@@ -111,7 +150,10 @@ export interface DeleteWorkspaceParams {
export async function deleteWorkspace(
params: DeleteWorkspaceParams
): Promise<void> {
await client.delete(`api/workspace/${params.id}`);
await client.delete(`api/workspace/${params.id}`).catch(() => {
sendMessage(messageCode.deleteWorkspaceFailed);
throw new RequestError('delete workspace failed');
});
}
export interface InviteMemberParams {
@@ -123,13 +165,18 @@ export interface InviteMemberParams {
* Notice: Only support normal(contrast to private) workspace.
*/
export async function inviteMember(params: InviteMemberParams): Promise<void> {
return client
.post(`api/workspace/${params.id}/permission`, {
json: {
email: params.email,
},
})
.json();
try {
return client
.post(`api/workspace/${params.id}/permission`, {
json: {
email: params.email,
},
})
.json();
} catch (error) {
sendMessage(messageCode.inviteMemberFailed);
throw new RequestError('invite member failed');
}
}
export interface RemoveMemberParams {
@@ -137,7 +184,10 @@ export interface RemoveMemberParams {
}
export async function removeMember(params: RemoveMemberParams): Promise<void> {
await client.delete(`api/permission/${params.permissionId}`);
await client.delete(`api/permission/${params.permissionId}`).catch(() => {
sendMessage(messageCode.removeMemberFailed);
throw new RequestError('remove member failed');
});
}
export interface AcceptInvitingParams {
@@ -147,7 +197,10 @@ export interface AcceptInvitingParams {
export async function acceptInviting(
params: AcceptInvitingParams
): Promise<void> {
await bareClient.post(`api/invitation/${params.invitingCode}`);
await bareClient.post(`api/invitation/${params.invitingCode}`).catch(() => {
sendMessage(messageCode.acceptInvitingFailed);
throw new RequestError('accept inviting failed');
});
}
export async function uploadBlob(params: { blob: Blob }): Promise<string> {
@@ -157,7 +210,12 @@ export async function uploadBlob(params: { blob: Blob }): Promise<string> {
export async function getBlob(params: {
blobId: string;
}): Promise<ArrayBuffer> {
return client.get(`api/blob/${params.blobId}`).arrayBuffer();
try {
return client.get(`api/blob/${params.blobId}`).arrayBuffer();
} catch (error) {
sendMessage(messageCode.getBlobFailed);
throw new RequestError('get blob failed');
}
}
export interface LeaveWorkspaceParams {
@@ -165,15 +223,26 @@ export interface LeaveWorkspaceParams {
}
export async function leaveWorkspace({ id }: LeaveWorkspaceParams) {
await client.delete(`api/workspace/${id}/permission`).json();
await client
.delete(`api/workspace/${id}/permission`)
.json()
.catch(() => {
sendMessage(messageCode.leaveWorkspaceFailed);
throw new RequestError('leave workspace failed');
});
}
export async function downloadWorkspace(
workspaceId: string,
published = false
): Promise<ArrayBuffer> {
if (published) {
return bareClient.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
try {
if (published) {
return bareClient.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
}
return client.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
} catch (error) {
sendMessage(messageCode.downloadWorkspaceFailed);
throw new RequestError('download workspace failed');
}
return client.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
}

View File

@@ -22,10 +22,15 @@ export type UpdateWorkspaceMetaParams = Partial<
>;
export class BaseProvider {
/** provider id */
public readonly id: string = 'base';
/** workspace unit collection */
protected _workspaces!: WorkspaceUnitCollectionScope;
protected _logger!: Logger;
protected _messageCenter!: MessageCenter;
/** send message with message center */
protected _sendMessage!: ReturnType<
InstanceType<typeof MessageCenter>['getMessageSender']
>;
public constructor({
logger,
@@ -34,7 +39,7 @@ export class BaseProvider {
}: ProviderConstructorParams) {
this._logger = (logger || defaultLogger) as Logger;
this._workspaces = workspaces;
this._messageCenter = messageCenter;
this._sendMessage = messageCenter.getMessageSender(this.id);
}
/**

View File

@@ -100,7 +100,7 @@ export class LocalProvider extends BaseProvider {
owner: undefined,
syncMode: 'core',
memberCount: 1,
provider: 'local',
provider: this.id,
});
this._workspaces.add(workspaceUnit);
this._storeWorkspaces(this._workspaces.list());

View File

@@ -25,4 +25,5 @@ export type Logger = ReturnType<typeof getLogger>;
export type Message = {
code: number;
message: string;
provider: string;
};