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

@@ -477,7 +477,8 @@ const SAVE_AS_DOC = {
toast: 'New doc created',
handler: (host: EditorHost, content: string) => {
reportResponse('result:add-page');
const newDoc = host.doc.workspace.createDoc();
const doc = host.doc.workspace.createDoc();
const newDoc = doc.getStore();
newDoc.load();
const rootId = newDoc.addBlock('affine:page');
newDoc.addBlock('affine:surface', {}, rootId);
@@ -533,7 +534,7 @@ const CREATE_AS_LINKED_DOC = {
}
// Create a new doc and add the content to it
const newDoc = host.doc.workspace.createDoc();
const newDoc = host.doc.workspace.createDoc().getStore();
newDoc.load();
const rootId = newDoc.addBlock('affine:page');
newDoc.addBlock('affine:surface', {}, rootId);

View File

@@ -219,7 +219,7 @@ export class AISlidesRenderer extends WithDisposable(LitElement) {
id: 'SLIDES_PREVIEW',
});
collection.meta.initialize();
const doc = collection.createDoc();
const doc = collection.createDoc().getStore();
doc.load(() => {
const pageBlockId = doc.addBlock('affine:page', {});

View File

@@ -30,7 +30,7 @@ describe('markdownToMindmap: convert markdown list to a mind map tree', () => {
`;
const collection = new TestWorkspace();
collection.meta.initialize();
const doc = collection.createDoc();
const doc = collection.createDoc().getStore();
const nodes = markdownToMindmap(markdown, doc, provider);
expect(nodes).toEqual({
@@ -68,7 +68,7 @@ describe('markdownToMindmap: convert markdown list to a mind map tree', () => {
`;
const collection = new TestWorkspace();
collection.meta.initialize();
const doc = collection.createDoc();
const doc = collection.createDoc().getStore();
const nodes = markdownToMindmap(markdown, doc, provider);
expect(nodes).toEqual({
@@ -100,7 +100,7 @@ describe('markdownToMindmap: convert markdown list to a mind map tree', () => {
const markdown = '';
const collection = new TestWorkspace();
collection.meta.initialize();
const doc = collection.createDoc();
const doc = collection.createDoc().getStore();
const nodes = markdownToMindmap(markdown, doc, provider);
expect(nodes).toEqual(null);

View File

@@ -103,7 +103,8 @@ export class MiniMindmapPreview extends WithDisposable(LitElement) {
id: 'MINI_MINDMAP_TEMPORARY',
});
collection.meta.initialize();
const doc = collection.createDoc({ id: 'doc:home' }).load();
const doc = collection.createDoc('doc:home').getStore();
doc.load();
const rootId = doc.addBlock('affine:page', {});
const surfaceId = doc.addBlock('affine:surface', {}, rootId);
const surface = doc.getModelById(surfaceId) as SurfaceBlockModel;

View File

@@ -684,7 +684,7 @@ const embedLinkedDocToolbarConfig = {
ctx.hide();
const model = block.model;
const doc = ctx.workspace.getDoc(model.props.pageId);
const doc = ctx.workspace.getDoc(model.props.pageId)?.getStore();
const abortController = new AbortController();
abortController.signal.onabort = () => ctx.show();

View File

@@ -165,8 +165,8 @@ export async function markDownToDoc(
schema,
blobCRUD: collection.blobSync,
docCRUD: {
create: (id: string) => collection.createDoc({ id }),
get: (id: string) => collection.getDoc(id),
create: (id: string) => collection.createDoc(id).getStore({ id }),
get: (id: string) => collection.getDoc(id)?.getStore({ id }) ?? null,
delete: (id: string) => collection.removeDoc(id),
},
middlewares,

View File

@@ -174,11 +174,9 @@ export const useSnapshotPage = (
docCollection.id,
workspacesService.getWorkspaceFlavourProvider(affineWorkspace.meta)
);
let page = historyShellWorkspace.getDoc(pageId);
let page = historyShellWorkspace.getDoc(pageId)?.getStore();
if (!page && snapshot) {
page = historyShellWorkspace.createDoc({
id: pageId,
});
page = historyShellWorkspace.createDoc(pageId).getStore();
page.readonly = true;
const spaceDoc = page.spaceDoc;
page.load(() => {

View File

@@ -65,8 +65,8 @@ async function exportDoc(
schema: getAFFiNEWorkspaceSchema(),
blobCRUD: doc.workspace.blobSync,
docCRUD: {
create: (id: string) => doc.workspace.createDoc({ id }),
get: (id: string) => doc.workspace.getDoc(id),
create: (id: string) => doc.workspace.createDoc(id).getStore({ id }),
get: (id: string) => doc.workspace.getDoc(id)?.getStore({ id }) ?? null,
delete: (id: string) => doc.workspace.removeDoc(id),
},
middlewares: [

View File

@@ -9,7 +9,7 @@ import { useCallback } from 'react';
export function useReferenceLinkHelper(docCollection: Workspace) {
const addReferenceLink = useCallback(
(pageId: string, referenceId: string) => {
const page = docCollection?.getDoc(pageId);
const page = docCollection?.getDoc(pageId)?.getStore();
if (!page) {
return;
}

View File

@@ -5,7 +5,7 @@ export function useDocCollectionHelper(docCollection: Workspace) {
return useMemo(
() => ({
createDoc: (pageId?: string): Store => {
return docCollection.createDoc({ id: pageId });
return docCollection.createDoc(pageId).getStore();
},
}),
[docCollection]

View File

@@ -9,8 +9,8 @@ export function useDocCollectionPage(
docCollection: Workspace,
pageId: string | null
): Store | null {
const [page, setPage] = useState(
pageId ? docCollection.getDoc(pageId) : null
const [page, setPage] = useState<Store | null>(
pageId ? (docCollection.getDoc(pageId)?.getStore() ?? null) : null
);
useEffect(() => {
@@ -18,7 +18,7 @@ export function useDocCollectionPage(
group.add(
docCollection.slots.docCreated.subscribe(id => {
if (pageId === id) {
setPage(docCollection.getDoc(id));
setPage(docCollection.getDoc(id)?.getStore() ?? null);
}
})
);

View File

@@ -33,12 +33,16 @@ beforeEach(async () => {
const frameId = page.addBlock('affine:note', {}, pageBlockId);
page.addBlock('affine:paragraph', {}, frameId);
};
await initPage(docCollection.createDoc({ id: 'page0', extensions }));
const store = docCollection.createDoc('page0').getStore({ extensions });
await initPage(store);
});
describe('useBlockSuitePagePreview', () => {
test('basic', async () => {
const page = docCollection.getDoc('page0') as Store;
const page = docCollection.getDoc('page0')?.getStore();
if (!page) {
throw new Error('Page not found');
}
const id = page.addBlock(
'affine:paragraph',
{

View File

@@ -9,8 +9,8 @@ export function useDocCollectionPage(
docCollection: Workspace,
pageId: string | null
): Store | null {
const [page, setPage] = useState(
pageId ? docCollection.getDoc(pageId) : null
const [page, setPage] = useState<Store | null>(
pageId ? (docCollection.getDoc(pageId)?.getStore() ?? null) : null
);
useEffect(() => {
@@ -18,7 +18,7 @@ export function useDocCollectionPage(
group.add(
docCollection.slots.docCreated.subscribe(id => {
if (pageId === id) {
setPage(docCollection.getDoc(id));
setPage(docCollection.getDoc(id)?.getStore() ?? null);
}
})
);
@@ -46,7 +46,9 @@ export function useDocCollectionPage(
useEffect(() => {
if (page?.id !== pageId) {
setPage(pageId ? docCollection.getDoc(pageId) : null);
setPage(
pageId ? (docCollection.getDoc(pageId)?.getStore() ?? null) : null
);
}
}, [docCollection, page?.id, pageId]);

View File

@@ -87,8 +87,8 @@ async function initDoc(name: DocName) {
schema: getAFFiNEWorkspaceSchema(),
blobCRUD: collection.blobSync,
docCRUD: {
create: (id: string) => collection.createDoc({ id }),
get: (id: string) => collection.getDoc(id),
create: (id: string) => collection.createDoc(id).getStore({ id }),
get: (id: string) => collection.getDoc(id)?.getStore({ id }) ?? null,
delete: (id: string) => collection.removeDoc(id),
},
middlewares: [],

View File

@@ -96,7 +96,7 @@ export const EditorChatPanel = forwardRef(function EditorChatPanel(
},
getDoc: (docId: string) => {
const doc = workspaceService.workspace.docCollection.getDoc(docId);
return doc;
return doc?.getStore() ?? null;
},
getReferenceDocs: (docIds: string[]) => {
const docs$ = docsSearchService.watchRefsFrom(docIds);

View File

@@ -155,7 +155,7 @@ export class DndService extends Service {
getBlocksuiteDndAPI(sourceDocId?: string) {
const collection = this.workspaceService.workspace.docCollection;
sourceDocId ??= collection.docs.keys().next().value;
const doc = sourceDocId ? collection.getDoc(sourceDocId) : null;
const doc = sourceDocId ? collection.getDoc(sourceDocId)?.getStore() : null;
if (!doc) {
return null;

View File

@@ -206,8 +206,8 @@ export class DocsService extends Service {
schema: getAFFiNEWorkspaceSchema(),
blobCRUD: collection.blobSync,
docCRUD: {
create: (id: string) => collection.createDoc({ id }),
get: (id: string) => collection.getDoc(id),
create: (id: string) => collection.createDoc(id).getStore({ id }),
get: (id: string) => collection.getDoc(id)?.getStore({ id }) ?? null,
delete: (id: string) => collection.removeDoc(id),
},
middlewares: [replaceIdMiddleware(collection.idGenerator)],

View File

@@ -21,7 +21,11 @@ export class DocsStore extends Store {
}
getBlockSuiteDoc(id: string) {
return this.workspaceService.workspace.docCollection.getDoc(id);
return (
this.workspaceService.workspace.docCollection
.getDoc(id)
?.getStore({ id }) ?? null
);
}
getBlocksuiteCollection() {
@@ -29,7 +33,8 @@ export class DocsStore extends Store {
}
createBlockSuiteDoc() {
return this.workspaceService.workspace.docCollection.createDoc();
const doc = this.workspaceService.workspace.docCollection.createDoc();
return doc.getStore({ id: doc.id });
}
watchDocIds() {

View File

@@ -192,8 +192,10 @@ function generateMarkdownPreviewBuilder(
schema: getAFFiNEWorkspaceSchema(),
blobCRUD: markdownPreviewDocCollection.blobSync,
docCRUD: {
create: (id: string) => markdownPreviewDocCollection.createDoc({ id }),
get: (id: string) => markdownPreviewDocCollection.getDoc(id),
create: (id: string) =>
markdownPreviewDocCollection.createDoc(id).getStore({ id }),
get: (id: string) =>
markdownPreviewDocCollection.getDoc(id)?.getStore({ id }) ?? null,
delete: (id: string) => markdownPreviewDocCollection.removeDoc(id),
},
middlewares: [docLinkBaseURLMiddleware, titleMiddleware],

View File

@@ -67,7 +67,7 @@ export class IntegrationWriter extends Entity {
} else {
const collection = workspace.docCollection;
const doc = collection.getDoc(docId);
const doc = collection.getDoc(docId)?.getStore();
if (!doc) throw new Error('Doc not found');
doc.workspace.meta.setDocMeta(docId, {

View File

@@ -69,7 +69,7 @@ function useImageBlob(
['workspace', 'image', docId, blockId],
{
fetcher: async ([_, __, pageId, blockId]) => {
const page = docCollection.getDoc(pageId);
const page = docCollection.getDoc(pageId)?.getStore();
const block = page?.getBlock(blockId);
if (!block) {
return null;

View File

@@ -4,12 +4,9 @@ import {
} from '@blocksuite/affine/global/exceptions';
import { NoopLogger } from '@blocksuite/affine/global/utils';
import {
type CreateBlocksOptions,
type Doc,
type GetBlocksOptions,
type IdGenerator,
nanoid,
type Store,
type Workspace,
type WorkspaceMeta,
} from '@blocksuite/affine/store';
@@ -113,9 +110,9 @@ export class WorkspaceImpl implements Workspace {
* If the `init` parameter is passed, a `surface`, `note`, and `paragraph` block
* will be created in the doc simultaneously.
*/
createDoc(options: CreateBlocksOptions = {}) {
const { id: docId = this.idGenerator(), query, readonly } = options;
if (this._hasDoc(docId)) {
createDoc(docId?: string): Doc {
const id = docId ?? this.idGenerator();
if (this._hasDoc(id)) {
throw new BlockSuiteError(
ErrorCode.DocCollectionError,
'doc already exists'
@@ -123,17 +120,13 @@ export class WorkspaceImpl implements Workspace {
}
this.meta.addDocMeta({
id: docId,
id,
title: '',
createDate: Date.now(),
tags: [],
});
this.slots.docCreated.next(docId);
return this.getDoc(docId, {
id: docId,
query,
readonly,
}) as Store;
this.slots.docCreated.next(id);
return this.getDoc(id) as Doc;
}
private _getDoc(docId: string): Doc | null {
@@ -141,12 +134,9 @@ export class WorkspaceImpl implements Workspace {
return space ?? null;
}
getDoc(
docId: string,
options: GetBlocksOptions = { id: docId }
): Store | null {
const collection = this._getDoc(docId);
return collection?.getStore(options) ?? null;
getDoc(docId: string): Doc | null {
const doc = this._getDoc(docId);
return doc;
}
removeDoc(docId: string) {