or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection-management.mddatabase-operations.mdextensions.mdindex.mdinstance-management.mdshared-types.md

extensions.mddocs/

0

# Extensions

1

2

Framework for creating custom connectors, databases, and shared types to extend Yjs functionality beyond the built-in modules.

3

4

## Capabilities

5

6

### Module Extension System

7

8

Add external modules to extend Yjs functionality before creating instances.

9

10

```javascript { .api }

11

/**

12

* Extend Yjs with additional modules

13

* Must be called before creating instances that use the modules

14

* @param {...any} modules - Connector, database, or type modules to add

15

*/

16

Y.extend(...modules);

17

```

18

19

**Usage Examples:**

20

21

```javascript

22

// Node.js - Manual module loading

23

const Y = require('yjs');

24

25

// Load required modules

26

Y.extend(

27

require('y-memory'), // Memory database

28

require('y-array'), // Array shared type

29

require('y-map'), // Map shared type

30

require('y-text'), // Text shared type

31

require('y-websockets-client') // WebSocket connector

32

);

33

34

// Now create instance with loaded modules

35

Y({

36

db: { name: 'memory' },

37

connector: { name: 'websockets-client', room: 'test' },

38

share: { doc: 'Text', list: 'Array' }

39

}).then(function(y) {

40

console.log('Yjs ready with extended modules');

41

});

42

43

// Browser - Conditional module loading

44

if (typeof window !== 'undefined') {

45

// Browser environment - modules loaded automatically

46

Y({

47

sourceDir: '/bower_components',

48

type: ['Array', 'Map', 'Text', 'WebSocketsClient', 'Memory'],

49

db: { name: 'memory' },

50

connector: { name: 'websockets-client', room: 'browser-test' },

51

share: { content: 'Text' }

52

});

53

} else {

54

// Node.js environment - manual loading required

55

Y.extend(require('y-memory'), require('y-text'));

56

}

57

```

58

59

### Abstract Base Classes

60

61

Base classes for implementing custom connectors and database adapters.

62

63

```javascript { .api }

64

/**

65

* Abstract base class for custom connectors

66

* Implement communication protocols for peer synchronization

67

*/

68

class Y.AbstractConnector {

69

constructor(y, options);

70

71

/**

72

* Send message to connected peers

73

* @param {ArrayBuffer} message - Binary message to send

74

*/

75

send(message);

76

77

/**

78

* Handle received message from peer

79

* @param {ArrayBuffer} message - Binary message received

80

*/

81

onMessage(message);

82

83

/**

84

* Connect to peers

85

*/

86

connect();

87

88

/**

89

* Disconnect from peers

90

*/

91

disconnect();

92

93

/**

94

* Check if connected to any peers

95

* @returns {boolean} Connection status

96

*/

97

isConnected();

98

}

99

100

/**

101

* Abstract base class for custom database adapters

102

* Implement persistence and transaction management

103

*/

104

class Y.AbstractDatabase {

105

constructor(y, options);

106

107

/**

108

* Store operation in database

109

* @param {Operation} op - Operation to store

110

*/

111

storeOperation(op);

112

113

/**

114

* Retrieve operations from database

115

* @param {any} criteria - Search criteria

116

* @returns {Operation[]} Matching operations

117

*/

118

getOperations(criteria);

119

120

/**

121

* Delete operations from database

122

* @param {any} criteria - Deletion criteria

123

*/

124

deleteOperations(criteria);

125

126

/**

127

* Start garbage collection

128

*/

129

startGarbageCollector();

130

131

/**

132

* Stop garbage collection

133

*/

134

stopGarbageCollector();

135

}

136

```

137

138

**Usage Examples:**

139

140

