Skip to content

Commit 39c2489

Browse files
committed
Support document forking
1 parent 803631d commit 39c2489

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

javascript/src/api.ts

+36-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import type {
2020
JSONValue,
2121
PartialJSONValue
2222
} from '@lumino/coreutils';
23-
import type { IObservableDisposable } from '@lumino/disposable';
23+
import type { IDisposable, IObservableDisposable } from '@lumino/disposable';
2424
import type { ISignal } from '@lumino/signaling';
2525

2626
/**
@@ -80,6 +80,19 @@ export interface ISharedBase extends IObservableDisposable {
8080
transact(f: () => void, undoable?: boolean): void;
8181
}
8282

83+
/**
84+
* An interface for a document provider.
85+
*/
86+
export interface IDocumentProvider extends IDisposable {
87+
/**
88+
* Returns a Promise that resolves when the document provider is ready.
89+
*/
90+
readonly ready: Promise<void>;
91+
92+
fork(): Promise<void>;
93+
connectFork(providerId: string, sharedDocument: ISharedDocument): IDocumentProvider;
94+
}
95+
8396
/**
8497
* Implement an API for Context information on the shared information.
8598
* This is used by, for example, docregistry to share the file-path of the edited content.
@@ -114,6 +127,28 @@ export interface ISharedDocument extends ISharedBase {
114127
* The changed signal.
115128
*/
116129
readonly changed: ISignal<this, DocumentChange>;
130+
131+
/**
132+
* Get a provider with a given ID
133+
*
134+
* @param providerId The provider ID
135+
*/
136+
getProvider(providerId: string, sharedModel?: ISharedDocument): IDocumentProvider;
137+
138+
/**
139+
* Set a provider for this document
140+
*
141+
* @param providerId Provider ID (either 'root' or a UUID)
142+
* @param provider The document provider
143+
*/
144+
setProvider(providerId: string, provider: IDocumentProvider): void;
145+
146+
/**
147+
* Add a fork ID to the document's ystate, as a new key 'fork_{forkId}'
148+
*
149+
* @param forkId The fork ID to add to the document
150+
*/
151+
addFork(forkId: string): void;
117152
}
118153

119154
/**

javascript/src/ydocument.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { JSONExt, JSONObject, JSONValue } from '@lumino/coreutils';
77
import { ISignal, Signal } from '@lumino/signaling';
88
import { Awareness } from 'y-protocols/awareness';
99
import * as Y from 'yjs';
10-
import type { DocumentChange, ISharedDocument, StateChange } from './api.js';
10+
import type { DocumentChange, IDocumentProvider, ISharedDocument, StateChange } from './api';
1111

1212
/**
1313
* Generic shareable document.
@@ -28,13 +28,37 @@ export abstract class YDocument<T extends DocumentChange>
2828
this._awareness = new Awareness(this._ydoc);
2929

3030
this._ystate.observe(this.onStateChanged);
31+
32+
this._providers = {};
3133
}
3234

3335
/**
3436
* Document version
3537
*/
3638
abstract readonly version: string;
3739

40+
addFork(forkId: string) {
41+
this.ystate.set(`fork_${forkId}`, 'new');
42+
}
43+
44+
getProvider(providerId: string, sharedModel?: ISharedDocument): IDocumentProvider {
45+
if (!(providerId in this._providers)) {
46+
if (providerId === 'root') {
47+
throw new Error('Cannot get a new provider for root document');
48+
}
49+
if (sharedModel === undefined) {
50+
throw new Error('New provider needs a shared document');
51+
}
52+
const root_provider = this._providers['root'];
53+
this._providers[providerId] = root_provider.connectFork(providerId, sharedModel!);
54+
}
55+
return this._providers[providerId];
56+
}
57+
58+
setProvider(providerId: string, provider: IDocumentProvider) {
59+
this._providers[providerId] = provider;
60+
}
61+
3862
/**
3963
* YJS document.
4064
*/
@@ -200,6 +224,7 @@ export abstract class YDocument<T extends DocumentChange>
200224
private _awareness: Awareness;
201225
private _isDisposed = false;
202226
private _disposed = new Signal<this, void>(this);
227+
private _providers: { [key: string]: IDocumentProvider };
203228
}
204229

205230
/**

0 commit comments

Comments
 (0)