@blocksuite/store
Advanced tools
Comparing version 0.0.0-canary-20241216011454 to 0.0.0-canary-20241216023618
137
CHANGELOG.md
# @blocksuite/store | ||
## 0.0.0-canary-20241216011454 | ||
## 0.0.0-canary-20241216023618 | ||
@@ -9,135 +9,6 @@ ### Patch Changes | ||
- Updated dependencies | ||
- @blocksuite/global@0.0.0-canary-20241216011454 | ||
- @blocksuite/inline@0.0.0-canary-20241216011454 | ||
- @blocksuite/sync@0.0.0-canary-20241216011454 | ||
- @blocksuite/global@0.0.0-canary-20241216023618 | ||
- @blocksuite/inline@0.0.0-canary-20241216023618 | ||
- @blocksuite/sync@0.0.0-canary-20241216023618 | ||
## 0.19.0 | ||
### Minor Changes | ||
- d7ec057: Blocksuite minor release. | ||
## Feat | ||
- feat: enable new dnd by default (#8970) | ||
- feat: should insert bookmark when drop frame and group (#8969) | ||
- feat(blocks): add block adapters for note block (#8963) | ||
## Fix | ||
- fix: note dnd preview (#8968) | ||
- fix: attachment, bookmark and embed blocks should be draggable (#8967) | ||
- fix: should copy embed doc when dnd (#8966) | ||
- fix(std): undefined editor during rect polling on mobile (#8965) | ||
- fix(blocks): fix incorrect font family in mobile widgets (#8961) | ||
- fix(blocks): at menu styles (#8962) | ||
## Refactor | ||
- refactor: optimize code of new drag event watcher (#8971) | ||
- refactor(playground): remove `mockPeekViewExtension` (#8964) | ||
### Patch Changes | ||
- Updated dependencies [d7ec057] | ||
- @blocksuite/global@0.19.0 | ||
- @blocksuite/inline@0.19.0 | ||
- @blocksuite/sync@0.19.0 | ||
## 0.18.7 | ||
### Patch Changes | ||
- 1057773: Blocksuite patch release. | ||
## Feat | ||
- feat(edgeless): rewrite mind map drag indicator (#8805) | ||
- feat: remove data transfer from dnd api (#8955) | ||
## Fix | ||
- fix: dnd from entity api (#8958) | ||
- fix(std): edge case on pointer controller (#8954) | ||
- fix: indent behavior (#8941) | ||
- fix(edgeless): add index reorder buttong for frame block (#8951) | ||
## Chore | ||
- chore: run headless vitest locally by default (#8957) | ||
- chore(blocks): disable image peekview on mobile (#8952) | ||
## Refactor | ||
- refactor(database): refactor addRow functionality in kanban and table views (#8956) | ||
- refactor: notion html adapter (#8947) | ||
- Updated dependencies [1057773] | ||
- @blocksuite/global@0.18.7 | ||
- @blocksuite/inline@0.18.7 | ||
- @blocksuite/sync@0.18.7 | ||
## 0.18.6 | ||
### Patch Changes | ||
- d925364: Blocksuite patch release. | ||
## Feat | ||
- feat: add from entity api for dnd (#8946) | ||
- feat: make block to snapshot a sync method (#8943) | ||
- feat(database): enhance filter functionality with default values (#8932) | ||
- feat: bring back the ability to drag blocks from note to edgeless (#8914) | ||
- feat(blocks): responsive ui for embed doc (#8900) | ||
- feat(edgeless): unlock and unlock button (#8826) | ||
- feat(edgeless): impl lock interface for edgeless element and block (#8825) | ||
- feat(edgeless): add lock property to edgeless block and element (#8824) | ||
- feat(blocks): support embed linked doc and synced doc html block adapter (#8907) | ||
- feat(blocks): support database html block adapter (#8898) | ||
## Fix | ||
- fix(blocks): inconsistent language list behavior on hover in Firefox (#8944) | ||
- fix(database): adjust detail panel layout for better responsiveness (#8945) | ||
- fix(database): move cursor in kanban card title by arrow keys (#8893) | ||
- fix(blocks): show keyboard toolbar when focus on title and hide on scrolling (#8939) | ||
- fix(blocks): missing aliases when duplicating linked doc block on edgeless (#8930) | ||
- fix: remove vitest extension from recommendation list (#8936) | ||
- fix(blocks): should prevent default if drop event is handled (#8929) | ||
- fix(blocks): missing aliases when converting from embed to card (#8928) | ||
- fix(blocks): should show original doc title when hovering title button (#8925) | ||
- fix(blocks): hide the thumb for bookmark if its width is less than 375 (#8922) | ||
- fix(blocks): button styling when disabled on embed card edit popup (#8924) | ||
- fix(edgeless): undefined telemetry service (#8918) | ||
- fix(database): add group call frequency is incorrect (#8916) | ||
- fix(database): adjust padding for mobile menu to accommodate safe area insets (#8915) | ||
## Chore | ||
- chore(edgeless): telemetry for edgeless lock feature (#8933) | ||
- chore(blocks): use rest params in parsed result (#8908) | ||
- chore: lock file maintenance (#8919) | ||
- chore: lock file maintenance (#8894) | ||
## Refactor | ||
- refactor: adapter types and utils (#8934) | ||
- refactor: make notion text adapter as an extension (#8926) | ||
## Perf | ||
- perf(std): cache dom rect for pointer controller (#8940) | ||
## Test | ||
- test(database): add sorting functionality tests for multiple rules (#8917) | ||
- test(edgeless): fix lock flaky test by adding waitNextFrame (#8937) | ||
- test(edgeless): edgeless element lock feature tests (#8867) | ||
- Updated dependencies [d925364] | ||
- @blocksuite/global@0.18.6 | ||
- @blocksuite/inline@0.18.6 | ||
- @blocksuite/sync@0.18.6 | ||
## 0.18.5 | ||
@@ -144,0 +15,0 @@ |
@@ -25,3 +25,3 @@ import { BlockSuiteError } from '@blocksuite/global/exceptions'; | ||
try { | ||
const blockSnapshot = this.job.blockToSnapshot(model); | ||
const blockSnapshot = await this.job.blockToSnapshot(model); | ||
if (!blockSnapshot) | ||
@@ -42,3 +42,3 @@ return; | ||
try { | ||
const docSnapshot = this.job.docToSnapshot(doc); | ||
const docSnapshot = await this.job.docToSnapshot(doc); | ||
if (!docSnapshot) | ||
@@ -59,3 +59,3 @@ return; | ||
try { | ||
const sliceSnapshot = this.job.sliceToSnapshot(slice); | ||
const sliceSnapshot = await this.job.sliceToSnapshot(slice); | ||
if (!sliceSnapshot) | ||
@@ -62,0 +62,0 @@ return; |
@@ -13,2 +13,3 @@ import type { BlockSuiteFlags } from '@blocksuite/global/types'; | ||
import { DocCollectionMeta, type DocMeta } from './meta.js'; | ||
import { ObjectPool, type RcRef } from './object-pool.js'; | ||
export type DocCollectionOptions = { | ||
@@ -41,2 +42,3 @@ schema: Schema; | ||
readonly doc: BlockSuiteDoc; | ||
readonly docPool: ObjectPool<string, Doc>; | ||
readonly docSync: DocEngine; | ||
@@ -80,2 +82,3 @@ readonly id: string; | ||
getDoc(docId: string, options?: GetDocOptions): Doc | null; | ||
getDocRef(docId: string): RcRef<Doc> | null; | ||
removeDoc(docId: string): void; | ||
@@ -82,0 +85,0 @@ /** Update doc meta state. Note that this intentionally does not mutate doc state. */ |
@@ -47,2 +47,3 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { | ||
import { DocCollectionMeta } from './meta.js'; | ||
import { ObjectPool } from './object-pool.js'; | ||
const FLAGS_PRESET = { | ||
@@ -64,3 +65,3 @@ enable_synced_doc_block: false, | ||
enable_shape_shadow_blur: false, | ||
enable_new_dnd: true, | ||
enable_new_dnd: false, | ||
enable_mobile_keyboard_toolbar: false, | ||
@@ -111,2 +112,8 @@ enable_mobile_linked_doc_menu: false, | ||
this.blockCollections = new Map(); | ||
this.docPool = new ObjectPool({ | ||
onDelete: doc => { | ||
doc.dispose(); | ||
}, | ||
onDangling: doc => doc.docSync.canGracefulStop(), | ||
}); | ||
this.slots = { | ||
@@ -131,3 +138,3 @@ docAdded: new Slot(), | ||
this.meta.docMetaAdded.on(docId => { | ||
const doc = new BlockCollection({ | ||
const blockCollection = new BlockCollection({ | ||
id: docId, | ||
@@ -139,4 +146,4 @@ collection: this, | ||
}); | ||
this.blockCollections.set(doc.id, doc); | ||
this.slots.docAdded.emit(doc.id); | ||
this.blockCollections.set(blockCollection.id, blockCollection); | ||
this.slots.docAdded.emit(blockCollection.id); | ||
}); | ||
@@ -202,2 +209,13 @@ this.meta.docMetaUpdated.on(() => this.slots.docUpdated.emit()); | ||
} | ||
getDocRef(docId) { | ||
const ref = this.docPool.get(docId); | ||
if (ref) | ||
return ref; | ||
const doc = this.getBlockCollection(docId)?.getDoc(); | ||
if (doc) { | ||
const newRef = this.docPool.put(docId, doc); | ||
return newRef; | ||
} | ||
return null; | ||
} | ||
removeDoc(docId) { | ||
@@ -204,0 +222,0 @@ const docMeta = this.meta.getDocMeta(docId); |
@@ -99,3 +99,2 @@ import { Slot } from '@blocksuite/global/utils'; | ||
clearQuery(query: Query, readonly?: boolean): void; | ||
destroy(): void; | ||
dispose(): void; | ||
@@ -102,0 +101,0 @@ generateBlockId(): string; |
@@ -201,7 +201,2 @@ import { Slot } from '@blocksuite/global/utils'; | ||
} | ||
destroy() { | ||
this._ySpaceDoc.destroy(); | ||
this._onLoadSlot.dispose(); | ||
this._loaded = false; | ||
} | ||
dispose() { | ||
@@ -212,3 +207,3 @@ this.slots.historyUpdated.dispose(); | ||
this._yBlocks.unobserveDeep(this._handleYEvents); | ||
this._yBlocks.clear(); | ||
this._ySpaceDoc.destroy(); | ||
} | ||
@@ -227,3 +222,2 @@ } | ||
blockCollection: this, | ||
crud: this._docCRUD, | ||
schema: this.collection.schema, | ||
@@ -264,3 +258,6 @@ readonly, | ||
remove() { | ||
this.destroy(); | ||
this.clear(); | ||
this._ySpaceDoc.destroy(); | ||
this._onLoadSlot.dispose(); | ||
this._loaded = false; | ||
this.rootDoc.spaces.delete(this.id); | ||
@@ -267,0 +264,0 @@ } |
@@ -60,13 +60,2 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
} | ||
const props = { | ||
...initialProps, | ||
}; | ||
delete props.id; | ||
delete props.flavour; | ||
delete props.children; | ||
Object.entries(props).forEach(([key, value]) => { | ||
if (value === undefined) | ||
return; | ||
yBlock.set(`prop:${key}`, native2Y(value)); | ||
}); | ||
} | ||
@@ -73,0 +62,0 @@ } |
import { type Disposable, Slot } from '@blocksuite/global/utils'; | ||
import type { BlockModel, Schema } from '../../schema/index.js'; | ||
import type { DraftModel } from '../../transformer/index.js'; | ||
import type { BlockCollection, BlockProps } from './block-collection.js'; | ||
import type { DocCRUD } from './crud.js'; | ||
import { Block } from './block/index.js'; | ||
import { BlockCollection, type BlockProps } from './block-collection.js'; | ||
import { type Query } from './query.js'; | ||
@@ -11,3 +11,2 @@ type DocOptions = { | ||
blockCollection: BlockCollection; | ||
crud: DocCRUD; | ||
readonly?: boolean; | ||
@@ -18,6 +17,6 @@ query?: Query; | ||
private _runQuery; | ||
protected readonly _blockCollection: BlockCollection; | ||
protected _blockCollection: BlockCollection; | ||
protected readonly _blocks: import("@preact/signals-core").Signal<Record<string, Block>>; | ||
protected readonly _crud: DocCRUD; | ||
protected readonly _disposeBlockUpdated: Disposable; | ||
protected _crud: DocCRUD; | ||
protected _disposeBlockUpdated: Disposable; | ||
protected readonly _query: Query; | ||
@@ -92,4 +91,5 @@ protected readonly _readonly?: boolean; | ||
get withoutTransact(): (callback: () => void) => void; | ||
constructor({ schema, blockCollection, crud, readonly, query }: DocOptions); | ||
constructor({ schema, blockCollection, readonly, query }: DocOptions); | ||
private _getSiblings; | ||
private _initializeBlockCollection; | ||
private _onBlockAdded; | ||
@@ -96,0 +96,0 @@ private _onBlockRemoved; |
@@ -6,2 +6,3 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
import { Block } from './block/index.js'; | ||
import { BlockCollection } from './block-collection.js'; | ||
import { runQuery } from './query.js'; | ||
@@ -108,3 +109,3 @@ export class Doc { | ||
} | ||
constructor({ schema, blockCollection, crud, readonly, query }) { | ||
constructor({ schema, blockCollection, readonly, query }) { | ||
this._runQuery = (block) => { | ||
@@ -153,3 +154,2 @@ runQuery(this._query, block); | ||
}; | ||
this._blockCollection = blockCollection; | ||
this.slots = { | ||
@@ -160,6 +160,5 @@ ready: new Slot(), | ||
blockUpdated: new Slot(), | ||
historyUpdated: this._blockCollection.slots.historyUpdated, | ||
yBlockUpdated: this._blockCollection.slots.yBlockUpdated, | ||
historyUpdated: blockCollection.slots.historyUpdated, | ||
yBlockUpdated: blockCollection.slots.yBlockUpdated, | ||
}; | ||
this._crud = crud; | ||
this._schema = schema; | ||
@@ -170,8 +169,25 @@ this._readonly = readonly; | ||
} | ||
this._initializeBlockCollection(blockCollection); | ||
} | ||
_getSiblings(block, fn) { | ||
const parent = this.getParent(block); | ||
if (!parent) | ||
return null; | ||
const blockModel = typeof block === 'string' ? this.getBlock(block)?.model : block; | ||
if (!blockModel) | ||
return null; | ||
const index = parent.children.indexOf(blockModel); | ||
if (index === -1) | ||
return null; | ||
return fn(parent, index); | ||
} | ||
_initializeBlockCollection(blockCollection) { | ||
this._blockCollection = blockCollection; | ||
this._crud = blockCollection.crud; | ||
this._yBlocks.forEach((_, id) => { | ||
if (id in this._blocks.peek()) { | ||
if (id in this._blocks.peek()) | ||
return; | ||
} | ||
this._onBlockAdded(id, true); | ||
}); | ||
this._disposeBlockUpdated?.dispose(); | ||
this._disposeBlockUpdated = this._blockCollection.slots.yBlockUpdated.on(({ type, id }) => { | ||
@@ -190,14 +206,2 @@ switch (type) { | ||
} | ||
_getSiblings(block, fn) { | ||
const parent = this.getParent(block); | ||
if (!parent) | ||
return null; | ||
const blockModel = typeof block === 'string' ? this.getBlock(block)?.model : block; | ||
if (!blockModel) | ||
return null; | ||
const index = parent.children.indexOf(blockModel); | ||
if (index === -1) | ||
return null; | ||
return fn(parent, index); | ||
} | ||
_onBlockAdded(id, init = false) { | ||
@@ -335,7 +339,8 @@ try { | ||
dispose() { | ||
this._blockCollection.dispose(); | ||
this._disposeBlockUpdated.dispose(); | ||
this.slots.ready.dispose(); | ||
this.slots.blockUpdated.dispose(); | ||
this.slots.rootAdded.dispose(); | ||
this.slots.rootDeleted.dispose(); | ||
// this.slots.ready.dispose(); | ||
// this.slots.blockUpdated.dispose(); | ||
// this.slots.rootAdded.dispose(); | ||
// this.slots.rootDeleted.dispose(); | ||
} | ||
@@ -405,2 +410,17 @@ getBlock(id) { | ||
load(initFn) { | ||
// recreate space doc | ||
if (this._blockCollection.spaceDoc.isDestroyed) { | ||
// This section intentionally recreates the BlockCollection by design (circular dependency). | ||
// It ensures the underlying Y.Doc is reinitialized after being garbage collected. | ||
const newBlockCollection = new BlockCollection({ | ||
id: this._blockCollection.id, | ||
collection: this._blockCollection.collection, | ||
doc: this._blockCollection.rootDoc, | ||
awarenessStore: this._blockCollection.awarenessStore, | ||
}); | ||
this._initializeBlockCollection(newBlockCollection); | ||
newBlockCollection.load(initFn); | ||
this.slots.ready.emit(); | ||
return this; | ||
} | ||
this._blockCollection.load(initFn); | ||
@@ -407,0 +427,0 @@ this.slots.ready.emit(); |
@@ -7,2 +7,3 @@ export type * from './collection.js'; | ||
export type * from './meta.js'; | ||
export * from './object-pool.js'; | ||
//# sourceMappingURL=index.d.ts.map |
export { DocCollection } from './collection.js'; | ||
export * from './doc/index.js'; | ||
export * from './id.js'; | ||
export * from './object-pool.js'; | ||
//# sourceMappingURL=index.js.map |
@@ -63,2 +63,3 @@ import type * as Y from 'yjs'; | ||
setProperties(meta: DocsPropertiesMeta): void; | ||
updateVersion(collection: DocCollection): void; | ||
/** | ||
@@ -65,0 +66,0 @@ * @deprecated Only used for legacy doc version validation |
@@ -163,2 +163,11 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
} | ||
updateVersion(collection) { | ||
this._proxy.workspaceVersion = COLLECTION_VERSION; | ||
this._proxy.pageVersion = PAGE_VERSION; | ||
const _versions = {}; | ||
collection.schema.flavourSchemaMap.forEach((schema, flavour) => { | ||
_versions[flavour] = schema.version; | ||
}); | ||
this._proxy.blockVersions = _versions; | ||
} | ||
/** | ||
@@ -165,0 +174,0 @@ * @deprecated Only used for legacy doc version validation |
@@ -28,5 +28,5 @@ import type { BlockModel, InternalPrimitives } from '../schema/index.js'; | ||
fromSnapshot({ json, }: FromSnapshotPayload): Promise<SnapshotNode<Props>> | SnapshotNode<Props>; | ||
toSnapshot({ model }: ToSnapshotPayload<Props>): BlockSnapshotLeaf; | ||
toSnapshot({ model, }: ToSnapshotPayload<Props>): Promise<BlockSnapshotLeaf> | BlockSnapshotLeaf; | ||
} | ||
export {}; | ||
//# sourceMappingURL=base.d.ts.map |
@@ -28,3 +28,3 @@ import { internalPrimitives } from '../schema/index.js'; | ||
} | ||
toSnapshot({ model }) { | ||
toSnapshot({ model, }) { | ||
const { id, flavour, version } = model; | ||
@@ -31,0 +31,0 @@ const props = this._propsToSnapshot(model); |
@@ -17,6 +17,6 @@ import type { BlockModel } from '../schema/index.js'; | ||
private readonly _slots; | ||
blockToSnapshot: (model: DraftModel) => BlockSnapshot | undefined; | ||
blockToSnapshot: (model: DraftModel) => Promise<BlockSnapshot | undefined>; | ||
collectionInfoToSnapshot: () => CollectionInfoSnapshot | undefined; | ||
docToSnapshot: (doc: Doc) => DocSnapshot | undefined; | ||
sliceToSnapshot: (slice: Slice) => SliceSnapshot | undefined; | ||
docToSnapshot: (doc: Doc) => Promise<DocSnapshot | undefined>; | ||
sliceToSnapshot: (slice: Slice) => Promise<SliceSnapshot | undefined>; | ||
snapshotToBlock: (snapshot: BlockSnapshot, doc: Doc, parent?: string, index?: number) => Promise<BlockModel | undefined>; | ||
@@ -23,0 +23,0 @@ snapshotToDoc: (snapshot: DocSnapshot) => Promise<Doc | undefined>; |
@@ -30,5 +30,5 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
}; | ||
this.blockToSnapshot = (model) => { | ||
this.blockToSnapshot = async (model) => { | ||
try { | ||
const snapshot = this._blockToSnapshot(model); | ||
const snapshot = await this._blockToSnapshot(model); | ||
BlockSnapshotSchema.parse(snapshot); | ||
@@ -67,3 +67,3 @@ return snapshot; | ||
}; | ||
this.docToSnapshot = (doc) => { | ||
this.docToSnapshot = async (doc) => { | ||
try { | ||
@@ -79,3 +79,3 @@ this._slots.beforeExport.emit({ | ||
} | ||
const blocks = this.blockToSnapshot(rootModel); | ||
const blocks = await this.blockToSnapshot(rootModel); | ||
if (!blocks) { | ||
@@ -103,3 +103,3 @@ return; | ||
}; | ||
this.sliceToSnapshot = (slice) => { | ||
this.sliceToSnapshot = async (slice) => { | ||
try { | ||
@@ -110,6 +110,6 @@ this._slots.beforeExport.emit({ | ||
}); | ||
const { content, pageId, workspaceId } = slice.data; | ||
const { content, pageVersion, workspaceVersion, pageId, workspaceId } = slice.data; | ||
const contentSnapshot = []; | ||
for (const block of content) { | ||
const blockSnapshot = this.blockToSnapshot(block); | ||
const blockSnapshot = await this.blockToSnapshot(block); | ||
if (!blockSnapshot) { | ||
@@ -124,2 +124,4 @@ return; | ||
pageId, | ||
pageVersion, | ||
workspaceVersion, | ||
content: contentSnapshot, | ||
@@ -209,3 +211,3 @@ }; | ||
}); | ||
const { content, workspaceId, pageId } = snapshot; | ||
const { content, pageVersion, workspaceVersion, workspaceId, pageId } = snapshot; | ||
// Create a temporary root snapshot to encompass all content blocks | ||
@@ -231,2 +233,4 @@ const tmpRootSnapshot = { | ||
content: contentBlocks, | ||
pageVersion, | ||
workspaceVersion, | ||
workspaceId, | ||
@@ -274,3 +278,3 @@ pageId, | ||
} | ||
_blockToSnapshot(model) { | ||
async _blockToSnapshot(model) { | ||
this._slots.beforeExport.emit({ | ||
@@ -282,9 +286,9 @@ type: 'block', | ||
const transformer = this._getTransformer(schema); | ||
const snapshotLeaf = transformer.toSnapshot({ | ||
const snapshotLeaf = await transformer.toSnapshot({ | ||
model, | ||
assets: this._assetsManager, | ||
}); | ||
const children = model.children.map(child => { | ||
const children = await Promise.all(model.children.map(child => { | ||
return this._blockToSnapshot(child); | ||
}); | ||
})); | ||
const snapshot = { | ||
@@ -373,3 +377,9 @@ type: 'block', | ||
const { meta } = this._collection; | ||
const { docs } = meta; | ||
const { pageVersion, workspaceVersion, docs } = meta; | ||
if (!pageVersion) { | ||
throw new BlockSuiteError(ErrorCode.TransformerError, 'Page version not found'); | ||
} | ||
if (!workspaceVersion) { | ||
throw new BlockSuiteError(ErrorCode.TransformerError, 'Workspace version not found'); | ||
} | ||
if (!docs) { | ||
@@ -379,2 +389,4 @@ throw new BlockSuiteError(ErrorCode.TransformerError, 'Docs not found'); | ||
return { | ||
pageVersion, | ||
workspaceVersion, | ||
properties: {}, // for backward compatibility | ||
@@ -381,0 +393,0 @@ pages: JSON.parse(JSON.stringify(docs)), |
@@ -7,2 +7,4 @@ import type { Doc } from '../store/index.js'; | ||
pageId: string; | ||
pageVersion: number; | ||
workspaceVersion: number; | ||
}; | ||
@@ -13,3 +15,5 @@ export declare class Slice { | ||
get docId(): string; | ||
get pageVersion(): number; | ||
get workspaceId(): string; | ||
get workspaceVersion(): number; | ||
constructor(data: SliceData); | ||
@@ -16,0 +20,0 @@ static fromModels(doc: Doc, models: DraftModel[]): Slice; |
@@ -0,1 +1,2 @@ | ||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
export class Slice { | ||
@@ -8,5 +9,11 @@ get content() { | ||
} | ||
get pageVersion() { | ||
return this.data.pageVersion; | ||
} | ||
get workspaceId() { | ||
return this.data.workspaceId; | ||
} | ||
get workspaceVersion() { | ||
return this.data.workspaceVersion; | ||
} | ||
constructor(data) { | ||
@@ -16,2 +23,7 @@ this.data = data; | ||
static fromModels(doc, models) { | ||
const meta = doc.collection.meta; | ||
const { pageVersion, workspaceVersion } = meta; | ||
if (!pageVersion || !workspaceVersion) { | ||
throw new BlockSuiteError(ErrorCode.ModelCRUDError, 'pageVersion or workspaceVersion not found when creating slice'); | ||
} | ||
return new Slice({ | ||
@@ -21,2 +33,4 @@ content: models, | ||
pageId: doc.id, | ||
pageVersion, | ||
workspaceVersion, | ||
}); | ||
@@ -23,0 +37,0 @@ } |
@@ -15,2 +15,4 @@ import { z } from 'zod'; | ||
content: BlockSnapshot[]; | ||
pageVersion: number; | ||
workspaceVersion: number; | ||
workspaceId: string; | ||
@@ -23,2 +25,4 @@ pageId: string; | ||
type: 'info'; | ||
pageVersion: number; | ||
workspaceVersion: number; | ||
properties: DocsPropertiesMeta; | ||
@@ -25,0 +29,0 @@ }; |
@@ -13,2 +13,4 @@ import { z } from 'zod'; | ||
content: BlockSnapshotSchema.array(), | ||
pageVersion: z.number(), | ||
workspaceVersion: z.number(), | ||
workspaceId: z.string(), | ||
@@ -20,2 +22,4 @@ pageId: z.string(), | ||
type: z.literal('info'), | ||
pageVersion: z.number(), | ||
workspaceVersion: z.number(), | ||
properties: z.record(z.any()), | ||
@@ -22,0 +26,0 @@ }); |
{ | ||
"name": "@blocksuite/store", | ||
"version": "0.0.0-canary-20241216011454", | ||
"version": "0.0.0-canary-20241216023618", | ||
"description": "BlockSuite data store built for general purpose state management.", | ||
@@ -23,5 +23,5 @@ "type": "module", | ||
"dependencies": { | ||
"@blocksuite/global": "0.0.0-canary-20241216011454", | ||
"@blocksuite/inline": "0.0.0-canary-20241216011454", | ||
"@blocksuite/sync": "0.0.0-canary-20241216011454", | ||
"@blocksuite/global": "0.0.0-canary-20241216023618", | ||
"@blocksuite/inline": "0.0.0-canary-20241216023618", | ||
"@blocksuite/sync": "0.0.0-canary-20241216023618", | ||
"@preact/signals-core": "^1.8.0", | ||
@@ -28,0 +28,0 @@ "@types/flexsearch": "^0.7.6", |
@@ -21,3 +21,2 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
} | ||
async set(value: Blob): Promise<string>; | ||
@@ -24,0 +23,0 @@ |
@@ -78,3 +78,3 @@ import { BlockSuiteError } from '@blocksuite/global/exceptions'; | ||
try { | ||
const blockSnapshot = this.job.blockToSnapshot(model); | ||
const blockSnapshot = await this.job.blockToSnapshot(model); | ||
if (!blockSnapshot) return; | ||
@@ -100,3 +100,3 @@ return await this.fromBlockSnapshot({ | ||
try { | ||
const docSnapshot = this.job.docToSnapshot(doc); | ||
const docSnapshot = await this.job.docToSnapshot(doc); | ||
if (!docSnapshot) return; | ||
@@ -122,3 +122,3 @@ return await this.fromDocSnapshot({ | ||
try { | ||
const sliceSnapshot = this.job.sliceToSnapshot(slice); | ||
const sliceSnapshot = await this.job.sliceToSnapshot(slice); | ||
if (!sliceSnapshot) return; | ||
@@ -125,0 +125,0 @@ wrapFakeNote(sliceSnapshot); |
@@ -34,2 +34,3 @@ import type { BlockSuiteFlags } from '@blocksuite/global/types'; | ||
import { DocCollectionMeta, type DocMeta } from './meta.js'; | ||
import { ObjectPool, type RcRef } from './object-pool.js'; | ||
@@ -69,3 +70,3 @@ export type DocCollectionOptions = { | ||
enable_shape_shadow_blur: false, | ||
enable_new_dnd: true, | ||
enable_new_dnd: false, | ||
enable_mobile_keyboard_toolbar: false, | ||
@@ -96,2 +97,9 @@ enable_mobile_linked_doc_menu: false, | ||
readonly docPool = new ObjectPool<string, Doc>({ | ||
onDelete: doc => { | ||
doc.dispose(); | ||
}, | ||
onDangling: doc => doc.docSync.canGracefulStop(), | ||
}); | ||
readonly docSync: DocEngine; | ||
@@ -182,3 +190,3 @@ | ||
this.meta.docMetaAdded.on(docId => { | ||
const doc = new BlockCollection({ | ||
const blockCollection = new BlockCollection({ | ||
id: docId, | ||
@@ -190,4 +198,4 @@ collection: this, | ||
}); | ||
this.blockCollections.set(doc.id, doc); | ||
this.slots.docAdded.emit(doc.id); | ||
this.blockCollections.set(blockCollection.id, blockCollection); | ||
this.slots.docAdded.emit(blockCollection.id); | ||
}); | ||
@@ -266,2 +274,15 @@ | ||
getDocRef(docId: string): RcRef<Doc> | null { | ||
const ref = this.docPool.get(docId); | ||
if (ref) return ref; | ||
const doc = this.getBlockCollection(docId)?.getDoc(); | ||
if (doc) { | ||
const newRef = this.docPool.put(docId, doc); | ||
return newRef; | ||
} | ||
return null; | ||
} | ||
removeDoc(docId: string) { | ||
@@ -268,0 +289,0 @@ const docMeta = this.meta.getDocMeta(docId); |
@@ -318,8 +318,2 @@ import { type Disposable, Slot } from '@blocksuite/global/utils'; | ||
destroy() { | ||
this._ySpaceDoc.destroy(); | ||
this._onLoadSlot.dispose(); | ||
this._loaded = false; | ||
} | ||
dispose() { | ||
@@ -331,3 +325,3 @@ this.slots.historyUpdated.dispose(); | ||
this._yBlocks.unobserveDeep(this._handleYEvents); | ||
this._yBlocks.clear(); | ||
this._ySpaceDoc.destroy(); | ||
} | ||
@@ -351,3 +345,2 @@ } | ||
blockCollection: this, | ||
crud: this._docCRUD, | ||
schema: this.collection.schema, | ||
@@ -403,3 +396,6 @@ readonly, | ||
remove() { | ||
this.destroy(); | ||
this.clear(); | ||
this._ySpaceDoc.destroy(); | ||
this._onLoadSlot.dispose(); | ||
this._loaded = false; | ||
this.rootDoc.spaces.delete(this.id); | ||
@@ -406,0 +402,0 @@ } |
@@ -88,14 +88,2 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
} | ||
const props = { | ||
...initialProps, | ||
}; | ||
delete props.id; | ||
delete props.flavour; | ||
delete props.children; | ||
Object.entries(props).forEach(([key, value]) => { | ||
if (value === undefined) return; | ||
yBlock.set(`prop:${key}`, native2Y(value)); | ||
}); | ||
} | ||
@@ -102,0 +90,0 @@ } else { |
@@ -8,3 +8,2 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
import type { BlockOptions } from './block/index.js'; | ||
import type { BlockCollection, BlockProps } from './block-collection.js'; | ||
import type { DocCRUD } from './crud.js'; | ||
@@ -14,2 +13,3 @@ | ||
import { Block } from './block/index.js'; | ||
import { BlockCollection, type BlockProps } from './block-collection.js'; | ||
import { type Query, runQuery } from './query.js'; | ||
@@ -20,3 +20,2 @@ | ||
blockCollection: BlockCollection; | ||
crud: DocCRUD; | ||
readonly?: boolean; | ||
@@ -31,9 +30,9 @@ query?: Query; | ||
protected readonly _blockCollection: BlockCollection; | ||
protected _blockCollection!: BlockCollection; | ||
protected readonly _blocks = signal<Record<string, Block>>({}); | ||
protected readonly _crud: DocCRUD; | ||
protected _crud!: DocCRUD; | ||
protected readonly _disposeBlockUpdated: Disposable; | ||
protected _disposeBlockUpdated!: Disposable; | ||
@@ -273,5 +272,3 @@ protected readonly _query: Query = { | ||
constructor({ schema, blockCollection, crud, readonly, query }: DocOptions) { | ||
this._blockCollection = blockCollection; | ||
constructor({ schema, blockCollection, readonly, query }: DocOptions) { | ||
this.slots = { | ||
@@ -282,7 +279,6 @@ ready: new Slot(), | ||
blockUpdated: new Slot(), | ||
historyUpdated: this._blockCollection.slots.historyUpdated, | ||
yBlockUpdated: this._blockCollection.slots.yBlockUpdated, | ||
historyUpdated: blockCollection.slots.historyUpdated, | ||
yBlockUpdated: blockCollection.slots.yBlockUpdated, | ||
}; | ||
this._crud = crud; | ||
this._schema = schema; | ||
@@ -294,9 +290,32 @@ this._readonly = readonly; | ||
this._initializeBlockCollection(blockCollection); | ||
} | ||
private _getSiblings<T>( | ||
block: BlockModel | string, | ||
fn: (parent: BlockModel, index: number) => T | ||
) { | ||
const parent = this.getParent(block); | ||
if (!parent) return null; | ||
const blockModel = | ||
typeof block === 'string' ? this.getBlock(block)?.model : block; | ||
if (!blockModel) return null; | ||
const index = parent.children.indexOf(blockModel); | ||
if (index === -1) return null; | ||
return fn(parent, index); | ||
} | ||
private _initializeBlockCollection(blockCollection: BlockCollection) { | ||
this._blockCollection = blockCollection; | ||
this._crud = blockCollection.crud; | ||
this._yBlocks.forEach((_, id) => { | ||
if (id in this._blocks.peek()) { | ||
return; | ||
} | ||
if (id in this._blocks.peek()) return; | ||
this._onBlockAdded(id, true); | ||
}); | ||
this._disposeBlockUpdated?.dispose(); | ||
this._disposeBlockUpdated = this._blockCollection.slots.yBlockUpdated.on( | ||
@@ -318,19 +337,2 @@ ({ type, id }) => { | ||
private _getSiblings<T>( | ||
block: BlockModel | string, | ||
fn: (parent: BlockModel, index: number) => T | ||
) { | ||
const parent = this.getParent(block); | ||
if (!parent) return null; | ||
const blockModel = | ||
typeof block === 'string' ? this.getBlock(block)?.model : block; | ||
if (!blockModel) return null; | ||
const index = parent.children.indexOf(blockModel); | ||
if (index === -1) return null; | ||
return fn(parent, index); | ||
} | ||
private _onBlockAdded(id: string, init = false) { | ||
@@ -550,7 +552,8 @@ try { | ||
dispose() { | ||
this._blockCollection.dispose(); | ||
this._disposeBlockUpdated.dispose(); | ||
this.slots.ready.dispose(); | ||
this.slots.blockUpdated.dispose(); | ||
this.slots.rootAdded.dispose(); | ||
this.slots.rootDeleted.dispose(); | ||
// this.slots.ready.dispose(); | ||
// this.slots.blockUpdated.dispose(); | ||
// this.slots.rootAdded.dispose(); | ||
// this.slots.rootDeleted.dispose(); | ||
} | ||
@@ -655,2 +658,18 @@ | ||
load(initFn?: () => void) { | ||
// recreate space doc | ||
if (this._blockCollection.spaceDoc.isDestroyed) { | ||
// This section intentionally recreates the BlockCollection by design (circular dependency). | ||
// It ensures the underlying Y.Doc is reinitialized after being garbage collected. | ||
const newBlockCollection = new BlockCollection({ | ||
id: this._blockCollection.id, | ||
collection: this._blockCollection.collection, | ||
doc: this._blockCollection.rootDoc, | ||
awarenessStore: this._blockCollection.awarenessStore, | ||
}); | ||
this._initializeBlockCollection(newBlockCollection); | ||
newBlockCollection.load(initFn); | ||
this.slots.ready.emit(); | ||
return this; | ||
} | ||
this._blockCollection.load(initFn); | ||
@@ -657,0 +676,0 @@ this.slots.ready.emit(); |
@@ -7,1 +7,2 @@ export type * from './collection.js'; | ||
export type * from './meta.js'; | ||
export * from './object-pool.js'; |
@@ -248,2 +248,14 @@ import type * as Y from 'yjs'; | ||
updateVersion(collection: DocCollection) { | ||
this._proxy.workspaceVersion = COLLECTION_VERSION; | ||
this._proxy.pageVersion = PAGE_VERSION; | ||
const _versions: Record<string, number> = {}; | ||
collection.schema.flavourSchemaMap.forEach((schema, flavour) => { | ||
_versions[flavour] = schema.version; | ||
}); | ||
this._proxy.blockVersions = _versions; | ||
} | ||
/** | ||
@@ -250,0 +262,0 @@ * @deprecated Only used for legacy doc version validation |
@@ -67,3 +67,5 @@ import type { BlockModel, InternalPrimitives } from '../schema/index.js'; | ||
toSnapshot({ model }: ToSnapshotPayload<Props>): BlockSnapshotLeaf { | ||
toSnapshot({ | ||
model, | ||
}: ToSnapshotPayload<Props>): Promise<BlockSnapshotLeaf> | BlockSnapshotLeaf { | ||
const { id, flavour, version } = model; | ||
@@ -70,0 +72,0 @@ |
@@ -65,5 +65,7 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
blockToSnapshot = (model: DraftModel): BlockSnapshot | undefined => { | ||
blockToSnapshot = async ( | ||
model: DraftModel | ||
): Promise<BlockSnapshot | undefined> => { | ||
try { | ||
const snapshot = this._blockToSnapshot(model); | ||
const snapshot = await this._blockToSnapshot(model); | ||
BlockSnapshotSchema.parse(snapshot); | ||
@@ -104,3 +106,3 @@ | ||
docToSnapshot = (doc: Doc): DocSnapshot | undefined => { | ||
docToSnapshot = async (doc: Doc): Promise<DocSnapshot | undefined> => { | ||
try { | ||
@@ -119,3 +121,3 @@ this._slots.beforeExport.emit({ | ||
} | ||
const blocks = this.blockToSnapshot(rootModel); | ||
const blocks = await this.blockToSnapshot(rootModel); | ||
if (!blocks) { | ||
@@ -144,3 +146,5 @@ return; | ||
sliceToSnapshot = (slice: Slice): SliceSnapshot | undefined => { | ||
sliceToSnapshot = async ( | ||
slice: Slice | ||
): Promise<SliceSnapshot | undefined> => { | ||
try { | ||
@@ -151,6 +155,7 @@ this._slots.beforeExport.emit({ | ||
}); | ||
const { content, pageId, workspaceId } = slice.data; | ||
const { content, pageVersion, workspaceVersion, pageId, workspaceId } = | ||
slice.data; | ||
const contentSnapshot = []; | ||
for (const block of content) { | ||
const blockSnapshot = this.blockToSnapshot(block); | ||
const blockSnapshot = await this.blockToSnapshot(block); | ||
if (!blockSnapshot) { | ||
@@ -165,2 +170,4 @@ return; | ||
pageId, | ||
pageVersion, | ||
workspaceVersion, | ||
content: contentSnapshot, | ||
@@ -264,3 +271,4 @@ }; | ||
const { content, workspaceId, pageId } = snapshot; | ||
const { content, pageVersion, workspaceVersion, workspaceId, pageId } = | ||
snapshot; | ||
@@ -292,2 +300,4 @@ // Create a temporary root snapshot to encompass all content blocks | ||
content: contentBlocks, | ||
pageVersion, | ||
workspaceVersion, | ||
workspaceId, | ||
@@ -358,3 +368,3 @@ pageId, | ||
private _blockToSnapshot(model: DraftModel): BlockSnapshot { | ||
private async _blockToSnapshot(model: DraftModel): Promise<BlockSnapshot> { | ||
this._slots.beforeExport.emit({ | ||
@@ -366,9 +376,11 @@ type: 'block', | ||
const transformer = this._getTransformer(schema); | ||
const snapshotLeaf = transformer.toSnapshot({ | ||
const snapshotLeaf = await transformer.toSnapshot({ | ||
model, | ||
assets: this._assetsManager, | ||
}); | ||
const children = model.children.map(child => { | ||
return this._blockToSnapshot(child); | ||
}); | ||
const children = await Promise.all( | ||
model.children.map(child => { | ||
return this._blockToSnapshot(child); | ||
}) | ||
); | ||
const snapshot: BlockSnapshot = { | ||
@@ -481,3 +493,15 @@ type: 'block', | ||
const { meta } = this._collection; | ||
const { docs } = meta; | ||
const { pageVersion, workspaceVersion, docs } = meta; | ||
if (!pageVersion) { | ||
throw new BlockSuiteError( | ||
ErrorCode.TransformerError, | ||
'Page version not found' | ||
); | ||
} | ||
if (!workspaceVersion) { | ||
throw new BlockSuiteError( | ||
ErrorCode.TransformerError, | ||
'Workspace version not found' | ||
); | ||
} | ||
if (!docs) { | ||
@@ -487,2 +511,4 @@ throw new BlockSuiteError(ErrorCode.TransformerError, 'Docs not found'); | ||
return { | ||
pageVersion, | ||
workspaceVersion, | ||
properties: {}, // for backward compatibility | ||
@@ -489,0 +515,0 @@ pages: JSON.parse(JSON.stringify(docs)) as DocMeta[], |
@@ -0,1 +1,3 @@ | ||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; | ||
import type { Doc } from '../store/index.js'; | ||
@@ -8,2 +10,4 @@ import type { DraftModel } from './draft.js'; | ||
pageId: string; | ||
pageVersion: number; | ||
workspaceVersion: number; | ||
}; | ||
@@ -20,2 +24,6 @@ | ||
get pageVersion() { | ||
return this.data.pageVersion; | ||
} | ||
get workspaceId() { | ||
@@ -25,5 +33,17 @@ return this.data.workspaceId; | ||
get workspaceVersion() { | ||
return this.data.workspaceVersion; | ||
} | ||
constructor(readonly data: SliceData) {} | ||
static fromModels(doc: Doc, models: DraftModel[]) { | ||
const meta = doc.collection.meta; | ||
const { pageVersion, workspaceVersion } = meta; | ||
if (!pageVersion || !workspaceVersion) { | ||
throw new BlockSuiteError( | ||
ErrorCode.ModelCRUDError, | ||
'pageVersion or workspaceVersion not found when creating slice' | ||
); | ||
} | ||
return new Slice({ | ||
@@ -33,4 +53,6 @@ content: models, | ||
pageId: doc.id, | ||
pageVersion, | ||
workspaceVersion, | ||
}); | ||
} | ||
} |
@@ -26,2 +26,4 @@ import { z } from 'zod'; | ||
content: BlockSnapshot[]; | ||
pageVersion: number; | ||
workspaceVersion: number; | ||
workspaceId: string; | ||
@@ -34,2 +36,4 @@ pageId: string; | ||
content: BlockSnapshotSchema.array(), | ||
pageVersion: z.number(), | ||
workspaceVersion: z.number(), | ||
workspaceId: z.string(), | ||
@@ -42,2 +46,4 @@ pageId: z.string(), | ||
type: 'info'; | ||
pageVersion: number; | ||
workspaceVersion: number; | ||
properties: DocsPropertiesMeta; | ||
@@ -50,2 +56,4 @@ }; | ||
type: z.literal('info'), | ||
pageVersion: z.number(), | ||
workspaceVersion: z.number(), | ||
properties: z.record(z.any()), | ||
@@ -52,0 +60,0 @@ }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
807725
254
11643
+ Added@blocksuite/global@0.0.0-canary-20241216023618(transitive)
+ Added@blocksuite/inline@0.0.0-canary-20241216023618(transitive)
+ Added@blocksuite/sync@0.0.0-canary-20241216023618(transitive)
- Removed@blocksuite/global@0.0.0-canary-20241216011454(transitive)
- Removed@blocksuite/inline@0.0.0-canary-20241216011454(transitive)
- Removed@blocksuite/sync@0.0.0-canary-20241216011454(transitive)