Skip to content

Commit f2bf387

Browse files
committed
Support document forking
1 parent 925b257 commit f2bf387

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

javascript/src/api.ts

Lines changed: 43 additions & 1 deletion
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
import * as Y from 'yjs';
2626

@@ -81,6 +81,26 @@ export interface ISharedBase extends IObservableDisposable {
8181
transact(f: () => void, undoable?: boolean, origin?: any): void;
8282
}
8383

84+
/**
85+
* An interface for a document provider.
86+
*/
87+
export interface IDocumentProvider extends IDisposable {
88+
/**
89+
* Returns a Promise that resolves when the document provider is ready.
90+
*/
91+
readonly ready: Promise<void>;
92+
93+
/**
94+
* Request to fork the room in the backend, and connect the shared document to the forked room.
95+
*/
96+
fork(): Promise<void>;
97+
98+
/**
99+
* Connect a shared document to a forked room with forkId and return a document provider.
100+
*/
101+
connectFork(forkId: string, sharedDocument: ISharedDocument): IDocumentProvider;
102+
}
103+
84104
/**
85105
* Implement an API for Context information on the shared information.
86106
* This is used by, for example, docregistry to share the file-path of the edited content.
@@ -115,6 +135,28 @@ export interface ISharedDocument extends ISharedBase {
115135
* The changed signal.
116136
*/
117137
readonly changed: ISignal<this, DocumentChange>;
138+
139+
/**
140+
* Get a provider with a given ID
141+
*
142+
* @param providerId The provider ID
143+
*/
144+
getProvider(providerId: string, sharedModel?: ISharedDocument): IDocumentProvider;
145+
146+
/**
147+
* Set a provider for this document
148+
*
149+
* @param providerId Provider ID (either 'root' or a UUID)
150+
* @param provider The document provider
151+
*/
152+
setProvider(providerId: string, provider: IDocumentProvider): void;
153+
154+
/**
155+
* Add a fork ID to the document's ystate, as a new key 'fork_{forkId}'
156+
*
157+
* @param forkId The fork ID to add to the document
158+
*/
159+
addFork(forkId: string): void;
118160
}
119161

120162
/**

javascript/src/ydocument.ts

Lines changed: 26 additions & 1 deletion
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)