mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-03 02:20:19 +08:00
refactor(core): move workspace implementation to affine (#9504)
This commit is contained in:
@@ -18,7 +18,8 @@
|
|||||||
"@blocksuite/global": "workspace:*",
|
"@blocksuite/global": "workspace:*",
|
||||||
"@blocksuite/inline": "workspace:*",
|
"@blocksuite/inline": "workspace:*",
|
||||||
"@blocksuite/presets": "workspace:*",
|
"@blocksuite/presets": "workspace:*",
|
||||||
"@blocksuite/store": "workspace:*"
|
"@blocksuite/store": "workspace:*",
|
||||||
|
"@blocksuite/sync": "workspace:*"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
@@ -37,7 +38,8 @@
|
|||||||
"./inline/types": "./src/inline/types.ts",
|
"./inline/types": "./src/inline/types.ts",
|
||||||
"./presets": "./src/presets/index.ts",
|
"./presets": "./src/presets/index.ts",
|
||||||
"./blocks": "./src/blocks/index.ts",
|
"./blocks": "./src/blocks/index.ts",
|
||||||
"./blocks/schemas": "./src/blocks/schemas.ts"
|
"./blocks/schemas": "./src/blocks/schemas.ts",
|
||||||
|
"./sync": "./src/sync/index.ts"
|
||||||
},
|
},
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
@@ -88,6 +90,9 @@
|
|||||||
],
|
],
|
||||||
"blocks/schemas": [
|
"blocks/schemas": [
|
||||||
"dist/blocks/schemas.d.ts"
|
"dist/blocks/schemas.d.ts"
|
||||||
|
],
|
||||||
|
"sync": [
|
||||||
|
"dist/sync/index.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export * from '@blocksuite/sync';
|
||||||
@@ -70,10 +70,6 @@ const FLAGS_PRESET = {
|
|||||||
readonly: {},
|
readonly: {},
|
||||||
} satisfies BlockSuiteFlags;
|
} satisfies BlockSuiteFlags;
|
||||||
|
|
||||||
export interface StackItem {
|
|
||||||
meta: Map<'cursor-location' | 'selection-state', unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DocCollection implements Workspace {
|
export class DocCollection implements Workspace {
|
||||||
protected readonly _schema: Schema;
|
protected readonly _schema: Schema;
|
||||||
|
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ export { DocCollection } from './collection.js';
|
|||||||
export type * from './doc/block-collection.js';
|
export type * from './doc/block-collection.js';
|
||||||
export * from './doc/index.js';
|
export * from './doc/index.js';
|
||||||
export * from './id.js';
|
export * from './id.js';
|
||||||
export type * from './meta.js';
|
export * from './meta.js';
|
||||||
export * from './workspace.js';
|
export * from './workspace.js';
|
||||||
|
|||||||
@@ -84,3 +84,7 @@ export interface Workspace {
|
|||||||
|
|
||||||
dispose(): void;
|
dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StackItem {
|
||||||
|
meta: Map<'cursor-location' | 'selection-state', unknown>;
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "./store"
|
"path": "./store"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "./sync"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impl/workspace';
|
||||||
import type {
|
import type {
|
||||||
EditorHost,
|
EditorHost,
|
||||||
TextRangePoint,
|
TextRangePoint,
|
||||||
@@ -14,7 +15,7 @@ import {
|
|||||||
} from '@blocksuite/affine/blocks';
|
} from '@blocksuite/affine/blocks';
|
||||||
import type { ServiceProvider } from '@blocksuite/affine/global/di';
|
import type { ServiceProvider } from '@blocksuite/affine/global/di';
|
||||||
import type { JobMiddleware, Schema } from '@blocksuite/affine/store';
|
import type { JobMiddleware, Schema } from '@blocksuite/affine/store';
|
||||||
import { DocCollection, Job } from '@blocksuite/affine/store';
|
import { Job } from '@blocksuite/affine/store';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import type {
|
import type {
|
||||||
BlockModel,
|
BlockModel,
|
||||||
@@ -207,7 +208,7 @@ export async function markDownToDoc(
|
|||||||
additionalMiddlewares?: JobMiddleware[]
|
additionalMiddlewares?: JobMiddleware[]
|
||||||
) {
|
) {
|
||||||
// Should not create a new doc in the original collection
|
// Should not create a new doc in the original collection
|
||||||
const collection = new DocCollection({
|
const collection = new WorkspaceImpl({
|
||||||
schema,
|
schema,
|
||||||
});
|
});
|
||||||
collection.meta.initialize();
|
collection.meta.initialize();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impl/workspace';
|
||||||
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/block-std';
|
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
type AffineAIPanelWidgetConfig,
|
type AffineAIPanelWidgetConfig,
|
||||||
@@ -6,7 +7,7 @@ import {
|
|||||||
import { AffineSchemas } from '@blocksuite/affine/blocks/schemas';
|
import { AffineSchemas } from '@blocksuite/affine/blocks/schemas';
|
||||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||||
import type { Doc } from '@blocksuite/affine/store';
|
import type { Doc } from '@blocksuite/affine/store';
|
||||||
import { DocCollection, Schema } from '@blocksuite/affine/store';
|
import { Schema } from '@blocksuite/affine/store';
|
||||||
import { css, html, LitElement, nothing } from 'lit';
|
import { css, html, LitElement, nothing } from 'lit';
|
||||||
import { property, query } from 'lit/decorators.js';
|
import { property, query } from 'lit/decorators.js';
|
||||||
import { createRef, type Ref, ref } from 'lit/directives/ref.js';
|
import { createRef, type Ref, ref } from 'lit/directives/ref.js';
|
||||||
@@ -54,7 +55,7 @@ export class AISlidesRenderer extends WithDisposable(LitElement) {
|
|||||||
|
|
||||||
private _doc!: Doc;
|
private _doc!: Doc;
|
||||||
|
|
||||||
private _docCollection: DocCollection | null = null;
|
private _docCollection: WorkspaceImpl | null = null;
|
||||||
|
|
||||||
@query('editor-host')
|
@query('editor-host')
|
||||||
private accessor _editorHost!: EditorHost;
|
private accessor _editorHost!: EditorHost;
|
||||||
@@ -220,7 +221,7 @@ export class AISlidesRenderer extends WithDisposable(LitElement) {
|
|||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
|
||||||
const schema = new Schema().register(AffineSchemas);
|
const schema = new Schema().register(AffineSchemas);
|
||||||
const collection = new DocCollection({
|
const collection = new WorkspaceImpl({
|
||||||
schema,
|
schema,
|
||||||
id: 'SLIDES_PREVIEW',
|
id: 'SLIDES_PREVIEW',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impl/workspace.js';
|
||||||
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/block-std';
|
import { BlockStdScope, type EditorHost } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
MarkdownAdapter,
|
MarkdownAdapter,
|
||||||
@@ -13,7 +14,6 @@ import type { ServiceProvider } from '@blocksuite/affine/global/di';
|
|||||||
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
import { WithDisposable } from '@blocksuite/affine/global/utils';
|
||||||
import {
|
import {
|
||||||
type Doc,
|
type Doc,
|
||||||
DocCollection,
|
|
||||||
type DocCollectionOptions,
|
type DocCollectionOptions,
|
||||||
IdGeneratorType,
|
IdGeneratorType,
|
||||||
Job,
|
Job,
|
||||||
@@ -109,7 +109,7 @@ export class MiniMindmapPreview extends WithDisposable(LitElement) {
|
|||||||
awarenessSources: [],
|
awarenessSources: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const collection = new DocCollection(options);
|
const collection = new WorkspaceImpl(options);
|
||||||
collection.meta.initialize();
|
collection.meta.initialize();
|
||||||
collection.start();
|
collection.start();
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import { useDocMetaHelper } from '@affine/core/components/hooks/use-block-suite-
|
|||||||
import { useDocCollectionPage } from '@affine/core/components/hooks/use-block-suite-workspace-page';
|
import { useDocCollectionPage } from '@affine/core/components/hooks/use-block-suite-workspace-page';
|
||||||
import { FetchService, GraphQLService } from '@affine/core/modules/cloud';
|
import { FetchService, GraphQLService } from '@affine/core/modules/cloud';
|
||||||
import { getAFFiNEWorkspaceSchema } from '@affine/core/modules/workspace';
|
import { getAFFiNEWorkspaceSchema } from '@affine/core/modules/workspace';
|
||||||
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impl/workspace';
|
||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import type { ListHistoryQuery } from '@affine/graphql';
|
import type { ListHistoryQuery } from '@affine/graphql';
|
||||||
import { listHistoryQuery, recoverDocMutation } from '@affine/graphql';
|
import { listHistoryQuery, recoverDocMutation } from '@affine/graphql';
|
||||||
import { i18nTime } from '@affine/i18n';
|
import { i18nTime } from '@affine/i18n';
|
||||||
import { assertEquals } from '@blocksuite/affine/global/utils';
|
import { assertEquals } from '@blocksuite/affine/global/utils';
|
||||||
import { DocCollection, type Workspace } from '@blocksuite/affine/store';
|
import type { Workspace } from '@blocksuite/affine/store';
|
||||||
import { useService } from '@toeverything/infra';
|
import { useService } from '@toeverything/infra';
|
||||||
import { useEffect, useMemo } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
import useSWRImmutable from 'swr/immutable';
|
import useSWRImmutable from 'swr/immutable';
|
||||||
@@ -114,11 +115,9 @@ const getOrCreateShellWorkspace = (
|
|||||||
fetchService,
|
fetchService,
|
||||||
graphQLService
|
graphQLService
|
||||||
);
|
);
|
||||||
docCollection = new DocCollection({
|
docCollection = new WorkspaceImpl({
|
||||||
id: workspaceId,
|
id: workspaceId,
|
||||||
blobSources: {
|
blobSource: blobStorage,
|
||||||
main: blobStorage,
|
|
||||||
},
|
|
||||||
schema: getAFFiNEWorkspaceSchema(),
|
schema: getAFFiNEWorkspaceSchema(),
|
||||||
});
|
});
|
||||||
docCollectionMap.set(workspaceId, docCollection);
|
docCollectionMap.set(workspaceId, docCollection);
|
||||||
|
|||||||
+4
-3
@@ -1,16 +1,17 @@
|
|||||||
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impl/workspace';
|
||||||
import { AffineSchemas } from '@blocksuite/affine/blocks';
|
import { AffineSchemas } from '@blocksuite/affine/blocks';
|
||||||
import type { Doc, DocSnapshot } from '@blocksuite/affine/store';
|
import type { Doc, DocSnapshot } from '@blocksuite/affine/store';
|
||||||
import { DocCollection, Job, Schema } from '@blocksuite/affine/store';
|
import { Job, Schema } from '@blocksuite/affine/store';
|
||||||
|
|
||||||
const getCollection = (() => {
|
const getCollection = (() => {
|
||||||
let collection: DocCollection | null = null;
|
let collection: WorkspaceImpl | null = null;
|
||||||
return async function () {
|
return async function () {
|
||||||
if (collection) {
|
if (collection) {
|
||||||
return collection;
|
return collection;
|
||||||
}
|
}
|
||||||
const schema = new Schema();
|
const schema = new Schema();
|
||||||
schema.register(AffineSchemas);
|
schema.register(AffineSchemas);
|
||||||
collection = new DocCollection({ schema });
|
collection = new WorkspaceImpl({ schema });
|
||||||
collection.meta.initialize();
|
collection.meta.initialize();
|
||||||
return collection;
|
return collection;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import {
|
|||||||
import { Container } from '@blocksuite/affine/global/di';
|
import { Container } from '@blocksuite/affine/global/di';
|
||||||
import {
|
import {
|
||||||
createYProxy,
|
createYProxy,
|
||||||
DocCollection,
|
|
||||||
type DraftModel,
|
type DraftModel,
|
||||||
Job,
|
Job,
|
||||||
type JobMiddleware,
|
type JobMiddleware,
|
||||||
@@ -35,6 +34,7 @@ import {
|
|||||||
} from 'yjs';
|
} from 'yjs';
|
||||||
|
|
||||||
import { getAFFiNEWorkspaceSchema } from '../../workspace/global-schema';
|
import { getAFFiNEWorkspaceSchema } from '../../workspace/global-schema';
|
||||||
|
import { WorkspaceImpl } from '../../workspace/impl/workspace';
|
||||||
import type { BlockIndexSchema, DocIndexSchema } from '../schema';
|
import type { BlockIndexSchema, DocIndexSchema } from '../schema';
|
||||||
import type {
|
import type {
|
||||||
WorkerIngoingMessage,
|
WorkerIngoingMessage,
|
||||||
@@ -118,7 +118,7 @@ const bookmarkFlavours = new Set([
|
|||||||
'affine:embed-loom',
|
'affine:embed-loom',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const markdownPreviewDocCollection = new DocCollection({
|
const markdownPreviewDocCollection = new WorkspaceImpl({
|
||||||
id: 'indexer',
|
id: 'indexer',
|
||||||
schema: blocksuiteSchema,
|
schema: blocksuiteSchema,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import {
|
|||||||
getWorkspaceInfoQuery,
|
getWorkspaceInfoQuery,
|
||||||
getWorkspacesQuery,
|
getWorkspacesQuery,
|
||||||
} from '@affine/graphql';
|
} from '@affine/graphql';
|
||||||
import { DocCollection } from '@blocksuite/affine/store';
|
|
||||||
import {
|
import {
|
||||||
type BlobStorage,
|
type BlobStorage,
|
||||||
catchErrorInto,
|
catchErrorInto,
|
||||||
@@ -20,7 +19,6 @@ import {
|
|||||||
Service,
|
Service,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
import { EMPTY, map, mergeMap, Observable, switchMap } from 'rxjs';
|
import { EMPTY, map, mergeMap, Observable, switchMap } from 'rxjs';
|
||||||
import { encodeStateAsUpdate } from 'yjs';
|
import { encodeStateAsUpdate } from 'yjs';
|
||||||
|
|
||||||
@@ -43,6 +41,7 @@ import {
|
|||||||
type WorkspaceMetadata,
|
type WorkspaceMetadata,
|
||||||
type WorkspaceProfileInfo,
|
type WorkspaceProfileInfo,
|
||||||
} from '../../workspace';
|
} from '../../workspace';
|
||||||
|
import { WorkspaceImpl } from '../../workspace/impl/workspace';
|
||||||
import type { WorkspaceEngineStorageProvider } from '../providers/engine';
|
import type { WorkspaceEngineStorageProvider } from '../providers/engine';
|
||||||
import { BroadcastChannelAwarenessConnection } from './engine/awareness-broadcast-channel';
|
import { BroadcastChannelAwarenessConnection } from './engine/awareness-broadcast-channel';
|
||||||
import { CloudAwarenessConnection } from './engine/awareness-cloud';
|
import { CloudAwarenessConnection } from './engine/awareness-cloud';
|
||||||
@@ -101,7 +100,7 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
|
|||||||
|
|
||||||
async createWorkspace(
|
async createWorkspace(
|
||||||
initial: (
|
initial: (
|
||||||
docCollection: DocCollection,
|
docCollection: WorkspaceImpl,
|
||||||
blobStorage: BlobStorage,
|
blobStorage: BlobStorage,
|
||||||
docStorage: DocStorage
|
docStorage: DocStorage
|
||||||
) => Promise<void>
|
) => Promise<void>
|
||||||
@@ -117,13 +116,10 @@ class CloudWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
|
|||||||
const blobStorage = this.storageProvider.getBlobStorage(workspaceId);
|
const blobStorage = this.storageProvider.getBlobStorage(workspaceId);
|
||||||
const docStorage = this.storageProvider.getDocStorage(workspaceId);
|
const docStorage = this.storageProvider.getDocStorage(workspaceId);
|
||||||
|
|
||||||
const docCollection = new DocCollection({
|
const docCollection = new WorkspaceImpl({
|
||||||
id: workspaceId,
|
id: workspaceId,
|
||||||
idGenerator: () => nanoid(),
|
|
||||||
schema: getAFFiNEWorkspaceSchema(),
|
schema: getAFFiNEWorkspaceSchema(),
|
||||||
blobSources: {
|
blobSource: blobStorage,
|
||||||
main: blobStorage,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
import { DebugLogger } from '@affine/debug';
|
||||||
import { DocCollection } from '@blocksuite/affine/store';
|
|
||||||
import type {
|
import type {
|
||||||
BlobStorage,
|
BlobStorage,
|
||||||
DocStorage,
|
DocStorage,
|
||||||
@@ -20,6 +19,7 @@ import {
|
|||||||
type WorkspaceMetadata,
|
type WorkspaceMetadata,
|
||||||
type WorkspaceProfileInfo,
|
type WorkspaceProfileInfo,
|
||||||
} from '../../workspace';
|
} from '../../workspace';
|
||||||
|
import { WorkspaceImpl } from '../../workspace/impl/workspace';
|
||||||
import type { WorkspaceEngineStorageProvider } from '../providers/engine';
|
import type { WorkspaceEngineStorageProvider } from '../providers/engine';
|
||||||
import { BroadcastChannelAwarenessConnection } from './engine/awareness-broadcast-channel';
|
import { BroadcastChannelAwarenessConnection } from './engine/awareness-broadcast-channel';
|
||||||
import { StaticBlobStorage } from './engine/blob-static';
|
import { StaticBlobStorage } from './engine/blob-static';
|
||||||
@@ -79,7 +79,7 @@ class LocalWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
|
|||||||
}
|
}
|
||||||
async createWorkspace(
|
async createWorkspace(
|
||||||
initial: (
|
initial: (
|
||||||
docCollection: DocCollection,
|
docCollection: WorkspaceImpl,
|
||||||
blobStorage: BlobStorage,
|
blobStorage: BlobStorage,
|
||||||
docStorage: DocStorage
|
docStorage: DocStorage
|
||||||
) => Promise<void>
|
) => Promise<void>
|
||||||
@@ -90,11 +90,10 @@ class LocalWorkspaceFlavourProvider implements WorkspaceFlavourProvider {
|
|||||||
const blobStorage = this.storageProvider.getBlobStorage(id);
|
const blobStorage = this.storageProvider.getBlobStorage(id);
|
||||||
const docStorage = this.storageProvider.getDocStorage(id);
|
const docStorage = this.storageProvider.getDocStorage(id);
|
||||||
|
|
||||||
const docCollection = new DocCollection({
|
const docCollection = new WorkspaceImpl({
|
||||||
id: id,
|
id: id,
|
||||||
idGenerator: () => nanoid(),
|
|
||||||
schema: getAFFiNEWorkspaceSchema(),
|
schema: getAFFiNEWorkspaceSchema(),
|
||||||
blobSources: { main: blobStorage },
|
blobSource: blobStorage,
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
import {
|
import type { Workspace as WorkspaceInterface } from '@blocksuite/affine/store';
|
||||||
DocCollection,
|
|
||||||
type Workspace as BSWorkspace,
|
|
||||||
} from '@blocksuite/affine/store';
|
|
||||||
import { Entity, LiveData } from '@toeverything/infra';
|
import { Entity, LiveData } from '@toeverything/infra';
|
||||||
import { nanoid } from 'nanoid';
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import type { Awareness } from 'y-protocols/awareness.js';
|
import type { Awareness } from 'y-protocols/awareness.js';
|
||||||
|
|
||||||
import { WorkspaceDBService } from '../../db';
|
import { WorkspaceDBService } from '../../db';
|
||||||
import { getAFFiNEWorkspaceSchema } from '../global-schema';
|
import { getAFFiNEWorkspaceSchema } from '../global-schema';
|
||||||
|
import { WorkspaceImpl } from '../impl/workspace';
|
||||||
import type { WorkspaceScope } from '../scopes/workspace';
|
import type { WorkspaceScope } from '../scopes/workspace';
|
||||||
import { WorkspaceEngineService } from '../services/engine';
|
import { WorkspaceEngineService } from '../services/engine';
|
||||||
|
|
||||||
@@ -25,16 +22,13 @@ export class Workspace extends Entity {
|
|||||||
|
|
||||||
readonly flavour = this.meta.flavour;
|
readonly flavour = this.meta.flavour;
|
||||||
|
|
||||||
_docCollection: BSWorkspace | null = null;
|
_docCollection: WorkspaceInterface | null = null;
|
||||||
|
|
||||||
get docCollection() {
|
get docCollection() {
|
||||||
if (!this._docCollection) {
|
if (!this._docCollection) {
|
||||||
this._docCollection = new DocCollection({
|
this._docCollection = new WorkspaceImpl({
|
||||||
id: this.openOptions.metadata.id,
|
id: this.openOptions.metadata.id,
|
||||||
blobSources: {
|
blobSource: this.engine.blob,
|
||||||
main: this.engine.blob,
|
|
||||||
},
|
|
||||||
idGenerator: () => nanoid(),
|
|
||||||
schema: getAFFiNEWorkspaceSchema(),
|
schema: getAFFiNEWorkspaceSchema(),
|
||||||
});
|
});
|
||||||
this._docCollection.slots.docCreated.on(id => {
|
this._docCollection.slots.docCreated.on(id => {
|
||||||
|
|||||||
@@ -0,0 +1,234 @@
|
|||||||
|
import {
|
||||||
|
BlockSuiteError,
|
||||||
|
ErrorCode,
|
||||||
|
} from '@blocksuite/affine/global/exceptions';
|
||||||
|
import type { BlockSuiteFlags } from '@blocksuite/affine/global/types';
|
||||||
|
import { NoopLogger, Slot } from '@blocksuite/affine/global/utils';
|
||||||
|
import {
|
||||||
|
AwarenessStore,
|
||||||
|
BlockCollection,
|
||||||
|
BlockSuiteDoc,
|
||||||
|
type CreateDocOptions,
|
||||||
|
type Doc,
|
||||||
|
DocCollectionMeta,
|
||||||
|
type GetDocOptions,
|
||||||
|
type IdGenerator,
|
||||||
|
nanoid,
|
||||||
|
type Schema,
|
||||||
|
type Workspace,
|
||||||
|
} from '@blocksuite/affine/store';
|
||||||
|
import {
|
||||||
|
AwarenessEngine,
|
||||||
|
BlobEngine,
|
||||||
|
type BlobSource,
|
||||||
|
DocEngine,
|
||||||
|
MemoryBlobSource,
|
||||||
|
NoopDocSource,
|
||||||
|
} from '@blocksuite/affine/sync';
|
||||||
|
import { Awareness } from 'y-protocols/awareness.js';
|
||||||
|
|
||||||
|
type WorkspaceOptions = {
|
||||||
|
id?: string;
|
||||||
|
schema: Schema;
|
||||||
|
blobSource?: BlobSource;
|
||||||
|
};
|
||||||
|
|
||||||
|
const FLAGS_PRESET = {
|
||||||
|
enable_synced_doc_block: false,
|
||||||
|
enable_pie_menu: false,
|
||||||
|
enable_database_number_formatting: false,
|
||||||
|
enable_database_attachment_note: false,
|
||||||
|
enable_database_full_width: false,
|
||||||
|
enable_block_query: false,
|
||||||
|
enable_lasso_tool: false,
|
||||||
|
enable_edgeless_text: true,
|
||||||
|
enable_ai_onboarding: false,
|
||||||
|
enable_ai_chat_block: false,
|
||||||
|
enable_color_picker: false,
|
||||||
|
enable_mind_map_import: false,
|
||||||
|
enable_advanced_block_visibility: false,
|
||||||
|
enable_shape_shadow_blur: false,
|
||||||
|
enable_mobile_keyboard_toolbar: false,
|
||||||
|
enable_mobile_linked_doc_menu: false,
|
||||||
|
readonly: {},
|
||||||
|
} satisfies BlockSuiteFlags;
|
||||||
|
|
||||||
|
export class WorkspaceImpl implements Workspace {
|
||||||
|
protected readonly _schema: Schema;
|
||||||
|
|
||||||
|
readonly awarenessStore: AwarenessStore;
|
||||||
|
|
||||||
|
readonly awarenessSync: AwarenessEngine;
|
||||||
|
|
||||||
|
readonly blobSync: BlobEngine;
|
||||||
|
|
||||||
|
readonly blockCollections = new Map<string, BlockCollection>();
|
||||||
|
|
||||||
|
readonly doc: BlockSuiteDoc;
|
||||||
|
|
||||||
|
readonly docSync: DocEngine;
|
||||||
|
|
||||||
|
readonly id: string;
|
||||||
|
|
||||||
|
readonly idGenerator: IdGenerator;
|
||||||
|
|
||||||
|
meta: DocCollectionMeta;
|
||||||
|
|
||||||
|
slots = {
|
||||||
|
docListUpdated: new Slot(),
|
||||||
|
docRemoved: new Slot<string>(),
|
||||||
|
docCreated: new Slot<string>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
get docs() {
|
||||||
|
return this.blockCollections;
|
||||||
|
}
|
||||||
|
|
||||||
|
get schema() {
|
||||||
|
return this._schema;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor({ id, schema, blobSource }: WorkspaceOptions) {
|
||||||
|
this._schema = schema;
|
||||||
|
|
||||||
|
this.id = id || '';
|
||||||
|
this.doc = new BlockSuiteDoc({ guid: id });
|
||||||
|
this.awarenessStore = new AwarenessStore(new Awareness(this.doc), {
|
||||||
|
...FLAGS_PRESET,
|
||||||
|
readonly: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
blobSource = blobSource ?? new MemoryBlobSource();
|
||||||
|
const docSource = new NoopDocSource();
|
||||||
|
const logger = new NoopLogger();
|
||||||
|
|
||||||
|
this.awarenessSync = new AwarenessEngine(this.awarenessStore.awareness, []);
|
||||||
|
this.docSync = new DocEngine(this.doc, docSource, [], logger);
|
||||||
|
this.blobSync = new BlobEngine(blobSource, [], logger);
|
||||||
|
|
||||||
|
this.idGenerator = nanoid;
|
||||||
|
|
||||||
|
this.meta = new DocCollectionMeta(this.doc);
|
||||||
|
this._bindDocMetaEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _bindDocMetaEvents() {
|
||||||
|
this.meta.docMetaAdded.on(docId => {
|
||||||
|
const doc = new BlockCollection({
|
||||||
|
id: docId,
|
||||||
|
collection: this,
|
||||||
|
doc: this.doc,
|
||||||
|
awarenessStore: this.awarenessStore,
|
||||||
|
idGenerator: this.idGenerator,
|
||||||
|
});
|
||||||
|
this.blockCollections.set(doc.id, doc);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.meta.docMetaUpdated.on(() => this.slots.docListUpdated.emit());
|
||||||
|
|
||||||
|
this.meta.docMetaRemoved.on(id => {
|
||||||
|
const space = this.getBlockCollection(id);
|
||||||
|
if (!space) return;
|
||||||
|
this.blockCollections.delete(id);
|
||||||
|
space.remove();
|
||||||
|
this.slots.docRemoved.emit(id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _hasDoc(docId: string) {
|
||||||
|
return this.docs.has(docId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify that all data has been successfully saved to the primary storage.
|
||||||
|
* Return true if the data transfer is complete and it is secure to terminate the synchronization operation.
|
||||||
|
*/
|
||||||
|
canGracefulStop() {
|
||||||
|
this.docSync.canGracefulStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default, only an empty doc will be created.
|
||||||
|
* If the `init` parameter is passed, a `surface`, `note`, and `paragraph` block
|
||||||
|
* will be created in the doc simultaneously.
|
||||||
|
*/
|
||||||
|
createDoc(options: CreateDocOptions = {}) {
|
||||||
|
const { id: docId = this.idGenerator(), query, readonly } = options;
|
||||||
|
if (this._hasDoc(docId)) {
|
||||||
|
throw new BlockSuiteError(
|
||||||
|
ErrorCode.DocCollectionError,
|
||||||
|
'doc already exists'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.meta.addDocMeta({
|
||||||
|
id: docId,
|
||||||
|
title: '',
|
||||||
|
createDate: Date.now(),
|
||||||
|
tags: [],
|
||||||
|
});
|
||||||
|
this.slots.docCreated.emit(docId);
|
||||||
|
return this.getDoc(docId, { query, readonly }) as Doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.awarenessStore.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate the data sync process forcefully, which may cause data loss.
|
||||||
|
* It is advised to invoke `canGracefulStop` before calling this method.
|
||||||
|
*/
|
||||||
|
forceStop() {
|
||||||
|
this.docSync.forceStop();
|
||||||
|
this.blobSync.stop();
|
||||||
|
this.awarenessSync.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
getBlockCollection(docId: string): BlockCollection | null {
|
||||||
|
const space = this.docs.get(docId) as BlockCollection | undefined;
|
||||||
|
return space ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDoc(docId: string, options?: GetDocOptions): Doc | null {
|
||||||
|
const collection = this.getBlockCollection(docId);
|
||||||
|
return collection?.getDoc(options) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
removeDoc(docId: string) {
|
||||||
|
const docMeta = this.meta.getDocMeta(docId);
|
||||||
|
if (!docMeta) {
|
||||||
|
throw new BlockSuiteError(
|
||||||
|
ErrorCode.DocCollectionError,
|
||||||
|
`doc meta not found: ${docId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const blockCollection = this.getBlockCollection(docId);
|
||||||
|
if (!blockCollection) return;
|
||||||
|
|
||||||
|
blockCollection.dispose();
|
||||||
|
this.meta.removeDocMeta(docId);
|
||||||
|
this.blockCollections.delete(docId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the data sync process
|
||||||
|
*/
|
||||||
|
start() {
|
||||||
|
this.docSync.start();
|
||||||
|
this.blobSync.start();
|
||||||
|
this.awarenessSync.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for all data has been successfully saved to the primary storage.
|
||||||
|
*/
|
||||||
|
waitForGracefulStop(abort?: AbortSignal) {
|
||||||
|
return this.docSync.waitForGracefulStop(abort);
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForSynced() {
|
||||||
|
return this.docSync.waitForSynced();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ export const PackageList = [
|
|||||||
'blocksuite/framework/inline',
|
'blocksuite/framework/inline',
|
||||||
'blocksuite/presets',
|
'blocksuite/presets',
|
||||||
'blocksuite/framework/store',
|
'blocksuite/framework/store',
|
||||||
|
'blocksuite/framework/sync',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3804,6 +3804,7 @@ __metadata:
|
|||||||
"@blocksuite/inline": "workspace:*"
|
"@blocksuite/inline": "workspace:*"
|
||||||
"@blocksuite/presets": "workspace:*"
|
"@blocksuite/presets": "workspace:*"
|
||||||
"@blocksuite/store": "workspace:*"
|
"@blocksuite/store": "workspace:*"
|
||||||
|
"@blocksuite/sync": "workspace:*"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user