feat(editor): schema extension (#10447)

1. **Major Architectural Change: Schema Management**
   - Moved from `workspace.schema` to `store.schema` throughout the codebase
   - Removed schema property from Workspace and Doc interfaces
   - Added `BlockSchemaExtension` pattern across multiple block types

2. **Block Schema Extensions Added**
   - Added new `BlockSchemaExtension` to numerous block types including:
     - DataView, Surface, Attachment, Bookmark, Code
     - Database, Divider, EdgelessText, Embed blocks (Figma, Github, HTML, etc.)
     - Frame, Image, Latex, List, Note, Paragraph
     - Root, Surface Reference, Table blocks

3. **Import/Export System Updates**
   - Updated import functions to accept `schema` parameter:
     - `importHTMLToDoc`
     - `importHTMLZip`
     - `importMarkdownToDoc`
     - `importMarkdownZip`
     - `importNotionZip`
   - Modified export functions to use new schema pattern

4. **Test Infrastructure Updates**
   - Updated test files to use new schema extensions
   - Modified test document creation to include schema extensions
   - Removed direct schema registration in favor of extensions

5. **Service Layer Changes**
   - Updated various services to use `getAFFiNEWorkspaceSchema()`
   - Modified transformer initialization to use document schema
   - Updated collection initialization patterns

6. **Version Management**
   - Removed version-related properties and methods from:
     - `WorkspaceMetaImpl`
     - `TestMeta`
     - `DocImpl`
   - Removed `blockVersions` and `workspaceVersion/pageVersion`

7. **Store and Extension Updates**
   - Added new store extensions and adapters
   - Updated store initialization patterns
   - Added new schema-related functionality in store extension

This PR represents a significant architectural shift in how schemas are managed, moving from a workspace-centric to a store-centric approach, while introducing a more extensible block schema system through `BlockSchemaExtension`. The changes touch multiple layers of the application including core functionality, services, testing infrastructure, and import/export capabilities.
This commit is contained in:
Saul-Mirone
2025-02-26 11:31:28 +00:00
parent 2732b96d00
commit ce87dcf58e
95 changed files with 655 additions and 490 deletions
@@ -3,7 +3,11 @@ import type {
GfxElementGeometry,
} from '@blocksuite/block-std/gfx';
import { GfxCompatible } from '@blocksuite/block-std/gfx';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
import type { EmbedCardStyle } from '../../utils/index.js';
import { AttachmentBlockTransformer } from './attachment-transformer.js';
@@ -86,6 +90,10 @@ export const AttachmentBlockSchema = defineBlockSchema({
toModel: () => new AttachmentBlockModel(),
});
export const AttachmentBlockSchemaExtension = BlockSchemaExtension(
AttachmentBlockSchema
);
export class AttachmentBlockModel
extends GfxCompatible<AttachmentBlockProps>(BlockModel)
implements GfxElementGeometry {}
@@ -3,7 +3,11 @@ import type {
GfxElementGeometry,
} from '@blocksuite/block-std/gfx';
import { GfxCompatible } from '@blocksuite/block-std/gfx';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
import type { EmbedCardStyle, LinkPreviewData } from '../../utils/index.js';
@@ -54,6 +58,9 @@ export const BookmarkBlockSchema = defineBlockSchema({
toModel: () => new BookmarkBlockModel(),
});
export const BookmarkBlockSchemaExtension =
BlockSchemaExtension(BookmarkBlockSchema);
export class BookmarkBlockModel
extends GfxCompatible<BookmarkBlockProps>(BlockModel)
implements GfxElementGeometry {}
@@ -1,4 +1,9 @@
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
type Text,
} from '@blocksuite/store';
interface CodeBlockProps {
text: Text;
@@ -30,6 +35,8 @@ export const CodeBlockSchema = defineBlockSchema({
toModel: () => new CodeBlockModel(),
});
export const CodeBlockSchemaExtension = BlockSchemaExtension(CodeBlockSchema);
export class CodeBlockModel extends BlockModel<CodeBlockProps> {
override text!: Text;
}
@@ -1,5 +1,9 @@
import type { Text } from '@blocksuite/store';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
import type { Column, SerializedCells, ViewBasicDataType } from './types.js';
@@ -28,3 +32,6 @@ export const DatabaseBlockSchema = defineBlockSchema({
},
toModel: () => new DatabaseBlockModel(),
});
export const DatabaseBlockSchemaExtension =
BlockSchemaExtension(DatabaseBlockSchema);
@@ -1,4 +1,8 @@
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
export const DividerBlockSchema = defineBlockSchema({
flavour: 'affine:divider',
@@ -15,3 +19,6 @@ type Props = {
};
export class DividerBlockModel extends BlockModel<Props> {}
export const DividerBlockSchemaExtension =
BlockSchemaExtension(DividerBlockSchema);
@@ -3,7 +3,11 @@ import type {
GfxElementGeometry,
} from '@blocksuite/block-std/gfx';
import { GfxCompatible } from '@blocksuite/block-std/gfx';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
import { z } from 'zod';
import {
@@ -76,6 +80,10 @@ export const EdgelessTextBlockSchema = defineBlockSchema({
},
});
export const EdgelessTextBlockSchemaExtension = BlockSchemaExtension(
EdgelessTextBlockSchema
);
export class EdgelessTextBlockModel
extends GfxCompatible<EdgelessTextProps>(BlockModel)
implements GfxElementGeometry {}
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedFigmaBlockProps,
@@ -20,3 +22,7 @@ export const EmbedFigmaBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedFigmaModel(),
props: (): EmbedFigmaBlockProps => defaultEmbedFigmaProps,
});
export const EmbedFigmaBlockSchemaExtension = BlockSchemaExtension(
EmbedFigmaBlockSchema
);
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedGithubBlockProps,
@@ -29,3 +31,7 @@ export const EmbedGithubBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedGithubModel(),
props: (): EmbedGithubBlockProps => defaultEmbedGithubProps,
});
export const EmbedGithubBlockSchemaExtension = BlockSchemaExtension(
EmbedGithubBlockSchema
);
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedHtmlBlockProps,
@@ -18,3 +20,6 @@ export const EmbedHtmlBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedHtmlModel(),
props: (): EmbedHtmlBlockProps => defaultEmbedHtmlProps,
});
export const EmbedHtmlBlockSchemaExtension =
BlockSchemaExtension(EmbedHtmlBlockSchema);
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedLinkedDocBlockProps,
@@ -20,3 +22,7 @@ export const EmbedLinkedDocBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedLinkedDocModel(),
props: (): EmbedLinkedDocBlockProps => defaultEmbedLinkedDocBlockProps,
});
export const EmbedLinkedDocBlockSchemaExtension = BlockSchemaExtension(
EmbedLinkedDocBlockSchema
);
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedLoomBlockProps,
@@ -22,3 +24,6 @@ export const EmbedLoomBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedLoomModel(),
props: (): EmbedLoomBlockProps => defaultEmbedLoomProps,
});
export const EmbedLoomBlockSchemaExtension =
BlockSchemaExtension(EmbedLoomBlockSchema);
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedSyncedDocBlockProps,
@@ -21,3 +23,7 @@ export const EmbedSyncedDocBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedSyncedDocModel(),
props: (): EmbedSyncedDocBlockProps => defaultEmbedSyncedDocBlockProps,
});
export const EmbedSyncedDocBlockSchemaExtension = BlockSchemaExtension(
EmbedSyncedDocBlockSchema
);
@@ -1,3 +1,5 @@
import { BlockSchemaExtension } from '@blocksuite/store';
import { createEmbedBlockSchema } from '../../../utils/index.js';
import {
type EmbedYoutubeBlockProps,
@@ -25,3 +27,7 @@ export const EmbedYoutubeBlockSchema = createEmbedBlockSchema({
toModel: () => new EmbedYoutubeModel(),
props: (): EmbedYoutubeBlockProps => defaultEmbedYoutubeProps,
});
export const EmbedYoutubeBlockSchemaExtension = BlockSchemaExtension(
EmbedYoutubeBlockSchema
);
@@ -15,7 +15,12 @@ import {
hasDescendantElementImpl,
} from '@blocksuite/block-std/gfx';
import { Bound } from '@blocksuite/global/utils';
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
type Text,
} from '@blocksuite/store';
import { z } from 'zod';
import { type Color, ColorSchema, DefaultTheme } from '../../themes/index.js';
@@ -57,6 +62,8 @@ export const FrameBlockSchema = defineBlockSchema({
},
});
export const FrameBlockSchemaExtension = BlockSchemaExtension(FrameBlockSchema);
export class FrameBlockModel
extends GfxCompatible<FrameBlockProps>(BlockModel)
implements GfxElementGeometry, GfxGroupCompatibleInterface
@@ -3,7 +3,11 @@ import type {
GfxElementGeometry,
} from '@blocksuite/block-std/gfx';
import { GfxCompatible } from '@blocksuite/block-std/gfx';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
import { ImageBlockTransformer } from './image-transformer.js';
@@ -40,6 +44,8 @@ export const ImageBlockSchema = defineBlockSchema({
toModel: () => new ImageBlockModel(),
});
export const ImageBlockSchemaExtension = BlockSchemaExtension(ImageBlockSchema);
export class ImageBlockModel
extends GfxCompatible<ImageBlockProps>(BlockModel)
implements GfxElementGeometry {}
@@ -3,7 +3,11 @@ import {
GfxCompatible,
type GfxElementGeometry,
} from '@blocksuite/block-std/gfx';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
export type LatexProps = {
latex: string;
@@ -34,6 +38,8 @@ export const LatexBlockSchema = defineBlockSchema({
},
});
export const LatexBlockSchemaExtension = BlockSchemaExtension(LatexBlockSchema);
export class LatexBlockModel
extends GfxCompatible<LatexProps>(BlockModel)
implements GfxElementGeometry {}
@@ -1,5 +1,9 @@
import type { Text } from '@blocksuite/store';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
// `toggle` type has been deprecated, do not use it
export type ListType = 'bulleted' | 'numbered' | 'todo' | 'toggle';
@@ -38,6 +42,8 @@ export const ListBlockSchema = defineBlockSchema({
toModel: () => new ListBlockModel(),
});
export const ListBlockSchemaExtension = BlockSchemaExtension(ListBlockSchema);
export class ListBlockModel extends BlockModel<ListProps> {
override text!: Text;
}
@@ -4,7 +4,11 @@ import type {
} from '@blocksuite/block-std/gfx';
import { GfxCompatible } from '@blocksuite/block-std/gfx';
import { Bound } from '@blocksuite/global/utils';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
import { z } from 'zod';
import {
@@ -21,6 +25,7 @@ import {
StrokeStyleSchema,
} from '../../consts/note';
import { type Color, ColorSchema, DefaultTheme } from '../../themes';
import { TableModelFlavour } from '../table';
export const NoteZodSchema = z
.object({
@@ -47,7 +52,6 @@ export const NoteZodSchema = z
},
},
});
import { TableModelFlavour } from '../table';
export const NoteBlockSchema = defineBlockSchema({
flavour: 'affine:note',
@@ -92,6 +96,7 @@ export const NoteBlockSchema = defineBlockSchema({
},
});
export const NoteBlockSchemaExtension = BlockSchemaExtension(NoteBlockSchema);
export type NoteProps = {
background: Color;
displayMode: NoteDisplayMode;
@@ -1,4 +1,9 @@
import { BlockModel, defineBlockSchema, type Text } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
type Text,
} from '@blocksuite/store';
export type ParagraphType =
| 'text'
@@ -37,6 +42,9 @@ export const ParagraphBlockSchema = defineBlockSchema({
toModel: () => new ParagraphBlockModel(),
});
export const ParagraphBlockSchemaExtension =
BlockSchemaExtension(ParagraphBlockSchema);
export class ParagraphBlockModel extends BlockModel<ParagraphProps> {
override text!: Text;
@@ -1,5 +1,9 @@
import type { Text } from '@blocksuite/store';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
export type RootBlockProps = {
title: Text;
@@ -51,3 +55,5 @@ export const RootBlockSchema = defineBlockSchema({
},
toModel: () => new RootBlockModel(),
});
export const RootBlockSchemaExtension = BlockSchemaExtension(RootBlockSchema);
@@ -1,4 +1,8 @@
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
export type SurfaceRefProps = {
reference: string;
@@ -21,4 +25,8 @@ export const SurfaceRefBlockSchema = defineBlockSchema({
toModel: () => new SurfaceRefBlockModel(),
});
export const SurfaceRefBlockSchemaExtension = BlockSchemaExtension(
SurfaceRefBlockSchema
);
export class SurfaceRefBlockModel extends BlockModel<SurfaceRefProps> {}
@@ -1,6 +1,10 @@
import type { DeltaInsert } from '@blocksuite/inline';
import type { Text } from '@blocksuite/store';
import { BlockModel, defineBlockSchema } from '@blocksuite/store';
import {
BlockModel,
BlockSchemaExtension,
defineBlockSchema,
} from '@blocksuite/store';
export type TableCell = {
text: Text;
@@ -56,3 +60,5 @@ export const TableBlockSchema = defineBlockSchema({
},
toModel: () => new TableBlockModel(),
});
export const TableBlockSchemaExtension = BlockSchemaExtension(TableBlockSchema);