or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

document-management.mdevent-system.mdindex.mdposition-tracking.mdshared-data-types.mdsnapshot-system.mdsynchronization.mdtransaction-system.mdundo-redo-system.mdxml-types.md

index.mddocs/

0

# Yjs

1

2

Yjs is a Conflict-free Replicated Data Type (CRDT) framework that enables real-time collaborative editing without conflicts. It provides shared data types that multiple users can edit simultaneously, with automatic synchronization and conflict resolution. Yjs is network-agnostic and supports peer-to-peer synchronization, offline editing, undo/redo functionality, and efficient binary serialization.

3

4

## Package Information

5

6

- **Package Name**: yjs

7

- **Package Type**: npm

8

- **Language**: JavaScript/TypeScript

9

- **Installation**: `npm install yjs`

10

11

## Core Imports

12

13

```typescript

14

import * as Y from "yjs";

15

```

16

17

For individual imports:

18

19

```typescript

20

import { Doc, Array as YArray, Map as YMap, Text as YText } from "yjs";

21

```

22

23

CommonJS:

24

25

```javascript

26

const Y = require("yjs");

27

const { Doc, Array: YArray, Map: YMap, Text: YText } = require("yjs");

28

```

29

30

## Basic Usage

31

32

```typescript

33

import * as Y from "yjs";

34

35

// Create a new document

36

const doc = new Y.Doc();

37

38

// Get shared types

39

const yarray = doc.getArray("my-array");

40

const ymap = doc.getMap("my-map");

41

const ytext = doc.getText("my-text");

42

43

// Use shared types

44

yarray.push(["hello", "world"]);

45

ymap.set("key", "value");

46

ytext.insert(0, "Hello collaborative world!");

47

48

// Observe changes

49

yarray.observe((event) => {

50

console.log("Array changed:", event.changes);

51

});

52

53

// Create updates for synchronization

54

const update = Y.encodeStateAsUpdate(doc);

55

56

// Apply updates from other clients

57

const otherDoc = new Y.Doc();

58

Y.applyUpdate(otherDoc, update);

59

```

60

61

## Architecture

62

63

Yjs is built around several key components:

64

65

- **Document (Doc)**: Central container managing shared types and synchronization state

66

- **Shared Data Types**: Observable CRDT types (YArray, YMap, YText, YXmlElement) for collaborative editing

67

- **Transaction System**: Atomic change batching for consistent updates and event handling

68

- **Position System**: Relative positions that survive concurrent edits and structural changes

69

- **Update System**: Binary serialization and merging for efficient network synchronization

70

- **Snapshot System**: Time-travel functionality for document state at specific points

71

- **Undo/Redo System**: Multi-level undo/redo with scope management and origin tracking

72

73

## Capabilities

74

75

### Document Management

76

77

Core document functionality for creating, managing, and synchronizing collaborative documents.

78

79

```typescript { .api }

80

class Doc {

81

constructor(options?: DocOpts);

82

readonly clientID: number;

83

readonly guid: string;

84

readonly isLoaded: boolean;

85

readonly isSynced: boolean;

86

readonly isDestroyed: boolean;

87

readonly whenLoaded: Promise<Doc>;

88

readonly whenSynced: Promise<void>;

89

readonly subdocs: Set<Doc>;

90

get<Type>(name: string, TypeConstructor?: Type): InstanceType<Type>;

91

getArray<T>(name?: string): YArray<T>;

92

getText(name?: string): YText;

93

getMap<T>(name?: string): YMap<T>;

94

getXmlElement(name?: string): YXmlElement;

95

getXmlFragment(name?: string): YXmlFragment;

96

transact<T>(f: (transaction: Transaction) => T, origin?: any): T;

97

load(): void;

98

getSubdocs(): Set<Doc>;

99

getSubdocGuids(): Set<string>;

100

destroy(): void;

101

toJSON(): any;

102

}

103

104

interface DocOpts {

105

clientID?: number;

106

guid?: string;

107

collectionid?: string | null;

108

gc?: boolean;

109

gcFilter?: (item: Item) => boolean;

110

meta?: any;

111

autoLoad?: boolean;

112

shouldLoad?: boolean;

113

}

114

```

115

116

[Document Management](./document-management.md)

117

118

### Shared Data Types

119

120

