Skip to content

@blocksuite/store

This package is the data layer for modeling collaborative document states. It's natively built on the CRDT library Yjs, powering all BlockSuite documents with built-in real-time collaboration and time-travel capabilities.

Doc

In BlockSuite, a Doc is the container for a block tree, providing essential functionalities for creating, retrieving, updating, and deleting blocks inside it. Under the hood, every doc holds a Yjs subdocument.

Besides the block tree, the selection state is also stored in the doc.awarenessStore inside the doc. This store is also built on top of the Yjs awareness.

DocCollection

In BlockSuite, a DocCollection is defined as an opt-in collection of multiple docs, providing comprehensive features for managing cross-doc updates and data synchronization. You can access the collection via the doc.collection getter, or you can also create a collection manually:

ts
import { DocCollection, Schema } from '@blocksuite/store';

const schema = new Schema();

// You can register a batch of block schemas to the collection
schema.register(AffineSchemas);

const collection = new DocCollection({ schema });
collection.meta.initialize();

Then multiple docs can be created under the collection:

ts
const collection = new DocCollection({ schema });
collection.meta.initialize();

// This is an empty doc at this moment
const doc = collection.createDoc();

As an example, the createEmptyDoc is a simple helper implemented exactly in this way (source):

ts
import { AffineSchemas } from '@blocksuite/blocks/models';
import { Schema, DocCollection } from '@blocksuite/store';

export function createEmptyDoc() {
  const schema = new Schema().register(AffineSchemas);
  const collection = new DocCollection({ schema });
  collection.meta.initialize();
  const doc = collection.createDoc();

  return {
    doc,
    async init() {
      await doc.load(() => {
        const rootBlockId = doc.addBlock('affine:page', {});
        doc.addBlock('affine:surface', {}, rootBlockId);
        const noteId = doc.addBlock('affine:note', {}, rootBlockId);
        doc.addBlock('affine:paragraph', {}, noteId);
      });
      return doc;
    },
  };
}