Skip to content

Commit 83681d6

Browse files
committed
Support document forking
1 parent 803631d commit 83681d6

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

javascript/src/api.ts

+43-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,26 @@ 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+
/**
93+
* Request to fork the room in the backend, and connect the shared document to the forked room.
94+
*/
95+
fork(): Promise<void>;
96+
97+
/**
98+
* Connect a shared document to a forked room with forkId and return a document provider.
99+
*/
100+
connectFork(forkId: string, sharedDocument: ISharedDocument): IDocumentProvider;
101+
}
102+
83103
/**
84104
* Implement an API for Context information on the shared information.
85105
* This is used by, for example, docregistry to share the file-path of the edited content.
@@ -114,6 +134,28 @@ export interface ISharedDocument extends ISharedBase {
114134
* The changed signal.
115135
*/
116136
readonly changed: ISignal<this, DocumentChange>;
137+
138+
/**
139+
* Get a provider with a given ID
140+
*
141+
* @param providerId The provider ID
142+
*/
143+
getProvider(providerId: string, sharedModel?: ISharedDocument): IDocumentProvider;
144+
145+
/**
146+
* Set a provider for this document
147+
*
148+
* @param providerId Provider ID (either 'root' or a UUID)
149+
* @param provider The document provider
150+
*/
151+
setProvider(providerId: string, provider: IDocumentProvider): void;
152+
153+
/**
154+
* Add a fork ID to the document's ystate, as a new key 'fork_{forkId}'
155+
*
156+
* @param forkId The fork ID to add to the document
157+
*/
158+
addFork(forkId: string): void;
117159
}
118160

119161
/**

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)