```javascript

141

// Custom WebSocket connector implementation

142

class CustomWebSocketConnector extends Y.AbstractConnector {

143

constructor(y, options) {

144

super(y, options);

145

this.url = options.url;

146

this.room = options.room;

147

this.ws = null;

148

this.connected = false;

149

}

150

151

connect() {

152

this.ws = new WebSocket(this.url);

153

154

this.ws.onopen = () => {

155

this.connected = true;

156

this.ws.send(JSON.stringify({

157

type: 'join',

158

room: this.room

159

}));

160

};

161

162

this.ws.onmessage = (event) => {

163

const data = JSON.parse(event.data);

164

if (data.type === 'sync') {

165

this.onMessage(data.message);

166

}

167

};

168

169

this.ws.onclose = () => {

170

this.connected = false;

171

};

172

}

173

174

send(message) {

175

if (this.connected) {

176

this.ws.send(JSON.stringify({

177

type: 'sync',

178

room: this.room,

179

message: message

180

}));

181

}

182

}

183

184

disconnect() {

185

if (this.ws) {

186

this.ws.close();

187

this.connected = false;

188

}

189

}

190

191

isConnected() {

192

return this.connected;

193

}

194

}

195

196

// Register custom connector

197

Y.extend({

198

name: 'custom-websocket',

199

connector: CustomWebSocketConnector

200

});

201

202

// Use custom connector

203

Y({

204

db: { name: 'memory' },

205

connector: {

206

name: 'custom-websocket',

207

url: 'ws://custom-server.com:8080',

208

room: 'custom-room'

209

},

210

share: { doc: 'Text' }

211

});

212

```

213

214

### Utility Classes and Functions

215

216

Helper utilities for building extensions and custom functionality.

217

218

```javascript { .api }

219

/**

220

* Utility functions and classes namespace

221

*/

222

Y.utils: {

223

/**

224

* Event listener handler for managing DOM events

225

*/

226

EventListenerHandler: Function,

227

228

/**

229

* Extended event handling with custom event types

230

*/

231

EventHandler: Function,

232

233

/**

234

* Base class for custom shared types

235

*/

236

CustomType: Function,

237

238

/**

239

* Type definition utilities for custom types

240

*/

241

CustomTypeDefinition: Function,

242

243

/**

244

* Deep copy utility for objects

245

* @param {any} obj - Object to copy

246

* @returns {any} Deep copy of object

247

*/

248

copyObject: Function,

249

250

/**

251

* Copy operation data structures

252

* @param {Operation} op - Operation to copy

253

* @returns {Operation} Copy of operation

254

*/

255

copyOperation: Function,

256

257

/**

258

* Compare operation IDs for ordering

259

* @param {ID} id1 - First ID

260

* @param {ID} id2 - Second ID

261

* @returns {number} Comparison result

262

*/

263

compareIds: Function,

264

265

/**

266

* Generate unique identifier

267

* @returns {string} Unique GUID

268

*/

269

generateGuid: Function

270

};

271

```

272

273

**Usage Examples:**

274

275

```javascript

276

// Custom shared type using utilities

277

class CustomCounter extends Y.utils.CustomType {

278

constructor() {

279

super();

280

this.value = 0;

281

this.eventHandler = new Y.utils.EventHandler();

282

}

283

284

increment() {

285

this.value++;

286

this.eventHandler.callEventListeners('change', [{

287

type: 'increment',

288

newValue: this.value,

289

id: Y.utils.generateGuid()

290

}]);

291

}

292

293

decrement() {

294

this.value--;

295

this.eventHandler.callEventListeners('change', [{

296

type: 'decrement',

297

newValue: this.value,

298

id: Y.utils.generateGuid()

299

}]);

300

}

301

302

observe(callback) {

303

this.eventHandler.addEventListener('change', callback);

304

}

305

306

getValue() {

307

return this.value;

308

}

309

}

310

311

// Register custom type

312

Y.extend({

313

name: 'Counter',

314

type: CustomCounter

315

});

316

317

// Use custom type

318

Y({

319

db: { name: 'memory' },

320

connector: { name: 'test', room: 'counter-test' },

321

share: { counter: 'Counter' }

322

}).then(function(y) {

323

const counter = y.share.counter;

324

325

counter.observe(function(event) {

326

console.log('Counter changed:', event);

327

});

328

329

counter.increment(); // Triggers change event

330

console.log('Current value:', counter.getValue());

331

});

332

333

// Advanced utilities usage

334

function createAdvancedExtension() {

335

// Use object copying for state management

336

const baseState = { version: 1, features: ['sync', 'offline'] };

337

const customState = Y.utils.copyObject(baseState);

338

customState.features.push('custom-extension');

339

340

// Generate unique IDs for operations

341

const operationId = Y.utils.generateGuid();

342

343

return {

344

name: 'advanced-extension',

345

state: customState,

346

operationId: operationId,

347

348

compare: function(id1, id2) {

349

return Y.utils.compareIds(id1, id2);

350

}

351

};

352

}

353

354

Y.extend(createAdvancedExtension());

355

```

