refactor(data-center): remove side effect in affine provider (#1106)
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
import { toast } from '@affine/component';
|
import { toast } from '@affine/component';
|
||||||
import { getApis, MessageCenter } from '@affine/datacenter';
|
import { MessageCenter } from '@affine/datacenter';
|
||||||
|
import { AffineProvider } from '@affine/datacenter';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useEffect } from 'react';
|
import { ReactNode, useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
export function MessageCenterHandler({
|
import { useGlobalState } from '@/store/app';
|
||||||
children,
|
|
||||||
}: {
|
export function MessageCenterHandler({ children }: { children?: ReactNode }) {
|
||||||
children?: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const dataCenter = useGlobalState(useCallback(store => store.dataCenter, []));
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const instance = MessageCenter.getInstance();
|
const instance = MessageCenter.getInstance();
|
||||||
if (instance) {
|
if (instance) {
|
||||||
@@ -18,7 +18,15 @@ export function MessageCenterHandler({
|
|||||||
// todo: more specific message for accessing different resources
|
// todo: more specific message for accessing different resources
|
||||||
// todo: error toast style
|
// todo: error toast style
|
||||||
toast('You have no permission to access this workspace');
|
toast('You have no permission to access this workspace');
|
||||||
getApis().auth.clear();
|
// todo(himself65): remove dynamic lookup
|
||||||
|
const affineProvider = dataCenter.providers.find(
|
||||||
|
p => p.id === 'affine'
|
||||||
|
);
|
||||||
|
if (affineProvider && affineProvider instanceof AffineProvider) {
|
||||||
|
affineProvider.apis.auth.clear();
|
||||||
|
} else {
|
||||||
|
console.error('cannot find affine provider, please fix this ASAP');
|
||||||
|
}
|
||||||
// the status of the app right now is unknown, and it won't help if we let
|
// the status of the app right now is unknown, and it won't help if we let
|
||||||
// the app continue and let the user auth the app.
|
// the app continue and let the user auth the app.
|
||||||
// that's why so we need to reload the page for now.
|
// that's why so we need to reload the page for now.
|
||||||
@@ -30,7 +38,7 @@ export function MessageCenterHandler({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [router]);
|
}, [dataCenter?.providers, router]);
|
||||||
|
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,19 +78,19 @@ const App = ({ Component, pageProps }: AppPropsWithLayout) => {
|
|||||||
<ConfirmProvider key="ConfirmProvider" />,
|
<ConfirmProvider key="ConfirmProvider" />,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<MessageCenterHandler>
|
|
||||||
{NoNeedAppStatePageList.includes(router.route) ? (
|
{NoNeedAppStatePageList.includes(router.route) ? (
|
||||||
getLayout(<Component {...pageProps} />)
|
getLayout(<Component {...pageProps} />)
|
||||||
) : (
|
) : (
|
||||||
<Suspense fallback={<PageLoading />}>
|
<Suspense fallback={<PageLoading />}>
|
||||||
<DataCenterPreloader>
|
<DataCenterPreloader>
|
||||||
|
<MessageCenterHandler>
|
||||||
<AppDefender>
|
<AppDefender>
|
||||||
{getLayout(<Component {...pageProps} />)}
|
{getLayout(<Component {...pageProps} />)}
|
||||||
</AppDefender>
|
</AppDefender>
|
||||||
|
</MessageCenterHandler>
|
||||||
</DataCenterPreloader>
|
</DataCenterPreloader>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
)}
|
)}
|
||||||
</MessageCenterHandler>
|
|
||||||
</ProviderComposer>
|
</ProviderComposer>
|
||||||
</GlobalAppProvider>
|
</GlobalAppProvider>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const getDataCenter = _initializeDataCenter();
|
|||||||
export type { DataCenter };
|
export type { DataCenter };
|
||||||
export { getLogger } from './logger';
|
export { getLogger } from './logger';
|
||||||
export * from './message';
|
export * from './message';
|
||||||
|
export { AffineProvider } from './provider/affine';
|
||||||
export * from './provider/affine/apis';
|
export * from './provider/affine/apis';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export { WorkspaceUnit } from './workspace-unit';
|
export { WorkspaceUnit } from './workspace-unit';
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
import { KyInstance } from 'ky/distribution/types/ky';
|
||||||
|
|
||||||
import { MessageCenter } from '../../message';
|
import { MessageCenter } from '../../message';
|
||||||
import type { User } from '../../types';
|
import type { User } from '../../types';
|
||||||
@@ -12,16 +13,12 @@ import type {
|
|||||||
} from '../base';
|
} from '../base';
|
||||||
import { BaseProvider } from '../base';
|
import { BaseProvider } from '../base';
|
||||||
import type { Apis, WorkspaceDetail } from './apis';
|
import type { Apis, WorkspaceDetail } from './apis';
|
||||||
// import { IndexedDBProvider } from '../local/indexeddb';
|
|
||||||
import { getApis, Workspace } from './apis';
|
import { getApis, Workspace } from './apis';
|
||||||
|
import { createGoogleAuth } from './apis/google';
|
||||||
|
import { createAuthClient, createBareClient } from './apis/request';
|
||||||
import { WebsocketClient } from './channel';
|
import { WebsocketClient } from './channel';
|
||||||
import { WebsocketProvider } from './sync';
|
import { WebsocketProvider } from './sync';
|
||||||
import {
|
import { createWorkspaceUnit, loadWorkspaceUnit, migrateBlobDB } from './utils';
|
||||||
createBlocksuiteWorkspaceWithAuth,
|
|
||||||
createWorkspaceUnit,
|
|
||||||
loadWorkspaceUnit,
|
|
||||||
migrateBlobDB,
|
|
||||||
} from './utils';
|
|
||||||
|
|
||||||
type ChannelMessage = {
|
type ChannelMessage = {
|
||||||
ws_list: Workspace[];
|
ws_list: Workspace[];
|
||||||
@@ -39,6 +36,9 @@ const {
|
|||||||
} = BlocksuiteWorkspace;
|
} = BlocksuiteWorkspace;
|
||||||
|
|
||||||
export class AffineProvider extends BaseProvider {
|
export class AffineProvider extends BaseProvider {
|
||||||
|
private readonly bareClient: KyInstance;
|
||||||
|
private readonly authClient: KyInstance;
|
||||||
|
|
||||||
public id = 'affine';
|
public id = 'affine';
|
||||||
private _wsMap: Map<BlocksuiteWorkspace, WebsocketProvider> = new Map();
|
private _wsMap: Map<BlocksuiteWorkspace, WebsocketProvider> = new Map();
|
||||||
private _apis: Apis;
|
private _apis: Apis;
|
||||||
@@ -52,7 +52,14 @@ export class AffineProvider extends BaseProvider {
|
|||||||
|
|
||||||
constructor({ apis, ...params }: AffineProviderConstructorParams) {
|
constructor({ apis, ...params }: AffineProviderConstructorParams) {
|
||||||
super(params);
|
super(params);
|
||||||
this._apis = apis || getApis();
|
this.bareClient = createBareClient('/');
|
||||||
|
const googleAuth = createGoogleAuth(this.bareClient);
|
||||||
|
this.authClient = createAuthClient(this.bareClient, googleAuth);
|
||||||
|
this._apis = apis || getApis(this.bareClient, this.authClient, googleAuth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get apis() {
|
||||||
|
return Object.freeze(this._apis);
|
||||||
}
|
}
|
||||||
|
|
||||||
override async init() {
|
override async init() {
|
||||||
@@ -80,6 +87,7 @@ export class AffineProvider extends BaseProvider {
|
|||||||
window.location.host
|
window.location.host
|
||||||
}/api/global/sync/`,
|
}/api/global/sync/`,
|
||||||
this._logger,
|
this._logger,
|
||||||
|
this._apis.auth,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
token: this._apis.auth.refresh,
|
token: this._apis.auth.refresh,
|
||||||
@@ -370,7 +378,8 @@ export class AffineProvider extends BaseProvider {
|
|||||||
public override async createWorkspace(
|
public override async createWorkspace(
|
||||||
meta: CreateWorkspaceInfoParams
|
meta: CreateWorkspaceInfoParams
|
||||||
): Promise<WorkspaceUnit | undefined> {
|
): Promise<WorkspaceUnit | undefined> {
|
||||||
const workspaceUnitForUpload = await createWorkspaceUnit({
|
const workspaceUnitForUpload = await createWorkspaceUnit(
|
||||||
|
{
|
||||||
id: '',
|
id: '',
|
||||||
name: meta.name,
|
name: meta.name,
|
||||||
avatar: undefined,
|
avatar: undefined,
|
||||||
@@ -379,7 +388,9 @@ export class AffineProvider extends BaseProvider {
|
|||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
provider: this.id,
|
provider: this.id,
|
||||||
syncMode: 'core',
|
syncMode: 'core',
|
||||||
});
|
},
|
||||||
|
this._apis
|
||||||
|
);
|
||||||
const { id } = await this._apis.createWorkspace(
|
const { id } = await this._apis.createWorkspace(
|
||||||
new Blob([
|
new Blob([
|
||||||
encodeStateAsUpdate(workspaceUnitForUpload.blocksuiteWorkspace!.doc)
|
encodeStateAsUpdate(workspaceUnitForUpload.blocksuiteWorkspace!.doc)
|
||||||
@@ -387,7 +398,8 @@ export class AffineProvider extends BaseProvider {
|
|||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
|
||||||
const workspaceUnit = await createWorkspaceUnit({
|
const workspaceUnit = await createWorkspaceUnit(
|
||||||
|
{
|
||||||
id,
|
id,
|
||||||
name: meta.name,
|
name: meta.name,
|
||||||
avatar: undefined,
|
avatar: undefined,
|
||||||
@@ -396,7 +408,9 @@ export class AffineProvider extends BaseProvider {
|
|||||||
memberCount: 1,
|
memberCount: 1,
|
||||||
provider: this.id,
|
provider: this.id,
|
||||||
syncMode: 'core',
|
syncMode: 'core',
|
||||||
});
|
},
|
||||||
|
this._apis
|
||||||
|
);
|
||||||
|
|
||||||
this._workspaces.add(workspaceUnit);
|
this._workspaces.add(workspaceUnit);
|
||||||
|
|
||||||
@@ -446,7 +460,8 @@ export class AffineProvider extends BaseProvider {
|
|||||||
});
|
});
|
||||||
await migrateBlobDB(workspaceUnit.id, id);
|
await migrateBlobDB(workspaceUnit.id, id);
|
||||||
|
|
||||||
const blocksuiteWorkspace = await createBlocksuiteWorkspaceWithAuth(id);
|
const blocksuiteWorkspace =
|
||||||
|
await this._apis.createBlockSuiteWorkspaceWithAuth(id);
|
||||||
assert(workspaceUnit.blocksuiteWorkspace);
|
assert(workspaceUnit.blocksuiteWorkspace);
|
||||||
await applyUpdate(
|
await applyUpdate(
|
||||||
blocksuiteWorkspace,
|
blocksuiteWorkspace,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { describe, expect, test } from 'vitest';
|
import { describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
import { Auth } from '../auth';
|
import { GoogleAuth } from '../google';
|
||||||
|
|
||||||
describe('class Auth', () => {
|
describe('class Auth', () => {
|
||||||
test('parse tokens', () => {
|
test('parse tokens', () => {
|
||||||
const tokenString = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzU2Nzk1MjAsImlkIjo2LCJuYW1lIjoidGVzdCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJhdmF0YXJfdXJsIjoiaHR0cHM6Ly90ZXN0LmNvbS9hdmF0YXIiLCJjcmVhdGVkX2F0IjoxNjc1Njc4OTIwMzU4fQ.R8GxrNhn3gNumtapthrP6_J5eQjXLV7i-LanSPqe7hw`;
|
const tokenString = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzU2Nzk1MjAsImlkIjo2LCJuYW1lIjoidGVzdCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJhdmF0YXJfdXJsIjoiaHR0cHM6Ly90ZXN0LmNvbS9hdmF0YXIiLCJjcmVhdGVkX2F0IjoxNjc1Njc4OTIwMzU4fQ.R8GxrNhn3gNumtapthrP6_J5eQjXLV7i-LanSPqe7hw`;
|
||||||
expect(Auth.parseIdToken(tokenString)).toEqual({
|
expect(GoogleAuth.parseIdToken(tokenString)).toEqual({
|
||||||
avatar_url: 'https://test.com/avatar',
|
avatar_url: 'https://test.com/avatar',
|
||||||
created_at: 1675678920358,
|
created_at: 1675678920358,
|
||||||
email: 'test@gmail.com',
|
email: 'test@gmail.com',
|
||||||
@@ -17,6 +17,6 @@ describe('class Auth', () => {
|
|||||||
|
|
||||||
test('parse invalid tokens', () => {
|
test('parse invalid tokens', () => {
|
||||||
const tokenString = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.aaa.R8GxrNhn3gNumtapthrP6_J5eQjXLV7i-LanSPqe7hw`;
|
const tokenString = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.aaa.R8GxrNhn3gNumtapthrP6_J5eQjXLV7i-LanSPqe7hw`;
|
||||||
expect(Auth.parseIdToken(tokenString)).toEqual(null);
|
expect(GoogleAuth.parseIdToken(tokenString)).toEqual(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import {
|
|||||||
signOut,
|
signOut,
|
||||||
} from 'firebase/auth';
|
} from 'firebase/auth';
|
||||||
import { decode } from 'js-base64';
|
import { decode } from 'js-base64';
|
||||||
|
import { KyInstance } from 'ky/distribution/types/ky';
|
||||||
|
|
||||||
import { getLogger } from '../../../logger';
|
import { getLogger } from '../../../logger';
|
||||||
import { storage } from '../storage';
|
import { storage } from '../storage';
|
||||||
import { bareClient } from './request';
|
|
||||||
|
|
||||||
export interface AccessTokenMessage {
|
export interface AccessTokenMessage {
|
||||||
created_at: number;
|
created_at: number;
|
||||||
@@ -43,20 +43,24 @@ const AFFINE_LOGIN_STORAGE_KEY = 'affine:login';
|
|||||||
* Use refresh token to get a new access token (JWT)
|
* Use refresh token to get a new access token (JWT)
|
||||||
* The returned token also contains the user info payload.
|
* The returned token also contains the user info payload.
|
||||||
*/
|
*/
|
||||||
const doLogin = (params: LoginParams): Promise<LoginResponse> =>
|
const createDoLogin =
|
||||||
|
(bareClient: KyInstance) =>
|
||||||
|
(params: LoginParams): Promise<LoginResponse> =>
|
||||||
bareClient.post('api/user/token', { json: params }).json();
|
bareClient.post('api/user/token', { json: params }).json();
|
||||||
|
|
||||||
export class Auth {
|
export class GoogleAuth {
|
||||||
private readonly _logger;
|
private readonly _logger;
|
||||||
private _accessToken = ''; // idtoken (JWT)
|
private _accessToken = ''; // idtoken (JWT)
|
||||||
private _refreshToken = '';
|
private _refreshToken = '';
|
||||||
|
|
||||||
private _user: AccessTokenMessage | null = null;
|
private _user: AccessTokenMessage | null = null;
|
||||||
private _padding?: Promise<LoginResponse>;
|
private _padding?: Promise<LoginResponse>;
|
||||||
|
private readonly _doLogin: ReturnType<typeof createDoLogin>;
|
||||||
|
|
||||||
constructor() {
|
constructor(bareClient: KyInstance) {
|
||||||
this._logger = getLogger('token');
|
this._logger = getLogger('token');
|
||||||
this._logger.enabled = true;
|
this._logger.enabled = true;
|
||||||
|
this._doLogin = createDoLogin(bareClient);
|
||||||
|
|
||||||
this.restoreLogin();
|
this.restoreLogin();
|
||||||
}
|
}
|
||||||
@@ -64,7 +68,7 @@ export class Auth {
|
|||||||
setLogin(login: LoginResponse) {
|
setLogin(login: LoginResponse) {
|
||||||
this._accessToken = login.token;
|
this._accessToken = login.token;
|
||||||
this._refreshToken = login.refresh;
|
this._refreshToken = login.refresh;
|
||||||
this._user = Auth.parseIdToken(this._accessToken);
|
this._user = GoogleAuth.parseIdToken(this._accessToken);
|
||||||
|
|
||||||
this.triggerChange(this._user);
|
this.triggerChange(this._user);
|
||||||
this.storeLogin();
|
this.storeLogin();
|
||||||
@@ -94,14 +98,14 @@ export class Auth {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async initToken(token: string) {
|
async initToken(token: string) {
|
||||||
const res = await doLogin({ token, type: 'Google' });
|
const res = await this._doLogin({ token, type: 'Google' });
|
||||||
this.setLogin(res);
|
this.setLogin(res);
|
||||||
return this._user;
|
return this._user;
|
||||||
}
|
}
|
||||||
|
|
||||||
async refreshToken(refreshToken?: string) {
|
async refreshToken(refreshToken?: string) {
|
||||||
if (!this._padding) {
|
if (!this._padding) {
|
||||||
this._padding = doLogin({
|
this._padding = this._doLogin({
|
||||||
type: 'Refresh',
|
type: 'Refresh',
|
||||||
token: refreshToken || this._refreshToken,
|
token: refreshToken || this._refreshToken,
|
||||||
});
|
});
|
||||||
@@ -181,9 +185,11 @@ export class Auth {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const auth = new Auth();
|
export function createGoogleAuth(bareAuth: KyInstance): GoogleAuth {
|
||||||
|
return new GoogleAuth(bareAuth);
|
||||||
|
}
|
||||||
|
|
||||||
export const getAuthorizer = () => {
|
export const getAuthorizer = (googleAuth: GoogleAuth) => {
|
||||||
let _firebaseAuth: FirebaseAuth | null = null;
|
let _firebaseAuth: FirebaseAuth | null = null;
|
||||||
const logger = getLogger('authorizer');
|
const logger = getLogger('authorizer');
|
||||||
|
|
||||||
@@ -225,7 +231,7 @@ export const getAuthorizer = () => {
|
|||||||
const idToken = await getToken();
|
const idToken = await getToken();
|
||||||
let loginUser: AccessTokenMessage | null = null;
|
let loginUser: AccessTokenMessage | null = null;
|
||||||
if (idToken) {
|
if (idToken) {
|
||||||
loginUser = await auth.initToken(idToken);
|
loginUser = await googleAuth.initToken(idToken);
|
||||||
} else {
|
} else {
|
||||||
const firebaseAuth = getAuth();
|
const firebaseAuth = getAuth();
|
||||||
if (firebaseAuth) {
|
if (firebaseAuth) {
|
||||||
@@ -237,7 +243,7 @@ export const getAuthorizer = () => {
|
|||||||
});
|
});
|
||||||
const user = await signInWithPopup(firebaseAuth, googleAuthProvider);
|
const user = await signInWithPopup(firebaseAuth, googleAuthProvider);
|
||||||
const idToken = await user.user.getIdToken();
|
const idToken = await user.user.getIdToken();
|
||||||
loginUser = await auth.initToken(idToken);
|
loginUser = await googleAuth.initToken(idToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return loginUser;
|
return loginUser;
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
// export { token } from './token.js';
|
export type { Callback } from './google';
|
||||||
export type { Callback } from './auth';
|
|
||||||
|
|
||||||
import { getAuthorizer } from './auth';
|
import { KyInstance } from 'ky/distribution/types/ky';
|
||||||
import { auth } from './auth';
|
|
||||||
import * as user from './user';
|
import { createGoogleAuth, getAuthorizer, GoogleAuth } from './google';
|
||||||
import * as workspace from './workspace';
|
import { createUserApis } from './user';
|
||||||
|
import { createWorkspaceApis } from './workspace';
|
||||||
|
|
||||||
// See https://twitter.com/mattpocockuk/status/1622730173446557697
|
// See https://twitter.com/mattpocockuk/status/1622730173446557697
|
||||||
// TODO: move to ts utils?
|
// TODO: move to ts utils?
|
||||||
@@ -14,27 +14,31 @@ type Prettify<T> = {
|
|||||||
} & {};
|
} & {};
|
||||||
|
|
||||||
export type Apis = Prettify<
|
export type Apis = Prettify<
|
||||||
typeof user &
|
ReturnType<typeof createUserApis> &
|
||||||
Omit<typeof workspace, 'WorkspaceType' | 'PermissionType'> & {
|
ReturnType<typeof createWorkspaceApis> & {
|
||||||
signInWithGoogle: ReturnType<typeof getAuthorizer>[0];
|
signInWithGoogle: ReturnType<typeof getAuthorizer>[0];
|
||||||
onAuthStateChanged: ReturnType<typeof getAuthorizer>[1];
|
onAuthStateChanged: ReturnType<typeof getAuthorizer>[1];
|
||||||
signOutFirebase: ReturnType<typeof getAuthorizer>[2];
|
signOutFirebase: ReturnType<typeof getAuthorizer>[2];
|
||||||
} & { auth: typeof auth }
|
} & { auth: ReturnType<typeof createGoogleAuth> }
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export const getApis = (): Apis => {
|
export const getApis = (
|
||||||
|
bareClient: KyInstance,
|
||||||
|
authClient: KyInstance,
|
||||||
|
googleAuth: GoogleAuth
|
||||||
|
): Apis => {
|
||||||
const [signInWithGoogle, onAuthStateChanged, signOutFirebase] =
|
const [signInWithGoogle, onAuthStateChanged, signOutFirebase] =
|
||||||
getAuthorizer();
|
getAuthorizer(googleAuth);
|
||||||
return {
|
return {
|
||||||
...user,
|
...createUserApis(bareClient, authClient),
|
||||||
...workspace,
|
...createWorkspaceApis(bareClient, authClient, googleAuth),
|
||||||
signInWithGoogle,
|
signInWithGoogle,
|
||||||
signOutFirebase,
|
signOutFirebase,
|
||||||
onAuthStateChanged,
|
onAuthStateChanged,
|
||||||
auth,
|
auth: googleAuth,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type { AccessTokenMessage } from './auth';
|
export type { AccessTokenMessage } from './google';
|
||||||
export type { Member, Workspace, WorkspaceDetail } from './workspace';
|
export type { Member, Workspace, WorkspaceDetail } from './workspace';
|
||||||
export * from './workspace';
|
export * from './workspace';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import ky from 'ky-universal';
|
import ky from 'ky-universal';
|
||||||
|
|
||||||
import { MessageCenter } from '../../../message';
|
import { MessageCenter } from '../../../message';
|
||||||
import { auth } from './auth';
|
import { GoogleAuth } from './google';
|
||||||
|
|
||||||
type KyInstance = typeof ky;
|
type KyInstance = typeof ky;
|
||||||
|
|
||||||
@@ -9,8 +9,9 @@ const messageCenter = MessageCenter.getInstance();
|
|||||||
|
|
||||||
const _sendMessage = messageCenter.getMessageSender('affine');
|
const _sendMessage = messageCenter.getMessageSender('affine');
|
||||||
|
|
||||||
export const bareClient: KyInstance = ky.extend({
|
export const createBareClient = (prefixUrl: string): KyInstance =>
|
||||||
prefixUrl: '/',
|
ky.extend({
|
||||||
|
prefixUrl: prefixUrl,
|
||||||
retry: 1,
|
retry: 1,
|
||||||
// todo: report timeout error
|
// todo: report timeout error
|
||||||
timeout: 60000,
|
timeout: 60000,
|
||||||
@@ -25,25 +26,29 @@ export const bareClient: KyInstance = ky.extend({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const refreshTokenIfExpired = async () => {
|
const refreshTokenIfExpired = async (googleAuth: GoogleAuth) => {
|
||||||
if (auth.isLogin && auth.isExpired) {
|
if (googleAuth.isLogin && googleAuth.isExpired) {
|
||||||
try {
|
try {
|
||||||
await auth.refreshToken();
|
await googleAuth.refreshToken();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return new Response('Unauthorized', { status: 401 });
|
return new Response('Unauthorized', { status: 401 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const client: KyInstance = bareClient.extend({
|
export const createAuthClient = (
|
||||||
|
bareClient: KyInstance,
|
||||||
|
googleAuth: GoogleAuth
|
||||||
|
): KyInstance =>
|
||||||
|
bareClient.extend({
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeRequest: [
|
beforeRequest: [
|
||||||
async request => {
|
async request => {
|
||||||
if (auth.isLogin) {
|
if (googleAuth.isLogin) {
|
||||||
await refreshTokenIfExpired();
|
await refreshTokenIfExpired(googleAuth);
|
||||||
request.headers.set('Authorization', auth.token);
|
request.headers.set('Authorization', googleAuth.token);
|
||||||
} else {
|
} else {
|
||||||
return new Response('Unauthorized', { status: 401 });
|
return new Response('Unauthorized', { status: 401 });
|
||||||
}
|
}
|
||||||
@@ -52,9 +57,9 @@ export const client: KyInstance = bareClient.extend({
|
|||||||
|
|
||||||
beforeRetry: [
|
beforeRetry: [
|
||||||
async ({ request }) => {
|
async ({ request }) => {
|
||||||
await refreshTokenIfExpired();
|
await refreshTokenIfExpired(googleAuth);
|
||||||
request.headers.set('Authorization', auth.token);
|
request.headers.set('Authorization', googleAuth.token);
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { client } from './request';
|
import { KyInstance } from 'ky/distribution/types/ky';
|
||||||
|
|
||||||
export interface GetUserByEmailParams {
|
export interface GetUserByEmailParams {
|
||||||
email: string;
|
email: string;
|
||||||
@@ -13,9 +13,13 @@ export interface User {
|
|||||||
create_at: string;
|
create_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUserByEmail(
|
export function createUserApis(bareClient: KyInstance, authClient: KyInstance) {
|
||||||
|
return {
|
||||||
|
getUserByEmail: async (
|
||||||
params: GetUserByEmailParams
|
params: GetUserByEmailParams
|
||||||
): Promise<User[] | null> {
|
): Promise<User[] | null> => {
|
||||||
const searchParams = new URLSearchParams({ ...params });
|
const searchParams = new URLSearchParams({ ...params });
|
||||||
return client.get('api/user', { searchParams }).json<User[] | null>();
|
return authClient.get('api/user', { searchParams }).json<User[] | null>();
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
import { KyInstance } from 'ky/distribution/types/ky';
|
||||||
|
|
||||||
import { MessageCenter } from '../../../message';
|
import { MessageCenter } from '../../../message';
|
||||||
import { bareClient, client } from './request';
|
import { createBlocksuiteWorkspace as _createBlocksuiteWorkspace } from '../../../utils';
|
||||||
|
import { GoogleAuth } from './google';
|
||||||
import type { User } from './user';
|
import type { User } from './user';
|
||||||
|
|
||||||
const messageCenter = MessageCenter.getInstance();
|
const messageCenter = MessageCenter.getInstance();
|
||||||
@@ -15,6 +18,7 @@ class RequestError extends Error {
|
|||||||
this.cause = cause;
|
this.cause = cause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetWorkspaceDetailParams {
|
export interface GetWorkspaceDetailParams {
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
@@ -39,37 +43,11 @@ export interface Workspace {
|
|||||||
create_at: number;
|
create_at: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getWorkspaces(): Promise<Workspace[]> {
|
|
||||||
try {
|
|
||||||
return await client
|
|
||||||
.get('api/workspace', {
|
|
||||||
headers: {
|
|
||||||
'Cache-Control': 'no-cache',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.json();
|
|
||||||
} catch (error) {
|
|
||||||
sendMessage(messageCode.loadListFailed);
|
|
||||||
throw new RequestError('load list failed', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WorkspaceDetail extends Workspace {
|
export interface WorkspaceDetail extends Workspace {
|
||||||
owner: User;
|
owner: User;
|
||||||
member_count: number;
|
member_count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getWorkspaceDetail(
|
|
||||||
params: GetWorkspaceDetailParams
|
|
||||||
): Promise<WorkspaceDetail | null> {
|
|
||||||
try {
|
|
||||||
return await client.get(`api/workspace/${params.id}`).json();
|
|
||||||
} catch (error) {
|
|
||||||
sendMessage(messageCode.getDetailFailed);
|
|
||||||
throw new RequestError('get detail failed', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Permission {
|
export interface Permission {
|
||||||
id: string;
|
id: string;
|
||||||
type: PermissionType;
|
type: PermissionType;
|
||||||
@@ -97,42 +75,93 @@ export interface GetWorkspaceMembersParams {
|
|||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getWorkspaceMembers(
|
|
||||||
params: GetWorkspaceDetailParams
|
|
||||||
): Promise<Member[]> {
|
|
||||||
try {
|
|
||||||
return await client.get(`api/workspace/${params.id}/permission`).json();
|
|
||||||
} catch (error) {
|
|
||||||
sendMessage(messageCode.getMembersFailed);
|
|
||||||
throw new RequestError('get members failed', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateWorkspaceParams {
|
export interface CreateWorkspaceParams {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createWorkspace(
|
|
||||||
encodedYDoc: Blob
|
|
||||||
): Promise<{ id: string }> {
|
|
||||||
try {
|
|
||||||
return await client.post('api/workspace', { body: encodedYDoc }).json();
|
|
||||||
} catch (error) {
|
|
||||||
sendMessage(messageCode.createWorkspaceFailed);
|
|
||||||
throw new RequestError('create workspace failed', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UpdateWorkspaceParams {
|
export interface UpdateWorkspaceParams {
|
||||||
id: string;
|
id: string;
|
||||||
public: boolean;
|
public: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateWorkspace(
|
export interface DeleteWorkspaceParams {
|
||||||
params: UpdateWorkspaceParams
|
id: string;
|
||||||
): Promise<{ public: boolean | null }> {
|
}
|
||||||
|
|
||||||
|
export interface InviteMemberParams {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RemoveMemberParams {
|
||||||
|
permissionId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AcceptInvitingParams {
|
||||||
|
invitingCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LeaveWorkspaceParams {
|
||||||
|
id: number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createWorkspaceApis(
|
||||||
|
bareClient: KyInstance,
|
||||||
|
authClient: KyInstance,
|
||||||
|
googleAuth: GoogleAuth
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
getWorkspaces: async (): Promise<Workspace[]> => {
|
||||||
try {
|
try {
|
||||||
return await client
|
return await authClient
|
||||||
|
.get('api/workspace', {
|
||||||
|
headers: {
|
||||||
|
'Cache-Control': 'no-cache',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.json();
|
||||||
|
} catch (error) {
|
||||||
|
sendMessage(messageCode.loadListFailed);
|
||||||
|
throw new RequestError('load list failed', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getWorkspaceDetail: async (
|
||||||
|
params: GetWorkspaceDetailParams
|
||||||
|
): Promise<WorkspaceDetail | null> => {
|
||||||
|
try {
|
||||||
|
return await authClient.get(`api/workspace/${params.id}`).json();
|
||||||
|
} catch (error) {
|
||||||
|
sendMessage(messageCode.getDetailFailed);
|
||||||
|
throw new RequestError('get detail failed', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getWorkspaceMembers: async (
|
||||||
|
params: GetWorkspaceDetailParams
|
||||||
|
): Promise<Member[]> => {
|
||||||
|
try {
|
||||||
|
return await authClient
|
||||||
|
.get(`api/workspace/${params.id}/permission`)
|
||||||
|
.json();
|
||||||
|
} catch (error) {
|
||||||
|
sendMessage(messageCode.getMembersFailed);
|
||||||
|
throw new RequestError('get members failed', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
createWorkspace: async (encodedYDoc: Blob): Promise<{ id: string }> => {
|
||||||
|
try {
|
||||||
|
return await authClient
|
||||||
|
.post('api/workspace', { body: encodedYDoc })
|
||||||
|
.json();
|
||||||
|
} catch (error) {
|
||||||
|
sendMessage(messageCode.createWorkspaceFailed);
|
||||||
|
throw new RequestError('create workspace failed', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
updateWorkspace: async (
|
||||||
|
params: UpdateWorkspaceParams
|
||||||
|
): Promise<{ public: boolean | null }> => {
|
||||||
|
try {
|
||||||
|
return await authClient
|
||||||
.post(`api/workspace/${params.id}`, {
|
.post(`api/workspace/${params.id}`, {
|
||||||
json: {
|
json: {
|
||||||
public: params.public,
|
public: params.public,
|
||||||
@@ -143,34 +172,22 @@ export async function updateWorkspace(
|
|||||||
sendMessage(messageCode.updateWorkspaceFailed);
|
sendMessage(messageCode.updateWorkspaceFailed);
|
||||||
throw new RequestError('update workspace failed', error);
|
throw new RequestError('update workspace failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
deleteWorkspace: async (params: DeleteWorkspaceParams): Promise<void> => {
|
||||||
export interface DeleteWorkspaceParams {
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function deleteWorkspace(
|
|
||||||
params: DeleteWorkspaceParams
|
|
||||||
): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
await client.delete(`api/workspace/${params.id}`);
|
await authClient.delete(`api/workspace/${params.id}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
sendMessage(messageCode.deleteWorkspaceFailed);
|
sendMessage(messageCode.deleteWorkspaceFailed);
|
||||||
throw new RequestError('delete workspace failed', error);
|
throw new RequestError('delete workspace failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
export interface InviteMemberParams {
|
/**
|
||||||
id: string;
|
|
||||||
email: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notice: Only support normal(contrast to private) workspace.
|
* Notice: Only support normal(contrast to private) workspace.
|
||||||
*/
|
*/
|
||||||
export async function inviteMember(params: InviteMemberParams): Promise<void> {
|
inviteMember: async (params: InviteMemberParams): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
await client.post(`api/workspace/${params.id}/permission`, {
|
await authClient.post(`api/workspace/${params.id}/permission`, {
|
||||||
json: {
|
json: {
|
||||||
email: params.email,
|
email: params.email,
|
||||||
},
|
},
|
||||||
@@ -179,28 +196,18 @@ export async function inviteMember(params: InviteMemberParams): Promise<void> {
|
|||||||
sendMessage(messageCode.inviteMemberFailed);
|
sendMessage(messageCode.inviteMemberFailed);
|
||||||
throw new RequestError('invite member failed', error);
|
throw new RequestError('invite member failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
removeMember: async (params: RemoveMemberParams): Promise<void> => {
|
||||||
export interface RemoveMemberParams {
|
|
||||||
permissionId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function removeMember(params: RemoveMemberParams): Promise<void> {
|
|
||||||
try {
|
try {
|
||||||
await client.delete(`api/permission/${params.permissionId}`);
|
await authClient.delete(`api/permission/${params.permissionId}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
sendMessage(messageCode.removeMemberFailed);
|
sendMessage(messageCode.removeMemberFailed);
|
||||||
throw new RequestError('remove member failed', error);
|
throw new RequestError('remove member failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
acceptInviting: async (
|
||||||
export interface AcceptInvitingParams {
|
|
||||||
invitingCode: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function acceptInviting(
|
|
||||||
params: AcceptInvitingParams
|
params: AcceptInvitingParams
|
||||||
): Promise<Permission> {
|
): Promise<Permission> => {
|
||||||
try {
|
try {
|
||||||
return await bareClient
|
return await bareClient
|
||||||
.post(`api/invitation/${params.invitingCode}`)
|
.post(`api/invitation/${params.invitingCode}`)
|
||||||
@@ -209,49 +216,53 @@ export async function acceptInviting(
|
|||||||
sendMessage(messageCode.acceptInvitingFailed);
|
sendMessage(messageCode.acceptInvitingFailed);
|
||||||
throw new RequestError('accept inviting failed', error);
|
throw new RequestError('accept inviting failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
uploadBlob: async (params: { blob: Blob }): Promise<string> => {
|
||||||
export async function uploadBlob(params: { blob: Blob }): Promise<string> {
|
return authClient.put('api/blob', { body: params.blob }).text();
|
||||||
return client.put('api/blob', { body: params.blob }).text();
|
},
|
||||||
}
|
getBlob: async (params: { blobId: string }): Promise<ArrayBuffer> => {
|
||||||
|
|
||||||
export async function getBlob(params: {
|
|
||||||
blobId: string;
|
|
||||||
}): Promise<ArrayBuffer> {
|
|
||||||
try {
|
try {
|
||||||
return await client.get(`api/blob/${params.blobId}`).arrayBuffer();
|
return await authClient.get(`api/blob/${params.blobId}`).arrayBuffer();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
sendMessage(messageCode.getBlobFailed);
|
sendMessage(messageCode.getBlobFailed);
|
||||||
throw new RequestError('get blob failed', error);
|
throw new RequestError('get blob failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
leaveWorkspace: async ({ id }: LeaveWorkspaceParams) => {
|
||||||
export interface LeaveWorkspaceParams {
|
|
||||||
id: number | string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function leaveWorkspace({ id }: LeaveWorkspaceParams) {
|
|
||||||
try {
|
try {
|
||||||
await client.delete(`api/workspace/${id}/permission`);
|
await authClient.delete(`api/workspace/${id}/permission`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
sendMessage(messageCode.leaveWorkspaceFailed);
|
sendMessage(messageCode.leaveWorkspaceFailed);
|
||||||
throw new RequestError('leave workspace failed', error);
|
throw new RequestError('leave workspace failed', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
downloadWorkspace: async (
|
||||||
export async function downloadWorkspace(
|
|
||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
published = false
|
published = false
|
||||||
): Promise<ArrayBuffer> {
|
): Promise<ArrayBuffer> => {
|
||||||
try {
|
try {
|
||||||
if (published) {
|
if (published) {
|
||||||
return await bareClient
|
return await bareClient
|
||||||
.get(`api/public/doc/${workspaceId}`)
|
.get(`api/public/doc/${workspaceId}`)
|
||||||
.arrayBuffer();
|
.arrayBuffer();
|
||||||
}
|
}
|
||||||
return await client.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
|
return await authClient
|
||||||
|
.get(`api/workspace/${workspaceId}/doc`)
|
||||||
|
.arrayBuffer();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
sendMessage(messageCode.downloadWorkspaceFailed);
|
sendMessage(messageCode.downloadWorkspaceFailed);
|
||||||
throw new RequestError('download workspace failed', error);
|
throw new RequestError('download workspace failed', error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
createBlockSuiteWorkspaceWithAuth: async (newWorkspaceId: string) => {
|
||||||
|
if (googleAuth.isExpired && googleAuth.isLogin) {
|
||||||
|
await googleAuth.refreshToken();
|
||||||
|
}
|
||||||
|
return _createBlocksuiteWorkspace(newWorkspaceId, {
|
||||||
|
blobOptionsGetter: (k: string) =>
|
||||||
|
// token could be expired
|
||||||
|
({ api: '/api/workspace', token: googleAuth.token }[k]),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as url from 'lib0/url';
|
|||||||
import * as websocket from 'lib0/websocket';
|
import * as websocket from 'lib0/websocket';
|
||||||
|
|
||||||
import { Logger } from '../../types';
|
import { Logger } from '../../types';
|
||||||
import { auth } from './apis/auth';
|
import { GoogleAuth } from './apis/google';
|
||||||
|
|
||||||
const RECONNECT_INTERVAL_TIME = 500;
|
const RECONNECT_INTERVAL_TIME = 500;
|
||||||
const MAX_RECONNECT_TIMES = 50;
|
const MAX_RECONNECT_TIMES = 50;
|
||||||
@@ -11,9 +11,11 @@ export class WebsocketClient extends websocket.WebsocketClient {
|
|||||||
public shouldReconnect = false;
|
public shouldReconnect = false;
|
||||||
private _logger: Logger;
|
private _logger: Logger;
|
||||||
private _retryTimes = 0;
|
private _retryTimes = 0;
|
||||||
|
private _auth: GoogleAuth;
|
||||||
constructor(
|
constructor(
|
||||||
serverUrl: string,
|
serverUrl: string,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
|
auth: GoogleAuth,
|
||||||
options?: ConstructorParameters<typeof websocket.WebsocketClient>[1] & {
|
options?: ConstructorParameters<typeof websocket.WebsocketClient>[1] & {
|
||||||
params: Record<string, string>;
|
params: Record<string, string>;
|
||||||
}
|
}
|
||||||
@@ -27,6 +29,7 @@ export class WebsocketClient extends websocket.WebsocketClient {
|
|||||||
const newUrl =
|
const newUrl =
|
||||||
serverUrl + '/' + (encodedParams.length === 0 ? '' : '?' + encodedParams);
|
serverUrl + '/' + (encodedParams.length === 0 ? '' : '?' + encodedParams);
|
||||||
super(newUrl, options);
|
super(newUrl, options);
|
||||||
|
this._auth = auth;
|
||||||
this._logger = logger;
|
this._logger = logger;
|
||||||
this._setupChannel();
|
this._setupChannel();
|
||||||
}
|
}
|
||||||
@@ -41,7 +44,7 @@ export class WebsocketClient extends websocket.WebsocketClient {
|
|||||||
this.on('disconnect', ({ error }: { error: Error }) => {
|
this.on('disconnect', ({ error }: { error: Error }) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
// Try reconnect if connect error has occurred
|
// Try reconnect if connect error has occurred
|
||||||
if (this.shouldReconnect && auth.isLogin && !this.connected) {
|
if (this.shouldReconnect && this._auth.isLogin && !this.connected) {
|
||||||
try {
|
try {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (this._retryTimes <= MAX_RECONNECT_TIMES) {
|
if (this._retryTimes <= MAX_RECONNECT_TIMES) {
|
||||||
|
|||||||
@@ -1,29 +1,16 @@
|
|||||||
import { createBlocksuiteWorkspace as _createBlocksuiteWorkspace } from '../../utils';
|
|
||||||
import { applyUpdate } from '../../utils';
|
import { applyUpdate } from '../../utils';
|
||||||
import type { WorkspaceUnitCtorParams } from '../../workspace-unit';
|
import type { WorkspaceUnitCtorParams } from '../../workspace-unit';
|
||||||
import { WorkspaceUnit } from '../../workspace-unit';
|
import { WorkspaceUnit } from '../../workspace-unit';
|
||||||
import { setDefaultAvatar } from '../utils';
|
import { setDefaultAvatar } from '../utils';
|
||||||
import type { Apis } from './apis';
|
import type { Apis } from './apis';
|
||||||
import { auth } from './apis/auth';
|
|
||||||
import { getDatabase } from './idb-kv';
|
import { getDatabase } from './idb-kv';
|
||||||
|
|
||||||
export const createBlocksuiteWorkspaceWithAuth = async (id: string) => {
|
|
||||||
if (auth.isExpired && auth.isLogin) {
|
|
||||||
await auth.refreshToken();
|
|
||||||
}
|
|
||||||
return _createBlocksuiteWorkspace(id, {
|
|
||||||
blobOptionsGetter: (k: string) =>
|
|
||||||
// token could be expired
|
|
||||||
({ api: '/api/workspace', token: auth.token }[k]),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const loadWorkspaceUnit = async (
|
export const loadWorkspaceUnit = async (
|
||||||
params: WorkspaceUnitCtorParams,
|
params: WorkspaceUnitCtorParams,
|
||||||
apis: Apis
|
apis: Apis
|
||||||
) => {
|
) => {
|
||||||
const workspaceUnit = new WorkspaceUnit(params);
|
const workspaceUnit = new WorkspaceUnit(params);
|
||||||
const blocksuiteWorkspace = await createBlocksuiteWorkspaceWithAuth(
|
const blocksuiteWorkspace = await apis.createBlockSuiteWorkspaceWithAuth(
|
||||||
workspaceUnit.id
|
workspaceUnit.id
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -54,10 +41,13 @@ export const loadWorkspaceUnit = async (
|
|||||||
return workspaceUnit;
|
return workspaceUnit;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createWorkspaceUnit = async (params: WorkspaceUnitCtorParams) => {
|
export const createWorkspaceUnit = async (
|
||||||
|
params: WorkspaceUnitCtorParams,
|
||||||
|
apis: Apis
|
||||||
|
) => {
|
||||||
const workspaceUnit = new WorkspaceUnit(params);
|
const workspaceUnit = new WorkspaceUnit(params);
|
||||||
|
|
||||||
const blocksuiteWorkspace = await createBlocksuiteWorkspaceWithAuth(
|
const blocksuiteWorkspace = await apis.createBlockSuiteWorkspaceWithAuth(
|
||||||
workspaceUnit.id
|
workspaceUnit.id
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user