snapshot of https://github.com/toeverything/AFFiNE.git (canary, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Build & Test / Analyze (javascript, affine) (push) Failing after 4s
Build & Test / Analyze (typescript, affine) (push) Failing after 3s
Build & Test / Rust test filter (push) Failing after 4s
Build & Test / Check yarn binary (push) Failing after 3s
Build & Test / E2E BlockSuite Test (3) (push) Failing after 3s
Build & Test / Analyze (javascript, blocksuite) (push) Failing after 3s
Build & Test / Analyze (typescript, blocksuite) (push) Failing after 3s
Build & Test / Mobile native build filter (push) Failing after 3s
Build & Test / E2E BlockSuite Test (1) (push) Failing after 4s
Build & Test / E2E BlockSuite Test (2) (push) Failing after 4s
Build & Test / E2E Mobile Test (1) (push) Failing after 3s
Build & Test / Unit Test (1) (push) Has been skipped
Build & Test / Unit Test (2) (push) Has been skipped
Build & Test / Unit Test (3) (push) Has been skipped
Build & Test / Unit Test (4) (push) Has been skipped
Build & Test / Unit Test (5) (push) Has been skipped
Build & Test / Native Unit Test (push) Has been skipped
Build & Test / E2E BlockSuite Test (4) (push) Failing after 3s
Build & Test / E2E BlockSuite Test (5) (push) Failing after 3s
Build & Test / E2E BlockSuite Cross Browser Test (push) Failing after 3s
Build & Test / E2E Mobile Test (2) (push) Failing after 3s
Build & Test / Build AFFiNE native (x86_64-unknown-linux-gnu) (push) Failing after 3s
Build & Test / Build Server native (push) Failing after 3s
Build & Test / Check Git Status (push) Has been skipped
Build & Test / Server Test (0, 4) (push) Has been skipped
Build & Test / Server Test (1, 4) (push) Has been skipped
Build & Test / Server Test (2, 4) (push) Has been skipped
Build & Test / Server Test (3, 4) (push) Has been skipped
Build & Test / Server Test with Elasticsearch (push) Has been skipped
Build & Test / Build @affine/electron renderer (push) Failing after 3s
Build & Test / Copilot test filter (push) Failing after 4s
Build & Test / Lint Rust (push) Has been skipped
Build & Test / Server Test with Embedded Search (push) Has been skipped
Build & Test / Server Test with Manticore Search (push) Has been skipped
Build & Test / Server E2E Test (push) Has been skipped
Build & Test / Cloud Desktop E2E Test (push) Has been skipped
Build & Test / Cloud E2E Test 1/2 (push) Has been skipped
Build & Test / Cloud E2E Test 2/2 (push) Has been skipped
Build & Test / Build Android app (push) Has been skipped
Build & Test / Test Android app (push) Has been skipped
Build & Test / Run native tests (push) Has been skipped
Build & Test / Server Copilot Api Test (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (1, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (2, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (3, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (4, 5) (push) Has been skipped
Build & Test / Frontend Copilot E2E Test (5, 5) (push) Has been skipped
Release / Canary Gate (push) Has been skipped
Build & Test / Build AFFiNE native (aarch64-apple-darwin) (push) Has been cancelled
Build & Test / Lint (push) Has been cancelled
Build & Test / Typecheck (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-apple-darwin) (push) Has been cancelled
Build & Test / Desktop Test (ubuntu-latest, linux, x64, x86_64-unknown-linux-gnu, true) (push) Has been cancelled
Build & Test / Desktop Test (windows-latest, windows, x64, x86_64-pc-windows-msvc, true) (push) Has been cancelled
Build & Test / E2E Test (1) (push) Has been cancelled
Build & Test / E2E Test (2) (push) Has been cancelled
Build & Test / E2E Test (3) (push) Has been cancelled
Build & Test / E2E Test (4) (push) Has been cancelled
Build & Test / E2E Test (5) (push) Has been cancelled
Build & Test / Build AFFiNE native (aarch64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Build AFFiNE native (x86_64-pc-windows-msvc) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, arm64, aarch64-apple-darwin, true) (push) Has been cancelled
Build & Test / Desktop Test (macos-latest, macos, x64, x86_64-apple-darwin, false) (push) Has been cancelled
Build & Test / 3, 2, 1 Launch (push) Has been cancelled
Build & Test / Build iOS app (push) Has been cancelled
Copilot Test Automatically / Setup Test (push) Failing after 1s
Release / Prepare (push) Failing after 2s
Release / Release Cloud (push) Has been skipped
Release / Release Desktop (push) Has been skipped
Release / Release Docker Image (push) Has been skipped
Release / Release Mobile (push) Has been skipped

This commit is contained in:
upstream-mirror
2026-09-16 04:01:20 +05:00
commit 702cc698a7
9990 changed files with 1073618 additions and 0 deletions

View File

@@ -0,0 +1,141 @@
[**BlockSuite API Documentation**](../../../README.md)
***
[BlockSuite API Documentation](../../../README.md) / [@blocksuite/store](../README.md) / Boxed
# Class: Boxed\<Value\>
Boxed is to store raw data in Yjs.
By default, store will try to convert a object to a Y.Map.
If you want to store a raw object for you want to manipulate the Y.Map directly, you can use Boxed.
> [!NOTE]
> Please notice that the data will be stored in Y.Map anyway so it can not hold data structure like function.
## Example
```ts
const boxedObject = new Boxed({ a: 1, b: 2 });
const boxedYMap = new Boxed(new Y.Map());
boxedObject.getValue().a; // 1
boxedYMap.getValue().set('a', 1);
boxedObject.setValue({ foo: 'bar' });
```
## Type Param
**T**
The type of the value stored in the Boxed.
## Type Parameters
### Value
`Value` = `unknown`
## Methods
### getValue()
> **getValue**(): `Value` \| `undefined`
Get the current value of the Boxed.
#### Returns
`Value` \| `undefined`
***
### setValue()
> **setValue**(`value`): `Value`
Replace the current value of the Boxed.
#### Parameters
##### value
`Value`
The new value to set.
#### Returns
`Value`
***
### from()
> `static` **from**\<`Value`\>(`map`): `Boxed`\<`Value`\>
Create a Boxed from a Y.Map.
It is useful when you sync a Y.Map from remote.
#### Type Parameters
##### Value
`Value`
The type of the value.
#### Parameters
##### map
`YMap`\<`unknown`\>
#### Returns
`Boxed`\<`Value`\>
#### Example
```ts
const doc1 = new Y.Doc();
const doc2 = new Y.Doc();
keepSynced(doc1, doc2);
const data1 = doc1.getMap('data');
const boxed1 = new Boxed({ a: 1, b: 2 });
data1.set('boxed', boxed1.yMap);
const data2 = doc2.getMap('data');
const boxed2 = Boxed.from<{ a: number; b: number }>(data2.get('boxed'));
```
***
### is()
> `static` **is**(`value`): `value is Boxed<unknown>`
Check if a value is a Boxed.
#### Parameters
##### value
`unknown`
#### Returns
`value is Boxed<unknown>`
#### Example
```ts
const doc = new Y.Doc();
const data = doc.getMap('data');
const boxed = new Boxed({ a: 1, b: 2 });
Boxed.is(boxed); // true
data.set('boxed', boxed.yMap);
Boxed.is(data.get('boxed)); // true
```

View File

@@ -0,0 +1,133 @@
[**BlockSuite API Documentation**](../../../README.md)
***
[BlockSuite API Documentation](../../../README.md) / [@blocksuite/store](../README.md) / Extension
# Abstract Class: Extension
# Understanding Extensions
Extensions provide a way to extend the functionality of a system using dependency injection.
They allow you to register services, implementations, and factories in the DI container,
which can then be retrieved and used by different parts of the application.
Extensions are particularly useful for:
- Registering different implementations for different types
- Creating pluggable architecture where components can be added or removed
- Managing dependencies between different parts of the application
# Usage Example: Fruit Processing System
Let's consider a fruit processing system where different types of fruits need
different processing methods. We'll show how to implement this using extensions.
## Step 1: Define the interfaces
```ts
interface FruitProcessor {
process(fruit: Fruit): void;
}
interface Fruit {
type: string;
// other properties
}
```
## Step 2: Create a service identifier
```ts
import { createIdentifier } from '@blocksuite/global/di';
const FruitProcessorProvider = createIdentifier<FruitProcessor>('fruit-processor-provider');
```
## Step 3: Create implementations
```ts
class AppleProcessor implements FruitProcessor {
process(fruit: Fruit): void {
console.log('Slicing apple');
// Apple-specific processing
}
}
class BananaProcessor implements FruitProcessor {
process(fruit: Fruit): void {
console.log('Peeling banana');
// Banana-specific processing
}
}
```
## Step 4: Create an extension factory
```ts
const FruitProcessorExtension = (
fruitType: string,
implementation: new () => FruitProcessor
): ExtensionType => {
return {
setup: di => {
di.addImpl(FruitProcessorProvider(fruitType), implementation);
}
};
};
```
## Step 5: Create concrete extensions
```ts
export const AppleProcessorExtension = FruitProcessorExtension('apple', AppleProcessor);
export const BananaProcessorExtension = FruitProcessorExtension('banana', BananaProcessor);
```
## Step 6: Use the extensions
```ts
import { Container } from '@blocksuite/global/di';
class FruitProcessingSystem {
provider: ServiceProvider;
constructor(extensions: ExtensionType[]) {
const container = new Container();
// Set up all extensions
extensions.forEach(ext => ext.setup(container));
// Create a provider from the container
this.provider = container.provider();
}
processFruit(fruit: Fruit) {
// Get the appropriate processor based on fruit type
const processor = this.provider.get(FruitProcessorProvider(fruit.type));
// Process the fruit
processor.process(fruit);
}
}
// Initialize the system with extensions
const system = new FruitProcessingSystem([
AppleProcessorExtension,
BananaProcessorExtension
]);
// Use the system
system.processFruit({ type: 'apple' }); // Output: Slicing apple
system.processFruit({ type: 'banana' }); // Output: Peeling banana
```
Note: We deliberately used a non-block specific example here. In BlockSuite, the extension
pattern can be applied to any entity that can be configured by third parties, not just blocks.
This includes different tools in the whiteboard, different column types in database blocks,
and many other extensible components. The pattern remains the same regardless of what you're extending.
## Extended by
- [`StoreExtension`](StoreExtension.md)
- [`BlockService`](../../std/index/classes/BlockService.md)
- [`LifeCycleWatcher`](../../std/index/classes/LifeCycleWatcher.md)

View File

@@ -0,0 +1,297 @@
[**BlockSuite API Documentation**](../../../README.md)
***
[BlockSuite API Documentation](../../../README.md) / [@blocksuite/store](../README.md) / Schema
# Class: Schema
Represents a schema manager for block flavours and their relationships.
Provides methods to register, validate, and query block schemas.
## Properties
### flavourSchemaMap
> `readonly` **flavourSchemaMap**: `Map`\<`string`, \{ `model`: \{ `children?`: `string`[]; `flavour`: `string`; `isFlatData?`: `boolean`; `parent?`: `string`[]; `props?`: (...`args`) => `Record`\<`string`, `any`\>; `role`: `string`; `toModel?`: (...`args`) => `BlockModel`\<`object`\>; \}; `transformer?`: (...`args`) => `BaseBlockTransformer`\<`object`\>; `version`: `number`; \}\>
A map storing block flavour names to their corresponding schema definitions.
## Accessors
### versions
#### Get Signature
> **get** **versions**(): `object`
Returns an object mapping each registered flavour to its version number.
##### Returns
`object`
## Methods
### get()
> **get**(`flavour`): \{ `model`: \{ `children?`: `string`[]; `flavour`: `string`; `isFlatData?`: `boolean`; `parent?`: `string`[]; `props?`: (...`args`) => `Record`\<`string`, `any`\>; `role`: `string`; `toModel?`: (...`args`) => `BlockModel`\<`object`\>; \}; `transformer?`: (...`args`) => `BaseBlockTransformer`\<`object`\>; `version`: `number`; \} \| `undefined`
Retrieves the schema for a given block flavour.
#### Parameters
##### flavour
`string`
The block flavour name.
#### Returns
\{ `model`: \{ `children?`: `string`[]; `flavour`: `string`; `isFlatData?`: `boolean`; `parent?`: `string`[]; `props?`: (...`args`) => `Record`\<`string`, `any`\>; `role`: `string`; `toModel?`: (...`args`) => `BlockModel`\<`object`\>; \}; `transformer?`: (...`args`) => `BaseBlockTransformer`\<`object`\>; `version`: `number`; \} \| `undefined`
The corresponding BlockSchemaType or undefined if not found.
***
### isValid()
> **isValid**(`child`, `parent`): `boolean`
Checks if the child flavour is valid under the parent flavour.
#### Parameters
##### child
`string`
The child block flavour name.
##### parent
`string`
The parent block flavour name.
#### Returns
`boolean`
True if the relationship is valid, false otherwise.
***
### register()
> **register**(`blockSchema`): `Schema`
Registers an array of block schemas into the schema manager.
#### Parameters
##### blockSchema
`object`[]
An array of block schema definitions to register.
#### Returns
`Schema`
The Schema instance (for chaining).
***
### safeValidate()
> **safeValidate**(`flavour`, `parentFlavour?`, `childFlavours?`): `boolean`
Safely validates the schema relationship for a given flavour, parent, and children.
Returns true if valid, false otherwise (does not throw).
#### Parameters
##### flavour
`string`
The block flavour to validate.
##### parentFlavour?
`string`
The parent block flavour (optional).
##### childFlavours?
`string`[]
The child block flavours (optional).
#### Returns
`boolean`
True if the schema relationship is valid, false otherwise.
***
### toJSON()
> **toJSON**(): `object`
Serializes the schema map to a plain object for JSON output.
#### Returns
`object`
An object mapping each flavour to its role, parent, and children.
***
### validate()
> **validate**(`flavour`, `parentFlavour?`, `childFlavours?`): `void`
Validates the schema relationship for a given flavour, parent, and children.
Throws SchemaValidateError if invalid.
#### Parameters
##### flavour
`string`
The block flavour to validate.
##### parentFlavour?
`string`
The parent block flavour (optional).
##### childFlavours?
`string`[]
The child block flavours (optional).
#### Returns
`void`
#### Throws
If the schema relationship is invalid.
***
### validateSchema()
> **validateSchema**(`child`, `parent`): `void`
Validates the relationship between a child and parent schema.
Throws if the relationship is invalid.
#### Parameters
##### child
The child block schema.
###### model
\{ `children?`: `string`[]; `flavour`: `string`; `isFlatData?`: `boolean`; `parent?`: `string`[]; `props?`: (...`args`) => `Record`\<`string`, `any`\>; `role`: `string`; `toModel?`: (...`args`) => `BlockModel`\<`object`\>; \} = `...`
###### model.children?
`string`[] = `ContentSchema`
###### model.flavour
`string` = `FlavourSchema`
###### model.isFlatData?
`boolean` = `...`
###### model.parent?
`string`[] = `ParentSchema`
###### model.props?
(...`args`) => `Record`\<`string`, `any`\> = `...`
###### model.role
`string` = `RoleSchema`
###### model.toModel?
(...`args`) => `BlockModel`\<`object`\> = `...`
###### transformer?
(...`args`) => `BaseBlockTransformer`\<`object`\> = `...`
###### version
`number` = `...`
##### parent
The parent block schema.
###### model
\{ `children?`: `string`[]; `flavour`: `string`; `isFlatData?`: `boolean`; `parent?`: `string`[]; `props?`: (...`args`) => `Record`\<`string`, `any`\>; `role`: `string`; `toModel?`: (...`args`) => `BlockModel`\<`object`\>; \} = `...`
###### model.children?
`string`[] = `ContentSchema`
###### model.flavour
`string` = `FlavourSchema`
###### model.isFlatData?
`boolean` = `...`
###### model.parent?
`string`[] = `ParentSchema`
###### model.props?
(...`args`) => `Record`\<`string`, `any`\> = `...`
###### model.role
`string` = `RoleSchema`
###### model.toModel?
(...`args`) => `BlockModel`\<`object`\> = `...`
###### transformer?
(...`args`) => `BaseBlockTransformer`\<`object`\> = `...`
###### version
`number` = `...`
#### Returns
`void`
#### Throws
If the relationship is invalid.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
[**BlockSuite API Documentation**](../../../README.md)
***
[BlockSuite API Documentation](../../../README.md) / [@blocksuite/store](../README.md) / StoreExtension
# Class: StoreExtension
Store extensions are used to extend the store.
They should be registered to the store. And they should be able to run in a none-dom environment.
## Extends
- [`Extension`](Extension.md)
## Properties
### key
> `readonly` `static` **key**: `string`
The key of the store extension.
**You must override this property with a unique string.**
## Methods
### disposed()
> **disposed**(): `void`
Lifecycle hook when the yjs document is disposed.
#### Returns
`void`
***
### loaded()
> **loaded**(): `void`
Lifecycle hook when the yjs document is loaded.
#### Returns
`void`

View File

@@ -0,0 +1,398 @@
[**BlockSuite API Documentation**](../../../README.md)
***
[BlockSuite API Documentation](../../../README.md) / [@blocksuite/store](../README.md) / Text
# Class: Text\<TextAttributes\>
Text is an abstraction of Y.Text.
It provides useful methods to manipulate the text content.
## Example
```ts
const text = new Text('Hello, world!');
text.insert(' blocksuite', 7);
text.delete(7, 1);
text.format(7, 1, { bold: true });
text.join(new Text(' blocksuite'));
text.split(7, 1);
```
Text [delta](https://docs.yjs.dev/api/delta-format) is a format from Y.js.
## Type Parameters
### TextAttributes
`TextAttributes` *extends* `BaseTextAttributes` = `BaseTextAttributes`
## Constructors
### Constructor
> **new Text**\<`TextAttributes`\>(`input?`): `Text`\<`TextAttributes`\>
#### Parameters
##### input?
`string` \| `YText` \| `DeltaInsert`\<`TextAttributes`\>[]
The input can be a string, a Y.Text instance, or an array of DeltaInsert.
#### Returns
`Text`\<`TextAttributes`\>
## Accessors
### deltas$
#### Get Signature
> **get** **deltas$**(): `Signal`\<`DeltaOperation`[]\>
Get the text delta as a signal.
##### Returns
`Signal`\<`DeltaOperation`[]\>
## Methods
### applyDelta()
> **applyDelta**(`delta`): `void`
Apply a delta to the text.
#### Parameters
##### delta
`DeltaOperation`[]
The delta to apply.
#### Returns
`void`
#### Example
```ts
const text = new Text('Hello, world!');
text.applyDelta([{insert: ' blocksuite', attributes: { bold: true }}]);
```
***
### clear()
> **clear**(): `void`
Clear the text content.
#### Returns
`void`
***
### clone()
> **clone**(): `Text`\<\{ `bold?`: `true` \| `null`; `code?`: `true` \| `null`; `italic?`: `true` \| `null`; `link?`: `string` \| `null`; `strike?`: `true` \| `null`; `underline?`: `true` \| `null`; \}\>
Clone the text to a new Text instance.
#### Returns
`Text`\<\{ `bold?`: `true` \| `null`; `code?`: `true` \| `null`; `italic?`: `true` \| `null`; `link?`: `string` \| `null`; `strike?`: `true` \| `null`; `underline?`: `true` \| `null`; \}\>
A new Text instance.
***
### delete()
> **delete**(`index`, `length`): `void`
Delete the text content.
#### Parameters
##### index
`number`
The index to delete.
##### length
`number`
The length to delete.
#### Returns
`void`
***
### format()
> **format**(`index`, `length`, `format`): `void`
Format the text content.
#### Parameters
##### index
`number`
The index to format.
##### length
`number`
The length to format.
##### format
`Record`\<`string`, `unknown`\>
The format to apply.
#### Returns
`void`
#### Example
```ts
const text = new Text('Hello, world!');
text.format(7, 1, { bold: true });
```
***
### insert()
> **insert**(`content`, `index`, `attributes?`): `void`
Insert content at the specified index.
#### Parameters
##### content
`string`
The content to insert.
##### index
`number`
The index to insert.
##### attributes?
`Record`\<`string`, `unknown`\>
#### Returns
`void`
#### Example
```ts
const text = new Text('Hello, world!');
text.insert(' blocksuite', 7);
```
***
### join()
> **join**(`other`): `void`
Join current text with another text.
#### Parameters
##### other
`Text`
The other text to join.
#### Returns
`void`
#### Example
```ts
const text = new Text('Hello, world!');
const other = new Text(' blocksuite');
text.join(other);
```
***
### replace()
> **replace**(`index`, `length`, `content`, `attributes?`): `void`
Replace the text content with a new content.
#### Parameters
##### index
`number`
The index to replace.
##### length
`number`
The length to replace.
##### content
`string`
The content to replace.
##### attributes?
`Record`\<`string`, `unknown`\>
The attributes to replace.
#### Returns
`void`
#### Example
```ts
const text = new Text('Hello, world!');
text.replace(7, 1, ' blocksuite');
```
***
### sliceToDelta()
> **sliceToDelta**(`begin`, `end?`): `DeltaOperation`[]
Slice the text to a delta.
#### Parameters
##### begin
`number`
The begin index.
##### end?
`number`
The end index.
#### Returns
`DeltaOperation`[]
The delta of the sliced text.
***
### split()
> **split**(`index`, `length?`): `Text`
Split the text into another Text.
#### Parameters
##### index
`number`
The index to split.
##### length?
`number` = `0`
The length to split.
#### Returns
`Text`
The right part of the text.
#### Example
```ts
const text = new Text('Hello, world!');
text.split(7, 1);
```
NOTE: The string included in [index, index + length) will be deleted.
Here are three cases for point position(index + length):
```
[{insert: 'abc', ...}, {insert: 'def', ...}, {insert: 'ghi', ...}]
1. abc|de|fghi
left: [{insert: 'abc', ...}]
right: [{insert: 'f', ...}, {insert: 'ghi', ...}]
2. abc|def|ghi
left: [{insert: 'abc', ...}]
right: [{insert: 'ghi', ...}]
3. abc|defg|hi
left: [{insert: 'abc', ...}]
right: [{insert: 'hi', ...}]
```
***
### toDelta()
> **toDelta**(): `DeltaOperation`[]
Get the text delta.
#### Returns
`DeltaOperation`[]
The delta of the text.
***
### toString()
> **toString**(): `string`
Get the text content as a string.
In most cases, you should not use this method. It will lose the delta attributes information.
#### Returns
`string`
The text content.