356

357

### External Module Ecosystem

358

359

Overview of available external modules that can be loaded with Y.extend().

360

361

#### Connector Modules

362

363

```javascript { .api }

364

// Available connector modules (require separate installation)

365

const connectorModules = {

366

'y-webrtc': 'Browser-to-browser peer-to-peer via WebRTC',

367

'y-websockets-client': 'WebSocket client connector',

368

'y-xmpp': 'XMPP multi-user chat rooms',

369

'y-ipfs': 'IPFS distributed network connector',

370

'y-test': 'Testing connector for development'

371

};

372

```

373

374

#### Database Modules

375

376

```javascript { .api }

377

// Available database modules (require separate installation)

378

const databaseModules = {

379

'y-memory': 'In-memory storage (no persistence)',

380

'y-indexeddb': 'Browser offline storage',

381

'y-leveldb': 'Node.js persistent storage'

382

};

383

```

384

385

#### Shared Type Modules

386

387

```javascript { .api }

388

// Available shared type modules (require separate installation)

389

const typeModules = {

390

'y-array': 'Collaborative arrays',

391

'y-map': 'Collaborative key-value maps',

392

'y-text': 'Collaborative text with editor bindings',

393

'y-xml': 'Collaborative XML/DOM manipulation',

394

'y-richtext': 'Rich text with Quill editor binding'

395

};

396

```

397

398

### Module Loading Patterns

399

400

#### Node.js Pattern

401

402

```javascript

403

// Explicit require and extend

404

const Y = require('yjs');

405

Y.extend(

406

require('y-memory'),

407

require('y-websockets-client'),

408

require('y-array'),

409

require('y-map')

410

);

411

```

412

413

#### Browser Pattern

414

415

```javascript

416

// Automatic loading via configuration

417

Y({

418

sourceDir: '/bower_components',

419

type: ['Memory', 'WebSocketsClient', 'Array', 'Map'],

420

// ... rest of config

421

});

422

```

423

424

#### Conditional Loading

425

426

```javascript

427

// Environment-specific loading

428

if (typeof require !== 'undefined') {

429

// Node.js

430

Y.extend(require('y-leveldb'));

431

} else {

432

// Browser - will auto-load IndexedDB

433

console.log('Browser environment detected');

434

}

435

```

436

437

### Custom Module Development

438

439

Template for creating new Yjs modules:

440

441

```javascript { .api }

442

// Module template structure

443

const CustomModule = {

444

// Module identification

445

name: 'custom-module',

446

version: '1.0.0',

447

448

// Module type (connector, database, or type)

449

type: 'connector', // or 'database' or 'type'

450

451

// Implementation class

452

implementation: CustomImplementationClass,

453

454

// Optional initialization

455

init: function(Y) {

456

// Setup code when module is loaded

457

},

458

459

// Optional cleanup

460

destroy: function() {

461

// Cleanup code when module is unloaded

462

}

463

};

464

465

// Export for use with Y.extend()

466

module.exports = CustomModule;

467

```