mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 06:16:59 +08:00
feat(infra): standard storage service (#5563)
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
"./app-config-storage": "./src/app-config-storage.ts",
|
||||
"./di": "./src/di/index.ts",
|
||||
"./livedata": "./src/livedata/index.ts",
|
||||
"./storage": "./src/storage/index.ts",
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,3 +2,6 @@ export * from './app-config-storage';
|
||||
export * from './atom';
|
||||
export * from './blocksuite';
|
||||
export * from './command';
|
||||
export * from './di';
|
||||
export * from './livedata';
|
||||
export * from './storage';
|
||||
|
||||
40
packages/common/infra/src/storage/__tests__/memento.spec.ts
Normal file
40
packages/common/infra/src/storage/__tests__/memento.spec.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { ServiceCollection } from '../../di';
|
||||
import { GlobalCache, GlobalState, MemoryMemento } from '..';
|
||||
|
||||
describe('memento', () => {
|
||||
test('memory', () => {
|
||||
const memento = new MemoryMemento();
|
||||
|
||||
expect(memento.get('foo')).toBeNull();
|
||||
memento.set('foo', 'bar');
|
||||
expect(memento.get('foo')).toEqual('bar');
|
||||
|
||||
let subscribed = null;
|
||||
const subscription = memento.watch('foo').subscribe(v => {
|
||||
subscribed = v;
|
||||
});
|
||||
expect(subscribed).toEqual('bar');
|
||||
memento.set('foo', 'baz');
|
||||
expect(subscribed).toEqual('baz');
|
||||
|
||||
subscription.unsubscribe();
|
||||
memento.set('foo', 'hello');
|
||||
expect(subscribed).toEqual('baz');
|
||||
});
|
||||
|
||||
test('service', () => {
|
||||
const services = new ServiceCollection();
|
||||
|
||||
services
|
||||
.addImpl(GlobalCache, MemoryMemento)
|
||||
.addImpl(GlobalState, MemoryMemento);
|
||||
|
||||
const provider = services.provider();
|
||||
const cache = provider.get(GlobalCache);
|
||||
expect(cache).toBeInstanceOf(MemoryMemento);
|
||||
const state = provider.get(GlobalState);
|
||||
expect(state).toBeInstanceOf(MemoryMemento);
|
||||
});
|
||||
});
|
||||
1
packages/common/infra/src/storage/index.ts
Normal file
1
packages/common/infra/src/storage/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './memento';
|
||||
57
packages/common/infra/src/storage/memento.ts
Normal file
57
packages/common/infra/src/storage/memento.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Observable } from 'rxjs';
|
||||
|
||||
import { createIdentifier } from '../di';
|
||||
import { LiveData } from '../livedata';
|
||||
|
||||
/**
|
||||
* A memento represents a storage utility. It can store and retrieve values, and observe changes.
|
||||
*/
|
||||
export interface Memento {
|
||||
get<T>(key: string): T | null;
|
||||
watch<T>(key: string): Observable<T | null>;
|
||||
set<T>(key: string, value: T | null): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A memento object that stores the entire application state.
|
||||
*
|
||||
* State is persisted, even the application is closed.
|
||||
*/
|
||||
export interface GlobalState extends Memento {}
|
||||
|
||||
export const GlobalState = createIdentifier<GlobalState>('GlobalState');
|
||||
|
||||
/**
|
||||
* A memento object that stores the entire application cache.
|
||||
*
|
||||
* Cache may be deleted from time to time, business logic should not rely on cache.
|
||||
*/
|
||||
export interface GlobalCache extends Memento {}
|
||||
|
||||
export const GlobalCache = createIdentifier<GlobalCache>('GlobalCache');
|
||||
|
||||
/**
|
||||
* A simple implementation of Memento. Used for testing.
|
||||
*/
|
||||
export class MemoryMemento implements Memento {
|
||||
private readonly data = new Map<string, LiveData<any>>();
|
||||
|
||||
private getLiveData(key: string): LiveData<any> {
|
||||
let data = this.data.get(key);
|
||||
if (!data) {
|
||||
data = new LiveData<any>(null);
|
||||
this.data.set(key, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
get<T>(key: string): T | null {
|
||||
return this.getLiveData(key).value;
|
||||
}
|
||||
watch<T>(key: string): Observable<T | null> {
|
||||
return this.getLiveData(key).asObservable();
|
||||
}
|
||||
set<T>(key: string, value: T | null): void {
|
||||
this.getLiveData(key).next(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user