Observable CRDT types for different collaborative editing scenarios with automatic conflict resolution.

121

122

```typescript { .api }

123

class YArray<T> {

124

constructor();

125

static from<T>(items: Array<T>): YArray<T>;

126

readonly length: number;

127

insert(index: number, content: Array<T>): void;

128

push(content: Array<T>): void;

129

unshift(content: Array<T>): void;

130

delete(index: number, length?: number): void;

131

get(index: number): T;

132

toArray(): Array<T>;

133

}

134

135

class YMap<T> {

136

constructor(entries?: Iterable<readonly [string, any]>);

137

readonly size: number;

138

set<VAL>(key: string, value: VAL): VAL;

139

get(key: string): T | undefined;

140

has(key: string): boolean;

141

delete(key: string): void;

142

clear(): void;

143

}

144

145

class YText {

146

constructor(string?: string);

147

readonly length: number;

148

insert(index: number, text: string, attributes?: TextAttributes): void;

149

insertEmbed(index: number, embed: Object | AbstractType<any>, attributes?: TextAttributes): void;

150

delete(index: number, length: number): void;

151

format(index: number, length: number, attributes: TextAttributes): void;

152

removeAttribute(attributeName: string): void;

153

setAttribute(attributeName: string, attributeValue: any): void;

154

getAttribute(attributeName: string): any;

155

getAttributes(): {[key: string]: any};

156

toString(): string;

157

}

158

```

159

160

[Shared Data Types](./shared-data-types.md)

161

162

### XML Types

163

164

XML-aware collaborative types for structured document editing with DOM integration.

165

166

```typescript { .api }

167

class YXmlElement<KV = { [key: string]: any }> {

168

constructor(nodeName?: string);

169

readonly nodeName: string;

170

setAttribute<KEY>(attributeName: KEY, attributeValue: KV[KEY]): void;

171

getAttribute<KEY>(attributeName: KEY): KV[KEY] | undefined;

172

hasAttribute(attributeName: string): boolean;

173

toDOM(document?: Document): Element;

174

}

175

176

class YXmlFragment {

177

constructor();

178

readonly length: number;

179

insert(index: number, content: Array<YXmlElement | YXmlText>): void;

180

insertAfter(ref: null | Item | YXmlElement | YXmlText, content: Array<YXmlElement | YXmlText>): void;

181

querySelector(query: string): YXmlElement | YXmlText | YXmlHook | null;

182

querySelectorAll(query: string): Array<YXmlElement | YXmlText | YXmlHook>;

183

createTreeWalker(filter?: (node: AbstractType<any>) => boolean): YXmlTreeWalker;

184

}

185

```

186

187

[XML Types](./xml-types.md)

188

189

### Transaction System

190

191

Atomic change batching for consistent updates and coordinated event handling.

192

193

```typescript { .api }

194

class Transaction {

195

readonly doc: Doc;

196

readonly origin: any;

197

readonly local: boolean;

198

readonly beforeState: Map<number, number>;

199

readonly afterState: Map<number, number>;

200

}

201

202

function transact<T>(doc: Doc, f: (transaction: Transaction) => T, origin?: any): T;

203

```

204

205

[Transaction System](./transaction-system.md)

206

207

### Event System

208

209

Comprehensive event handling for observing changes to shared types with detailed change information.

210

211

```typescript { .api }

212

abstract class YEvent<T> {

213

readonly target: T;

214

readonly transaction: Transaction;

215

readonly path: Array<string | number>;

216

readonly changes: {

217

added: Set<Item>;

218

deleted: Set<Item>;

219

keys: Map<string, any>;

220

delta: Array<any>;

221

};

222

}

223

224

interface AbstractType<EventType> {

225

observe(f: (event: EventType, transaction: Transaction) => void): void;

226

unobserve(f: (event: EventType, transaction: Transaction) => void): void;

227

observeDeep(f: (events: Array<YEvent<any>>, transaction: Transaction) => void): void;

228

}

229

```

230

231

[Event System](./event-system.md)

232

233

### Position Tracking

234

235

Position system that maintains references across concurrent edits and structural changes.

236

237

