feat(infra): standard storage service (#5563)

This commit is contained in:
EYHN
2024-01-30 06:31:15 +00:00
parent 48eb6c50e1
commit b3a8e62984
5 changed files with 102 additions and 0 deletions

View File

@@ -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": {

View File

@@ -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';

View 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);
});
});

View File

@@ -0,0 +1 @@
export * from './memento';

View 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);
}
}