feat: move data center to root

This commit is contained in:
DarkSky
2023-01-02 23:23:29 +08:00
committed by DarkSky
parent 2913da11a0
commit b105eaf9a6
21 changed files with 109 additions and 86 deletions

View File

@@ -1,4 +1,4 @@
import { signInWithGoogle } from '@affine/datacenter'; import { getDataCenter } from '@affine/datacenter';
import { styled } from '@/styles'; import { styled } from '@/styles';
import { Button } from '@/ui/button'; import { Button } from '@/ui/button';
import { useModal } from '@/providers/global-modal-provider'; import { useModal } from '@/providers/global-modal-provider';
@@ -9,7 +9,8 @@ export const GoogleLoginButton = () => {
return ( return (
<StyledGoogleButton <StyledGoogleButton
onClick={() => { onClick={() => {
signInWithGoogle() getDataCenter()
.then(dc => dc.apis.signInWithGoogle())
.then(() => { .then(() => {
triggerLoginModal(); triggerLoginModal();
}) })

View File

@@ -1,19 +1,18 @@
import { createContext, MutableRefObject, useContext } from 'react'; import { createContext, MutableRefObject, useContext } from 'react';
import type { Workspace } from '@affine/datacenter'; import type { Workspace } from '@affine/datacenter';
import { AccessTokenMessage } from '@affine/datacenter';
import type { import type {
Page as StorePage, Page as StorePage,
Workspace as StoreWorkspace, Workspace as StoreWorkspace,
} from '@blocksuite/store'; } from '@blocksuite/store';
import type { EditorContainer } from '@blocksuite/editor'; import type { EditorContainer } from '@blocksuite/editor';
export type LoadWorkspaceHandler = ( export type LoadWorkspaceHandler = (
workspaceId: string, workspaceId: string
user?: AccessTokenMessage | null // user?: AccessTokenMessage | null
) => Promise<StoreWorkspace | null> | null; ) => Promise<StoreWorkspace | null> | null;
export type CreateEditorHandler = (page: StorePage) => EditorContainer | null; export type CreateEditorHandler = (page: StorePage) => EditorContainer | null;
export interface AppStateValue { export interface AppStateValue {
user: AccessTokenMessage | null; // user: AccessTokenMessage | null;
workspacesMeta: Workspace[]; workspacesMeta: Workspace[];
currentWorkspaceId: string; currentWorkspaceId: string;
@@ -39,7 +38,7 @@ export interface AppStateContext extends AppStateValue {
} }
export const AppState = createContext<AppStateContext>({ export const AppState = createContext<AppStateContext>({
user: null, // user: null,
workspacesMeta: [], workspacesMeta: [],
currentWorkspaceId: '', currentWorkspaceId: '',

View File

@@ -0,0 +1,17 @@
export { token } from './token.js';
export type { Callback } from './token.js';
import { getAuthorizer } from './token.js';
import * as user from './user.js';
import * as workspace from './workspace.js';
export type Apis = typeof user &
typeof workspace & {
signInWithGoogle: ReturnType<typeof getAuthorizer>[0];
onAuthStateChanged: ReturnType<typeof getAuthorizer>[1];
};
export const getApis = (): Apis => {
const [signInWithGoogle, onAuthStateChanged] = getAuthorizer();
return { ...user, ...workspace, signInWithGoogle, onAuthStateChanged };
};

View File

@@ -1,7 +1,11 @@
import { getLogger } from '../../index.js'; import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import type { User } from 'firebase/auth';
import { getLogger } from '../index.js';
import { bareClient } from './request.js'; import { bareClient } from './request.js';
export interface AccessTokenMessage { interface AccessTokenMessage {
create_at: number; create_at: number;
exp: number; exp: number;
email: string; email: string;
@@ -133,3 +137,34 @@ class Token {
} }
export const token = new Token(); export const token = new Token();
export const getAuthorizer = () => {
const app = initializeApp({
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
});
try {
const firebaseAuth = getAuth(app);
const googleAuthProvider = new GoogleAuthProvider();
const signInWithGoogle = async () => {
const user = await signInWithPopup(firebaseAuth, googleAuthProvider);
const idToken = await user.user.getIdToken();
await token.initToken(idToken);
};
const onAuthStateChanged = (callback: (user: User | null) => void) => {
firebaseAuth.onAuthStateChanged(callback);
};
return [signInWithGoogle, onAuthStateChanged] as const;
} catch (e) {
return [] as const;
}
};

View File

@@ -1,5 +1,4 @@
// TODO: temporary reference, move all api into affine provider import { client } from './request.js';
import { client } from '../datacenter/provider/affine/request';
export interface GetUserByEmailParams { export interface GetUserByEmailParams {
email: string; email: string;

View File

@@ -1,6 +1,5 @@
// TODO: temporary reference, move all api into affine provider import { bareClient, client } from './request.js';
import { bareClient, client } from '../datacenter/provider/affine/request'; import type { User } from './user';
import { User } from './user';
export interface GetWorkspaceDetailParams { export interface GetWorkspaceDetailParams {
id: string; id: string;
@@ -165,6 +164,13 @@ export async function getBlob(params: {
export interface LeaveWorkspaceParams { export interface LeaveWorkspaceParams {
id: number | string; id: number | string;
} }
export async function leaveWorkspace({ id }: LeaveWorkspaceParams) { export async function leaveWorkspace({ id }: LeaveWorkspaceParams) {
await client.delete(`api/workspace/${id}/permission`).json(); await client.delete(`api/workspace/${id}/permission`).json();
} }
export async function downloadWorkspace(
workspaceId: string
): Promise<ArrayBuffer> {
return client.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
}

View File

@@ -1,28 +0,0 @@
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
import type { User } from 'firebase/auth';
// TODO: temporary reference, move all api into affine provider
import { token } from './datacenter/provider/affine/token';
const app = initializeApp({
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
});
export const firebaseAuth = getAuth(app);
const googleAuthProvider = new GoogleAuthProvider();
export const signInWithGoogle = async () => {
const user = await signInWithPopup(firebaseAuth, googleAuthProvider);
const idToken = await user.user.getIdToken();
await token.initToken(idToken);
};
export const onAuthStateChanged = (callback: (user: User | null) => void) => {
firebaseAuth.onAuthStateChanged(callback);
};

View File

@@ -3,6 +3,7 @@ import { BlockSchema } from '@blocksuite/blocks/models';
import { Workspace } from '@blocksuite/store'; import { Workspace } from '@blocksuite/store';
import { getLogger } from './index.js'; import { getLogger } from './index.js';
import { getApis, Apis } from './apis/index.js';
import { AffineProvider, BaseProvider } from './provider/index.js'; import { AffineProvider, BaseProvider } from './provider/index.js';
import { LocalProvider } from './provider/index.js'; import { LocalProvider } from './provider/index.js';
import { getKVConfigure } from './store.js'; import { getKVConfigure } from './store.js';
@@ -13,6 +14,7 @@ type GetWorkspaceParams = {
}; };
export class DataCenter { export class DataCenter {
private readonly _apis: Apis;
private readonly _providers = new Map<string, typeof BaseProvider>(); private readonly _providers = new Map<string, typeof BaseProvider>();
private readonly _workspaces = new Map<string, Promise<BaseProvider>>(); private readonly _workspaces = new Map<string, Promise<BaseProvider>>();
private readonly _config; private readonly _config;
@@ -27,11 +29,16 @@ export class DataCenter {
} }
private constructor(debug: boolean) { private constructor(debug: boolean) {
this._apis = getApis();
this._config = getKVConfigure('sys'); this._config = getKVConfigure('sys');
this._logger = getLogger('dc'); this._logger = getLogger('dc');
this._logger.enabled = debug; this._logger.enabled = debug;
} }
get apis(): Readonly<Apis> {
return this._apis;
}
private addProvider(provider: typeof BaseProvider) { private addProvider(provider: typeof BaseProvider) {
this._providers.set(provider.id, provider); this._providers.set(provider.id, provider);
} }
@@ -61,6 +68,7 @@ export class DataCenter {
const provider = new Provider(); const provider = new Provider();
await provider.init({ await provider.init({
apis: this._apis,
config: getKVConfigure(id), config: getKVConfigure(id),
debug: this._logger.enabled, debug: this._logger.enabled,
logger: this._logger.extend(`${Provider.id}:${id}`), logger: this._logger.extend(`${Provider.id}:${id}`),

View File

@@ -1,22 +0,0 @@
import debug from 'debug';
import { DataCenter } from './datacenter.js';
const _initializeDataCenter = () => {
let _dataCenterInstance: Promise<DataCenter>;
return (debug = true) => {
if (!_dataCenterInstance) {
_dataCenterInstance = DataCenter.init(debug);
}
return _dataCenterInstance;
};
};
export const getDataCenter = _initializeDataCenter();
export function getLogger(namespace: string) {
const logger = debug(namespace);
logger.log = console.log.bind(console);
return logger;
}

View File

@@ -1,7 +0,0 @@
import { client } from './request.js';
export async function downloadWorkspace(
workspaceId: string
): Promise<ArrayBuffer> {
return client.get(`api/workspace/${workspaceId}/doc`).arrayBuffer();
}

View File

@@ -1,8 +1,22 @@
export { signInWithGoogle, onAuthStateChanged } from './auth'; import debug from 'debug';
export * from './sdks'; import { DataCenter } from './datacenter.js';
export { getDataCenter } from './datacenter'; const _initializeDataCenter = () => {
let _dataCenterInstance: Promise<DataCenter>;
// TODO: temporary reference, move all api into affine provider return (debug = true) => {
export { token } from './datacenter/provider/affine/token'; if (!_dataCenterInstance) {
export type { AccessTokenMessage } from './datacenter/provider/affine/token'; _dataCenterInstance = DataCenter.init(debug);
}
return _dataCenterInstance;
};
};
export const getDataCenter = _initializeDataCenter();
export function getLogger(namespace: string) {
const logger = debug(namespace);
logger.log = console.log.bind(console);
return logger;
}

View File

@@ -2,11 +2,10 @@ import assert from 'assert';
import { applyUpdate } from 'yjs'; import { applyUpdate } from 'yjs';
import type { InitialParams } from '../index.js'; import type { InitialParams } from '../index.js';
import { token, Callback } from '../../apis/index.js';
import { LocalProvider } from '../local/index.js'; import { LocalProvider } from '../local/index.js';
import { downloadWorkspace } from './apis.js';
import { WebsocketProvider } from './sync.js'; import { WebsocketProvider } from './sync.js';
import { token, Callback } from './token.js';
export class AffineProvider extends LocalProvider { export class AffineProvider extends LocalProvider {
static id = 'affine'; static id = 'affine';
@@ -67,7 +66,7 @@ export class AffineProvider extends LocalProvider {
if (workspace.room && token.isLogin) { if (workspace.room && token.isLogin) {
try { try {
const updates = await downloadWorkspace(workspace.room); const updates = await this._apis.downloadWorkspace(workspace.room);
if (updates) { if (updates) {
await new Promise(resolve => { await new Promise(resolve => {
doc.once('update', resolve); doc.once('update', resolve);

View File

@@ -1,11 +1,12 @@
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
import type { Workspace } from '@blocksuite/store'; import type { Workspace } from '@blocksuite/store';
import type { Logger, InitialParams, ConfigStore } from './index'; import type { Apis, Logger, InitialParams, ConfigStore } from './index';
export class BaseProvider { export class BaseProvider {
static id = 'base'; static id = 'base';
protected _config!: ConfigStore; protected _apis!: Readonly<Apis>;
protected _config!: Readonly<ConfigStore>;
protected _logger!: Logger; protected _logger!: Logger;
protected _workspace!: Workspace; protected _workspace!: Workspace;
@@ -14,6 +15,7 @@ export class BaseProvider {
} }
async init(params: InitialParams) { async init(params: InitialParams) {
this._apis = params.apis;
this._config = params.config; this._config = params.config;
this._logger = params.logger; this._logger = params.logger;
this._workspace = params.workspace; this._workspace = params.workspace;

View File

@@ -1,18 +1,20 @@
import type { Workspace } from '@blocksuite/store'; import type { Workspace } from '@blocksuite/store';
import type { Apis } from '../apis';
import type { getLogger } from '../index'; import type { getLogger } from '../index';
import type { ConfigStore } from '../store'; import type { ConfigStore } from '../store';
export type Logger = ReturnType<typeof getLogger>; export type Logger = ReturnType<typeof getLogger>;
export type InitialParams = { export type InitialParams = {
apis: Apis;
config: ConfigStore; config: ConfigStore;
debug: boolean; debug: boolean;
logger: Logger; logger: Logger;
workspace: Workspace; workspace: Workspace;
}; };
export type { ConfigStore, Workspace }; export type { Apis, ConfigStore, Workspace };
export type { BaseProvider } from './base.js'; export type { BaseProvider } from './base.js';
export { AffineProvider } from './affine/index.js'; export { AffineProvider } from './affine/index.js';
export { LocalProvider } from './local/index.js'; export { LocalProvider } from './local/index.js';

View File

@@ -1,2 +0,0 @@
export * from './workspace';
export * from './user';

View File

@@ -1,5 +1,5 @@
export const getDataCenter = () => { export const getDataCenter = () => {
return import('../src/datacenter/index.js').then(async dataCenter => return import('../src/index.js').then(async dataCenter =>
dataCenter.getDataCenter(false) dataCenter.getDataCenter(false)
); );
}; };