```typescript { .api }

238

class RelativePosition {

239

readonly type: ID | null;

240

readonly tname: string | null;

241

readonly item: ID | null;

242

readonly assoc: number;

243

}

244

245

class AbsolutePosition {

246

readonly type: AbstractType<any>;

247

readonly index: number;

248

readonly assoc: number;

249

}

250

251

function createRelativePositionFromTypeIndex(

252

type: AbstractType<any>,

253

index: number,

254

assoc?: number

255

): RelativePosition;

256

257

function createAbsolutePositionFromRelativePosition(

258

rpos: RelativePosition,

259

doc: Doc

260

): AbsolutePosition | null;

261

262

function createRelativePositionFromJSON(json: any): RelativePosition;

263

function encodeRelativePosition(rpos: RelativePosition): Uint8Array;

264

function decodeRelativePosition(encoded: Uint8Array): RelativePosition;

265

function relativePositionToJSON(rpos: RelativePosition): any;

266

function compareRelativePositions(a: RelativePosition, b: RelativePosition): number;

267

```

268

269

[Position Tracking](./position-tracking.md)

270

271

### Synchronization

272

273

Binary update system for efficient network synchronization and state management.

274

275

```typescript { .api }

276

function encodeStateAsUpdate(doc: Doc, encodedTargetStateVector?: Uint8Array): Uint8Array;

277

function encodeStateAsUpdateV2(doc: Doc, encodedTargetStateVector?: Uint8Array): Uint8Array;

278

function applyUpdate(doc: Doc, update: Uint8Array, transactionOrigin?: any): void;

279

function applyUpdateV2(doc: Doc, update: Uint8Array, transactionOrigin?: any): void;

280

function mergeUpdates(updates: Array<Uint8Array>): Uint8Array;

281

function mergeUpdatesV2(updates: Array<Uint8Array>): Uint8Array;

282

function readUpdate(decoder: UpdateDecoder, doc: Doc, transactionOrigin?: any): void;

283

function readUpdateV2(decoder: UpdateDecoder, doc: Doc, transactionOrigin?: any): void;

284

function encodeStateVector(doc: Doc): Uint8Array;

285

function decodeStateVector(stateVector: Uint8Array): Map<number, number>;

286

function parseUpdateMeta(update: Uint8Array): { from: Map<number, number>; to: Map<number, number> };

287

function parseUpdateMetaV2(update: Uint8Array): { from: Map<number, number>; to: Map<number, number> };

288

function encodeStateVectorFromUpdate(update: Uint8Array): Uint8Array;

289

function encodeStateVectorFromUpdateV2(update: Uint8Array): Uint8Array;

290

function diffUpdate(update: Uint8Array, stateVector: Uint8Array): Uint8Array;

291

function diffUpdateV2(update: Uint8Array, stateVector: Uint8Array): Uint8Array;

292

function convertUpdateFormatV1ToV2(update: Uint8Array): Uint8Array;

293

function convertUpdateFormatV2ToV1(update: Uint8Array): Uint8Array;

294

function logUpdate(update: Uint8Array): void;

295

function logUpdateV2(update: Uint8Array): void;

296

```

297

298

[Synchronization](./synchronization.md)

299

300

### Snapshot System

301

302

Time-travel functionality for document state at specific points with diff capabilities.

303

304

```typescript { .api }

305

class Snapshot {

306

readonly ds: DeleteSet;

307

readonly sv: Map<number, number>;

308

}

309

310

function snapshot(doc: Doc): Snapshot;

311

function createSnapshot(doc: Doc): Snapshot;

312

function createDocFromSnapshot(originDoc: Doc, snapshot: Snapshot, newDoc?: Doc): Doc;

313

function equalSnapshots(snap1: Snapshot, snap2: Snapshot): boolean;

314

function encodeSnapshot(snapshot: Snapshot): Uint8Array;

315

function decodeSnapshot(encoded: Uint8Array): Snapshot;

316

function encodeSnapshotV2(snapshot: Snapshot): Uint8Array;

317

function decodeSnapshotV2(encoded: Uint8Array): Snapshot;

318

function snapshotContainsUpdate(snapshot: Snapshot, update: Uint8Array): boolean;

319

```

320

321

[Snapshot System](./snapshot-system.md)

322

323

### Undo/Redo System

324

325

Multi-level undo/redo functionality with scope management and origin tracking.

326

327

