Files
AFFiNE/packages/common/infra/src/modules/workspace/testing/testing-provider.ts
2024-09-13 07:27:08 +00:00

135 lines
3.8 KiB
TypeScript

import { WorkspaceFlavour } from '@affine/env/workspace';
import { DocCollection, nanoid } from '@blocksuite/store';
import { map } from 'rxjs';
import { applyUpdate, encodeStateAsUpdate } from 'yjs';
import { Service } from '../../../framework';
import { LiveData } from '../../../livedata';
import { wrapMemento } from '../../../storage';
import {
type BlobStorage,
type DocStorage,
MemoryDocStorage,
} from '../../../sync';
import { MemoryBlobStorage } from '../../../sync/blob/blob';
import type { GlobalState } from '../../storage';
import type { WorkspaceProfileInfo } from '../entities/profile';
import { getAFFiNEWorkspaceSchema } from '../global-schema';
import type { WorkspaceMetadata } from '../metadata';
import type {
WorkspaceEngineProvider,
WorkspaceFlavourProvider,
} from '../providers/flavour';
export class TestingWorkspaceLocalProvider
extends Service
implements WorkspaceFlavourProvider
{
flavour: WorkspaceFlavour = WorkspaceFlavour.LOCAL;
store = wrapMemento(this.globalStore, 'testing/');
workspaceListStore = wrapMemento(this.store, 'workspaces/');
docStorage = new MemoryDocStorage(wrapMemento(this.store, 'docs/'));
constructor(private readonly globalStore: GlobalState) {
super();
}
async deleteWorkspace(id: string): Promise<void> {
const list = this.workspaceListStore.get<WorkspaceMetadata[]>('list') ?? [];
const newList = list.filter(meta => meta.id !== id);
this.workspaceListStore.set('list', newList);
}
async createWorkspace(
initial: (
docCollection: DocCollection,
blobStorage: BlobStorage,
docStorage: DocStorage
) => Promise<void>
): Promise<WorkspaceMetadata> {
const id = nanoid();
const meta = { id, flavour: WorkspaceFlavour.LOCAL };
const blobStorage = new MemoryBlobStorage(
wrapMemento(this.store, id + '/blobs/')
);
const docCollection = new DocCollection({
id: id,
idGenerator: () => nanoid(),
schema: getAFFiNEWorkspaceSchema(),
blobSources: {
main: blobStorage,
},
});
// apply initial state
await initial(docCollection, blobStorage, this.docStorage);
// save workspace to storage
await this.docStorage.doc.set(id, encodeStateAsUpdate(docCollection.doc));
for (const subdocs of docCollection.doc.getSubdocs()) {
await this.docStorage.doc.set(subdocs.guid, encodeStateAsUpdate(subdocs));
}
const list = this.workspaceListStore.get<WorkspaceMetadata[]>('list') ?? [];
this.workspaceListStore.set('list', [...list, meta]);
return { id, flavour: WorkspaceFlavour.LOCAL };
}
workspaces$ = LiveData.from<WorkspaceMetadata[]>(
this.workspaceListStore
.watch<WorkspaceMetadata[]>('list')
.pipe(map(m => m ?? [])),
[]
);
async getWorkspaceProfile(
id: string
): Promise<WorkspaceProfileInfo | undefined> {
const data = await this.docStorage.doc.get(id);
if (!data) {
return;
}
const bs = new DocCollection({
id,
schema: getAFFiNEWorkspaceSchema(),
});
applyUpdate(bs.doc, data);
return {
name: bs.meta.name,
avatar: bs.meta.avatar,
isOwner: true,
};
}
getWorkspaceBlob(id: string, blob: string): Promise<Blob | null> {
return new MemoryBlobStorage(wrapMemento(this.store, id + '/blobs/')).get(
blob
);
}
getEngineProvider(workspaceId: string): WorkspaceEngineProvider {
return {
getDocStorage: () => {
return this.docStorage;
},
getAwarenessConnections() {
return [];
},
getDocServer() {
return null;
},
getLocalBlobStorage: () => {
return new MemoryBlobStorage(
wrapMemento(this.store, workspaceId + '/blobs/')
);
},
getRemoteBlobStorages() {
return [];
},
};
}
}