feat: seperate createDoc and createStore (#11182)

This commit is contained in:
Saul-Mirone
2025-03-26 11:03:47 +00:00
parent d6093e1d66
commit 0a8d8e0a6b
70 changed files with 337 additions and 312 deletions

View File

@@ -80,16 +80,16 @@ function createTestDoc(docId = defaultDocId) {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({
id: docId,
const doc = collection.createDoc(docId);
doc.load();
const store = doc.getStore({
extensions: [
pageSchemaExtension,
tableSchemaExtension,
flatTableSchemaExtension,
],
});
doc.load();
return doc;
return store;
}
test('init block without props should add default props', () => {

View File

@@ -61,12 +61,12 @@ function createTestDoc(docId = defaultDocId) {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({
id: docId,
const doc = collection.createDoc(docId);
const store = doc.getStore({
extensions,
});
doc.load();
return doc;
return store;
}
function requestIdleCallbackPolyfill(
@@ -97,7 +97,7 @@ describe('basic', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'doc:home' });
const doc = collection.createDoc('doc:home');
doc.load();
const actual = serializCollection(collection.doc);
const actualDoc = actual[spaceMetaId].pages[0] as DocMeta;
@@ -148,23 +148,23 @@ describe('basic', () => {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({
id: 'space:0',
const doc = collection.createDoc('space:0');
const store = doc.getStore({
extensions,
});
const readyCallback = vi.fn();
const rootAddedCallback = vi.fn();
doc.slots.ready.subscribe(readyCallback);
doc.slots.rootAdded.subscribe(rootAddedCallback);
store.slots.ready.subscribe(readyCallback);
store.slots.rootAdded.subscribe(rootAddedCallback);
doc.load(() => {
const rootId = doc.addBlock('affine:page', {
store.load(() => {
const rootId = store.addBlock('affine:page', {
title: new Text(),
});
expect(rootAddedCallback).toBeCalledTimes(1);
doc.addBlock('affine:note', {}, rootId);
store.addBlock('affine:note', {}, rootId);
});
expect(readyCallback).toBeCalledTimes(1);
@@ -175,12 +175,12 @@ describe('basic', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const collection2 = new TestWorkspace(options);
const doc = collection.createDoc({
id: 'space:0',
const doc = collection.createDoc('space:0');
const store = doc.getStore({
extensions,
});
doc.load(() => {
doc.addBlock('affine:page', {
store.addBlock('affine:page', {
title: new Text(),
});
});
@@ -206,9 +206,7 @@ describe('basic', () => {
// apply doc update
const update = encodeStateAsUpdate(doc.spaceDoc);
expect(collection2.docs.size).toBe(1);
const doc2 = collection2.getDoc('space:0', {
extensions,
});
const doc2 = collection2.getDoc('space:0');
if (!doc2) {
throw new Error('doc2 is not found');
}
@@ -382,12 +380,15 @@ describe('addBlock', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc0 = collection.createDoc({ id: 'doc:home' });
const doc1 = collection.createDoc({ id: 'space:doc1' });
const doc0 = collection.createDoc('doc:home');
const doc1 = collection.createDoc('space:doc1');
await Promise.all([doc0.load(), doc1.load()]);
assert.equal(collection.docs.size, 2);
const store0 = doc0.getStore({
extensions,
});
doc0.addBlock('affine:page', {
store0.addBlock('affine:page', {
title: new Text(),
});
collection.removeDoc(doc0.id);
@@ -407,8 +408,7 @@ describe('addBlock', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc0 = collection.createDoc({ id: 'doc:home' });
const doc0 = collection.createDoc('doc:home');
collection.removeDoc(doc0.id);
assert.equal(collection.docs.size, 0);
});
@@ -417,7 +417,7 @@ describe('addBlock', () => {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
collection.createDoc({ id: 'doc:home' });
collection.createDoc('doc:home');
assert.deepEqual(
collection.meta.docMetas.map(({ id, title }) => ({

View File

@@ -31,12 +31,15 @@ test('trigger props updated', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'home', extensions });
const doc = collection.createDoc('home');
doc.load();
const store = doc.getStore({
extensions,
});
doc.addBlock('affine:page');
store.addBlock('affine:page');
const rootModel = doc.root as RootBlockModel;
const rootModel = store.root as RootBlockModel;
expect(rootModel).not.toBeNull();
@@ -91,12 +94,15 @@ test('stash and pop', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'home', extensions });
const doc = collection.createDoc('home');
doc.load();
const store = doc.getStore({
extensions,
});
doc.addBlock('affine:page');
store.addBlock('affine:page');
const rootModel = doc.root as RootBlockModel;
const rootModel = store.root as RootBlockModel;
expect(rootModel).not.toBeNull();
@@ -161,12 +167,15 @@ test('always get latest value in onChange', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'home', extensions });
const doc = collection.createDoc('home');
doc.load();
const store = doc.getStore({
extensions,
});
doc.addBlock('affine:page');
store.addBlock('affine:page');
const rootModel = doc.root as RootBlockModel;
const rootModel = store.root as RootBlockModel;
expect(rootModel).not.toBeNull();
@@ -207,11 +216,15 @@ test('query', () => {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc1 = collection.createDoc({ id: 'home', extensions });
doc1.load();
const doc2 = collection.getDoc('home', { extensions });
const doc3 = collection.getDoc('home', {
const doc = collection.createDoc('home');
doc.load();
const store1 = doc.getStore({
extensions,
});
const store2 = doc.getStore({
extensions,
});
const store3 = doc.getStore({
extensions,
query: {
mode: 'loose',
@@ -223,48 +236,53 @@ test('query', () => {
],
},
});
expect(doc1).toBe(doc2);
expect(doc1).not.toBe(doc3);
expect(store1).toBe(store2);
expect(store1).not.toBe(store3);
const page = doc1.addBlock('affine:page');
const note = doc1.addBlock('affine:note', {}, page);
const paragraph1 = doc1.addBlock('affine:paragraph', {}, note);
const list1 = doc1.addBlock('affine:list' as never, {}, note);
const page = store1.addBlock('affine:page');
const note = store1.addBlock('affine:note', {}, page);
const paragraph1 = store1.addBlock('affine:paragraph', {}, note);
const list1 = store1.addBlock('affine:list' as never, {}, note);
expect(doc2?.getBlock(paragraph1)?.blockViewType).toBe('display');
expect(doc2?.getBlock(list1)?.blockViewType).toBe('display');
expect(doc3?.getBlock(list1)?.blockViewType).toBe('hidden');
expect(store2?.getBlock(paragraph1)?.blockViewType).toBe('display');
expect(store2?.getBlock(list1)?.blockViewType).toBe('display');
expect(store3?.getBlock(list1)?.blockViewType).toBe('hidden');
const list2 = doc1.addBlock('affine:list' as never, {}, note);
const list2 = store1.addBlock('affine:list' as never, {}, note);
expect(doc2?.getBlock(list2)?.blockViewType).toBe('display');
expect(doc3?.getBlock(list2)?.blockViewType).toBe('hidden');
expect(store2?.getBlock(list2)?.blockViewType).toBe('display');
expect(store3?.getBlock(list2)?.blockViewType).toBe('hidden');
});
test('local readonly', () => {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc1 = collection.createDoc({ id: 'home', extensions });
doc1.load();
const doc2 = collection.getDoc('home', { readonly: true, extensions });
const doc3 = collection.getDoc('home', { readonly: false, extensions });
const doc = collection.createDoc('home');
const store1 = doc.getStore({
extensions,
});
const store2 = doc.getStore({
readonly: true,
extensions,
});
const store3 = doc.getStore({ readonly: false, extensions });
expect(doc1.readonly).toBeFalsy();
expect(doc2?.readonly).toBeTruthy();
expect(doc3?.readonly).toBeFalsy();
expect(store1.readonly).toBeFalsy();
expect(store2.readonly).toBeTruthy();
expect(store3.readonly).toBeFalsy();
doc1.readonly = true;
store1.readonly = true;
expect(doc1.readonly).toBeTruthy();
expect(doc2?.readonly).toBeTruthy();
expect(doc3?.readonly).toBeFalsy();
expect(store1.readonly).toBeTruthy();
expect(store2.readonly).toBeTruthy();
expect(store3.readonly).toBeFalsy();
doc1.readonly = false;
store1.readonly = false;
expect(doc1.readonly).toBeFalsy();
expect(doc2?.readonly).toBeTruthy();
expect(doc3?.readonly).toBeFalsy();
expect(store1.readonly).toBeFalsy();
expect(store2.readonly).toBeTruthy();
expect(store3.readonly).toBeFalsy();
});
describe('move blocks', () => {
@@ -274,21 +292,22 @@ describe('move blocks', () => {
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'home', extensions });
const doc = collection.createDoc('home');
doc.load();
const pageId = doc.addBlock('affine:page');
const page = doc.getBlock(pageId)!.model;
const store = doc.getStore({ extensions });
const pageId = store.addBlock('affine:page');
const page = store.getBlock(pageId)!.model;
const noteIds = doc.addBlocks(
const noteIds = store.addBlocks(
[1, 2, 3].map(i => ({
flavour: 'affine:note',
blockProps: { id: `${i}` },
})),
page
);
const notes = noteIds.map(id => doc.getBlock(id)!.model);
const notes = noteIds.map(id => store.getBlock(id)!.model);
context.doc = doc;
context.doc = store;
context.page = page;
context.notes = notes;
});

View File

@@ -99,9 +99,10 @@ function createTestDoc(docId = defaultDocId) {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: docId, extensions });
const doc = collection.createDoc(docId);
doc.load();
return doc;
const store = doc.getStore({ extensions });
return store;
}
describe('schema', () => {

View File

@@ -59,10 +59,11 @@ test('model to snapshot', () => {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'home', extensions });
const doc = collection.createDoc('home');
const store = doc.getStore({ extensions });
doc.load();
doc.addBlock('page');
const rootModel = doc.root as RootBlockModel;
store.addBlock('page');
const rootModel = store.root as RootBlockModel;
expect(rootModel).not.toBeNull();
const snapshot = transformer.toSnapshot({
@@ -76,10 +77,11 @@ test('snapshot to model', async () => {
const options = createTestOptions();
const collection = new TestWorkspace(options);
collection.meta.initialize();
const doc = collection.createDoc({ id: 'home', extensions });
const doc = collection.createDoc('home');
const store = doc.getStore({ extensions });
doc.load();
doc.addBlock('page');
const rootModel = doc.root as RootBlockModel;
store.addBlock('page');
const rootModel = store.root as RootBlockModel;
const tempDoc = new Y.Doc();
const map = tempDoc.getMap('temp');