```typescript { .api }

328

class UndoManager {

329

constructor(

330

typeScope: Doc | AbstractType<any> | Array<AbstractType<any>>,

331

options?: UndoManagerOptions

332

);

333

readonly undoStack: Array<StackItem>;

334

readonly redoStack: Array<StackItem>;

335

undo(): StackItem | null;

336

redo(): StackItem | null;

337

canUndo(): boolean;

338

canRedo(): boolean;

339

clear(clearUndoStack?: boolean, clearRedoStack?: boolean): void;

340

}

341

342

interface UndoManagerOptions {

343

captureTimeout?: number;

344

captureTransaction?: (transaction: Transaction) => boolean;

345

deleteFilter?: (item: Item) => boolean;

346

trackedOrigins?: Set<any>;

347

}

348

```

349

350

[Undo/Redo System](./undo-redo-system.md)

351

352

### Utility Functions

353

354

Essential utility functions for working with Yjs internals and advanced operations.

355

356

```typescript { .api }

357

// Item and structure utilities

358

function getItem(store: StructStore, id: ID): Item;

359

function getItemCleanStart(transaction: Transaction, id: ID): Item;

360

function getItemCleanEnd(transaction: Transaction, id: ID): Item;

361

function isDeleted(deleteSet: DeleteSet, id: ID): boolean;

362

function isParentOf(parent: AbstractType<any>, child: Item): boolean;

363

364

// ID utilities

365

function createID(client: number, clock: number): ID;

366

function compareIDs(a: ID | null, b: ID | null): boolean;

367

function getState(store: StructStore, client: number): number;

368

369

// Delete set utilities

370

function createDeleteSet(): DeleteSet;

371

function createDeleteSetFromStructStore(store: StructStore): DeleteSet;

372

function equalDeleteSets(ds1: DeleteSet, ds2: DeleteSet): boolean;

373

function mergeDeleteSets(deleteSets: Array<DeleteSet>): DeleteSet;

374

375

// Advanced operations

376

function transact<T>(doc: Doc, f: (transaction: Transaction) => T, origin?: any): T;

377

function tryGc(deleteSet: DeleteSet, store: StructStore, gcFilter: Function): void;

378

function cleanupYTextFormatting(type: YText): number;

379

function findRootTypeKey(type: AbstractType<any>): string;

380

function getTypeChildren(type: AbstractType<any>): Array<AbstractType<any>>;

381

```

382

383

## Types

384

385

```typescript { .api }

386

interface ID {

387

readonly client: number;

388

readonly clock: number;

389

}

390

391

interface DeleteSet {

392

readonly clients: Map<number, Array<DeleteItem>>;

393

}

394

395

interface TextAttributes {

396

[key: string]: any;

397

}

398

399

interface UpdateDecoder {

400

readUint8(): number;

401

readUint32(): number;

402

readVarUint(): number;

403

readVarString(): string;

404

}

405

406

interface UpdateEncoder {

407

writeUint8(value: number): void;

408

writeUint32(value: number): void;

409

writeVarUint(value: number): void;

410

writeVarString(value: string): void;

411

toUint8Array(): Uint8Array;

412

}

413

414

interface DeleteItem {

415

clock: number;

416

len: number;

417

}

418

419

interface StructStore {

420

clients: Map<number, Array<AbstractStruct>>;

421

pendingStructs: null | { missing: Map<number, number>; update: Uint8Array };

422

}

423

424

interface Item {

425

readonly id: ID;

426

readonly left: Item | null;

427

readonly right: Item | null;

428

readonly origin: ID | null;

429

readonly rightOrigin: ID | null;

430

readonly parent: AbstractType<any> | ID | null;

431

readonly parentSub: string | null;

432

readonly content: AbstractContent;

433

}

434

435

// Abstract base classes

436

abstract class AbstractType<EventType> {

437

observe(f: (event: EventType, transaction: Transaction) => void): void;

438

unobserve(f: (event: EventType, transaction: Transaction) => void): void;

439

observeDeep(f: (events: Array<YEvent<any>>, transaction: Transaction) => void): void;

440

clone(): AbstractType<EventType>;

441

toJSON(): any;

442

}

443

444

abstract class AbstractStruct {

445

readonly id: ID;

446

readonly length: number;

447

}

448

449

class YXmlTreeWalker {

450

filter: (node: AbstractType<any>) => boolean;

451

nextNode(): AbstractType<any> | null;

452

}

453

```