refactor(editor): doc as store extension (#12170)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
  - Introduced new exports related to workspace management, making additional workspace features available.

- **Refactor**
  - Updated how document and workspace types are imported and exported, consolidating and reorganizing module structure.
  - Shifted dependency management for document instances to use an internal provider mechanism.
  - Streamlined and centralized type imports across various modules.

- **Bug Fixes**
  - Removed an unused schema definition to improve code clarity.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Saul-Mirone
2025-05-07 09:17:01 +00:00
parent 610565e617
commit eb62d0e853
12 changed files with 38 additions and 29 deletions
@@ -1,36 +0,0 @@
import type * as Y from 'yjs';
import type { AwarenessStore } from '../yjs/awareness.js';
import type { YBlock } from './block/types.js';
import type { Store, StoreOptions } from './store/store.js';
import type { Workspace } from './workspace.js';
import type { DocMeta } from './workspace-meta.js';
export type GetStoreOptions = Omit<StoreOptions, 'schema' | 'doc'>;
export type RemoveStoreOptions = Pick<
StoreOptions,
'query' | 'id' | 'readonly'
>;
export interface Doc {
readonly id: string;
get meta(): DocMeta | undefined;
remove(): void;
load(initFn?: () => void): void;
get ready(): boolean;
dispose(): void;
clear(): void;
getStore(options?: GetStoreOptions): Store;
removeStore(options: RemoveStoreOptions): void;
get loaded(): boolean;
get awarenessStore(): AwarenessStore;
get workspace(): Workspace;
get rootDoc(): Y.Doc;
get spaceDoc(): Y.Doc;
get yBlocks(): Y.Map<YBlock>;
}
@@ -1,6 +1,3 @@
export * from './block/index.js';
export * from './doc.js';
export * from './store/index.js';
export * from './store-container.js';
export * from './workspace.js';
export * from './workspace-meta.js';
@@ -1,4 +1,10 @@
import type { Doc, GetStoreOptions, RemoveStoreOptions } from './doc';
import type {
Doc,
ExtensionType,
GetStoreOptions,
RemoveStoreOptions,
} from '../extension';
import { DocIdentifier } from '../extension/workspace';
import { type Query, Store } from './store';
export class StoreContainer {
@@ -27,12 +33,18 @@ export class StoreContainer {
return this._storeMap.get(key) as Store;
}
const storeExtension: ExtensionType = {
setup: di => {
di.addImpl(DocIdentifier, () => this.doc);
},
};
const doc = new Store({
doc: this.doc,
readonly,
query,
provider,
extensions,
extensions: [storeExtension].concat(extensions ?? []),
});
this._storeMap.set(key, doc);
@@ -8,9 +8,11 @@ import * as Y from 'yjs';
import type { ExtensionType } from '../../extension/extension.js';
import {
BlockSchemaIdentifier,
type Doc,
StoreExtensionIdentifier,
StoreSelectionExtension,
} from '../../extension/index.js';
import { DocIdentifier } from '../../extension/workspace/doc.js';
import { Schema } from '../../schema/index.js';
import type { TransformerMiddleware } from '../../transformer/middleware.js';
import { Transformer } from '../../transformer/transformer.js';
@@ -21,7 +23,6 @@ import {
type BlockProps,
type YBlock,
} from '../block/index.js';
import type { Doc } from '../doc.js';
import { DocCRUD } from './crud.js';
import { StoreIdentifier } from './identifier.js';
import { type Query, runQuery } from './query.js';
@@ -561,8 +562,7 @@ export class Store {
* In most cases, you don't need to use the constructor directly.
* The store is created by the {@link Doc} instance.
*/
constructor({ doc, readonly, query, provider, extensions }: StoreOptions) {
this._doc = doc;
constructor({ readonly, query, provider, extensions }: StoreOptions) {
this.slots = {
ready: new Subject(),
rootAdded: new Subject(),
@@ -590,6 +590,7 @@ export class Store {
this._provider.getAll(BlockSchemaIdentifier).forEach(schema => {
this._schema.register([schema]);
});
this._doc = this._provider.get(DocIdentifier);
this._crud = new DocCRUD(this._yBlocks, this._schema);
if (readonly !== undefined) {
this._readonly.value = readonly;
@@ -1,46 +0,0 @@
import type { Subject } from 'rxjs';
export type Tag = {
id: string;
value: string;
color: string;
};
export type DocsPropertiesMeta = {
tags?: {
options: Tag[];
};
};
export interface DocMeta {
id: string;
title: string;
tags: string[];
createDate: number;
updatedDate?: number;
favorite?: boolean;
}
export interface WorkspaceMeta {
get docMetas(): DocMeta[];
addDocMeta(props: DocMeta, index?: number): void;
getDocMeta(id: string): DocMeta | undefined;
setDocMeta(id: string, props: Partial<DocMeta>): void;
removeDocMeta(id: string): void;
get properties(): DocsPropertiesMeta;
setProperties(meta: DocsPropertiesMeta): void;
get avatar(): string | undefined;
setAvatar(avatar: string): void;
get name(): string | undefined;
setName(name: string): void;
get docs(): unknown[] | undefined;
initialize(): void;
commonFieldsUpdated: Subject<void>;
docMetaAdded: Subject<string>;
docMetaRemoved: Subject<string>;
docMetaUpdated: Subject<void>;
}
@@ -1,32 +0,0 @@
import type { BlobEngine } from '@blocksuite/sync';
import type { Subject } from 'rxjs';
import type { Awareness } from 'y-protocols/awareness.js';
import type * as Y from 'yjs';
import type { IdGenerator } from '../utils/id-generator.js';
import type { Doc } from './doc.js';
import type { WorkspaceMeta } from './workspace-meta.js';
export interface Workspace {
readonly id: string;
readonly meta: WorkspaceMeta;
readonly idGenerator: IdGenerator;
readonly blobSync: BlobEngine;
readonly onLoadDoc?: (doc: Y.Doc) => void;
readonly onLoadAwareness?: (awareness: Awareness) => void;
get doc(): Y.Doc;
get docs(): Map<string, Doc>;
slots: {
docListUpdated: Subject<void>;
docCreated: Subject<string>;
docRemoved: Subject<string>;
};
createDoc(docId?: string): Doc;
getDoc(docId: string): Doc | null;
removeDoc(docId: string): void;
dispose(): void;
}