mirror of
https://github.com/toeverything/AFFiNE.git
synced 2025-01-09 03:39:30 +03:00
feat: dc provider
This commit is contained in:
parent
e6e4c775a8
commit
2bf6bf7ed8
@ -21,6 +21,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.29.1",
|
||||
"fake-indexeddb": "4.0.1",
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -30,6 +31,7 @@
|
||||
"ky": "^0.33.0",
|
||||
"lib0": "^0.2.58",
|
||||
"swr": "^2.0.0",
|
||||
"yjs": "^13.5.43",
|
||||
"y-protocols": "^1.0.5"
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,48 @@
|
||||
import { DCProvider, MemoryProvider } from './provider.js';
|
||||
import { Doc } from 'yjs';
|
||||
|
||||
import type { BaseProvider } from './provider/index.js';
|
||||
import { MemoryProvider } from './provider/index.js';
|
||||
import { getKVConfigure } from './store.js';
|
||||
|
||||
export class DataCenter {
|
||||
private readonly _providers = new Map<string, DCProvider>();
|
||||
private readonly _providers = new Map<string, typeof BaseProvider>();
|
||||
private readonly _workspaces = new Map<string, Promise<Doc | undefined>>();
|
||||
private readonly _config;
|
||||
|
||||
static async init() {
|
||||
static async init(): Promise<DataCenter> {
|
||||
const dc = new DataCenter();
|
||||
dc.addProvider(MemoryProvider);
|
||||
|
||||
return dc;
|
||||
}
|
||||
|
||||
private constructor() {
|
||||
// TODO
|
||||
this._config = getKVConfigure('sys');
|
||||
}
|
||||
|
||||
addProvider<P extends DCProvider>(provider: P) {
|
||||
addProvider(provider: typeof BaseProvider) {
|
||||
this._providers.set(provider.id, provider);
|
||||
}
|
||||
|
||||
private async _initWorkspace(id: string): Promise<Doc> {
|
||||
const workspace = new Doc();
|
||||
|
||||
const providerId = await this._config.get(`workspace:${id}:provider`);
|
||||
if (this._providers.has(providerId)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const Provider = this._providers.get(providerId)!;
|
||||
const provider = new Provider();
|
||||
provider.init(getKVConfigure(id));
|
||||
}
|
||||
return workspace;
|
||||
}
|
||||
|
||||
async getWorkspace(id: string): Promise<Doc | undefined> {
|
||||
if (!this._workspaces.has(id)) {
|
||||
const workspace = this._initWorkspace(id);
|
||||
this._workspaces.set(id, workspace);
|
||||
}
|
||||
|
||||
return this._workspaces.get(id);
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { IdbInstance } from './store.js';
|
||||
|
||||
export interface DCProvider {
|
||||
id: string;
|
||||
init(config: IdbInstance<any>): void;
|
||||
}
|
||||
|
||||
export class MemoryProvider implements DCProvider {
|
||||
static readonly id = 'memory';
|
||||
private _config: IdbInstance<any> | undefined;
|
||||
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
init(config: IdbInstance<any>) {
|
||||
this._config = config;
|
||||
}
|
||||
}
|
14
packages/data-center/src/datacenter/provider/base.ts
Normal file
14
packages/data-center/src/datacenter/provider/base.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import type { ConfigStore } from '../store.js';
|
||||
|
||||
export class BaseProvider {
|
||||
static id = 'memory';
|
||||
protected _config: ConfigStore | undefined;
|
||||
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
init(config: ConfigStore) {
|
||||
this._config = config;
|
||||
}
|
||||
}
|
2
packages/data-center/src/datacenter/provider/index.ts
Normal file
2
packages/data-center/src/datacenter/provider/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { BaseProvider } from './base.js';
|
||||
export { MemoryProvider } from './memory.js';
|
7
packages/data-center/src/datacenter/provider/memory.ts
Normal file
7
packages/data-center/src/datacenter/provider/memory.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { BaseProvider } from './base.js';
|
||||
|
||||
export class MemoryProvider extends BaseProvider {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
import { createStore, del, get, keys, set } from 'idb-keyval';
|
||||
|
||||
export type IdbInstance<T = any> = {
|
||||
export type ConfigStore<T = any> = {
|
||||
get: (key: string) => Promise<T | undefined>;
|
||||
set: (key: string, value: T) => Promise<void>;
|
||||
keys: () => Promise<string[]>;
|
||||
delete: (key: string) => Promise<void>;
|
||||
};
|
||||
|
||||
const initialIndexedDB = <T = any>(database: string): IdbInstance<T> => {
|
||||
const initialIndexedDB = <T = any>(database: string): ConfigStore<T> => {
|
||||
const store = createStore(`affine:${database}`, 'database');
|
||||
return {
|
||||
get: (key: string) => get<T>(key, store),
|
||||
@ -17,22 +17,31 @@ const initialIndexedDB = <T = any>(database: string): IdbInstance<T> => {
|
||||
};
|
||||
};
|
||||
|
||||
const globalIndexedDB = () => {
|
||||
const scopedIndexedDB = () => {
|
||||
const idb = initialIndexedDB('global');
|
||||
const storeCache = new Map<string, Readonly<ConfigStore>>();
|
||||
|
||||
return <T = any>(scope: string): IdbInstance<T> => ({
|
||||
get: (key: string) => idb.get(`${scope}:${key}`),
|
||||
set: (key: string, value: T) => idb.set(`${scope}:${key}`, value),
|
||||
keys: () =>
|
||||
idb
|
||||
.keys()
|
||||
.then(keys =>
|
||||
keys
|
||||
.filter(k => k.startsWith(`${scope}:`))
|
||||
.map(k => k.replace(`${scope}:`, ''))
|
||||
),
|
||||
delete: (key: string) => del(`${scope}:${key}`),
|
||||
});
|
||||
return <T = any>(scope: string): Readonly<ConfigStore<T>> => {
|
||||
if (!storeCache.has(scope)) {
|
||||
const store = {
|
||||
get: (key: string) => idb.get(`${scope}:${key}`),
|
||||
set: (key: string, value: T) => idb.set(`${scope}:${key}`, value),
|
||||
keys: () =>
|
||||
idb
|
||||
.keys()
|
||||
.then(keys =>
|
||||
keys
|
||||
.filter(k => k.startsWith(`${scope}:`))
|
||||
.map(k => k.replace(`${scope}:`, ''))
|
||||
),
|
||||
delete: (key: string) => del(`${scope}:${key}`),
|
||||
};
|
||||
|
||||
storeCache.set(scope, store);
|
||||
}
|
||||
|
||||
return storeCache.get(scope) as ConfigStore<T>;
|
||||
};
|
||||
};
|
||||
|
||||
export const getKVConfigure = globalIndexedDB();
|
||||
export const getKVConfigure = scopedIndexedDB();
|
||||
|
@ -1,8 +1,12 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { getDataCenter } from './utils.js';
|
||||
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
test('can init data center', async () => {
|
||||
const dataCenter = await getDataCenter();
|
||||
|
||||
expect(dataCenter).toBeTruthy();
|
||||
|
||||
const workspace = await dataCenter.getWorkspace('test');
|
||||
expect(workspace).toBeTruthy();
|
||||
});
|
||||
|
64
pnpm-lock.yaml
generated
64
pnpm-lock.yaml
generated
@ -133,6 +133,7 @@ importers:
|
||||
specifiers:
|
||||
'@playwright/test': ^1.29.1
|
||||
encoding: ^0.1.13
|
||||
fake-indexeddb: 4.0.1
|
||||
firebase: ^9.15.0
|
||||
idb-keyval: ^6.2.0
|
||||
ky: ^0.33.0
|
||||
@ -140,6 +141,7 @@ importers:
|
||||
swr: ^2.0.0
|
||||
typescript: ^4.8.4
|
||||
y-protocols: ^1.0.5
|
||||
yjs: ^13.5.43
|
||||
dependencies:
|
||||
encoding: 0.1.13
|
||||
firebase: 9.15.0_encoding@0.1.13
|
||||
@ -148,8 +150,10 @@ importers:
|
||||
lib0: 0.2.58
|
||||
swr: 2.0.0
|
||||
y-protocols: 1.0.5
|
||||
yjs: 13.5.44
|
||||
devDependencies:
|
||||
'@playwright/test': 1.29.1
|
||||
fake-indexeddb: 4.0.1
|
||||
typescript: 4.9.3
|
||||
|
||||
packages/logger:
|
||||
@ -4278,6 +4282,11 @@ packages:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: true
|
||||
|
||||
/base64-arraybuffer-es6/0.7.0:
|
||||
resolution: {integrity: sha512-ESyU/U1CFZDJUdr+neHRhNozeCv72Y7Vm0m1DCbjX3KBjT6eYocvAJlSk6+8+HkVwXlT1FNxhGW6q3UKAlCvvw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
dev: true
|
||||
|
||||
/base64-js/1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
dev: false
|
||||
@ -4858,6 +4867,12 @@ packages:
|
||||
csstype: 3.1.1
|
||||
dev: false
|
||||
|
||||
/domexception/1.0.1:
|
||||
resolution: {integrity: sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==}
|
||||
dependencies:
|
||||
webidl-conversions: 4.0.2
|
||||
dev: true
|
||||
|
||||
/domino/2.1.6:
|
||||
resolution: {integrity: sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ==}
|
||||
dev: false
|
||||
@ -5617,6 +5632,12 @@ packages:
|
||||
tmp: 0.0.33
|
||||
dev: true
|
||||
|
||||
/fake-indexeddb/4.0.1:
|
||||
resolution: {integrity: sha512-hFRyPmvEZILYgdcLBxVdHLik4Tj3gDTu/g7s9ZDOiU3sTNiGx+vEu1ri/AMsFJUZ/1sdRbAVrEcKndh3sViBcA==}
|
||||
dependencies:
|
||||
realistic-structured-clone: 3.0.0
|
||||
dev: true
|
||||
|
||||
/fast-deep-equal/3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
dev: true
|
||||
@ -8183,6 +8204,14 @@ packages:
|
||||
util-deprecate: 1.0.2
|
||||
dev: false
|
||||
|
||||
/realistic-structured-clone/3.0.0:
|
||||
resolution: {integrity: sha512-rOjh4nuWkAqf9PWu6JVpOWD4ndI+JHfgiZeMmujYcPi+fvILUu7g6l26TC1K5aBIp34nV+jE1cDO75EKOfHC5Q==}
|
||||
dependencies:
|
||||
domexception: 1.0.1
|
||||
typeson: 6.1.0
|
||||
typeson-registry: 1.0.0-alpha.39
|
||||
dev: true
|
||||
|
||||
/redent/3.0.0:
|
||||
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
|
||||
engines: {node: '>=8'}
|
||||
@ -8944,6 +8973,13 @@ packages:
|
||||
punycode: 2.1.1
|
||||
dev: true
|
||||
|
||||
/tr46/2.1.0:
|
||||
resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
punycode: 2.1.1
|
||||
dev: true
|
||||
|
||||
/trim-newlines/3.0.1:
|
||||
resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==}
|
||||
engines: {node: '>=8'}
|
||||
@ -9098,6 +9134,20 @@ packages:
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/typeson-registry/1.0.0-alpha.39:
|
||||
resolution: {integrity: sha512-NeGDEquhw+yfwNhguLPcZ9Oj0fzbADiX4R0WxvoY8nGhy98IbzQy1sezjoEFWOywOboj/DWehI+/aUlRVrJnnw==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dependencies:
|
||||
base64-arraybuffer-es6: 0.7.0
|
||||
typeson: 6.1.0
|
||||
whatwg-url: 8.7.0
|
||||
dev: true
|
||||
|
||||
/typeson/6.1.0:
|
||||
resolution: {integrity: sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA==}
|
||||
engines: {node: '>=0.1.14'}
|
||||
dev: true
|
||||
|
||||
/unbox-primitive/1.0.2:
|
||||
resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==}
|
||||
dependencies:
|
||||
@ -9263,6 +9313,11 @@ packages:
|
||||
resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==}
|
||||
dev: true
|
||||
|
||||
/webidl-conversions/6.1.0:
|
||||
resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==}
|
||||
engines: {node: '>=10.4'}
|
||||
dev: true
|
||||
|
||||
/webpack-sources/1.4.3:
|
||||
resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==}
|
||||
dependencies:
|
||||
@ -9299,6 +9354,15 @@ packages:
|
||||
webidl-conversions: 4.0.2
|
||||
dev: true
|
||||
|
||||
/whatwg-url/8.7.0:
|
||||
resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
tr46: 2.1.0
|
||||
webidl-conversions: 6.1.0
|
||||
dev: true
|
||||
|
||||
/which-boxed-primitive/1.0.2:
|
||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user