@hocuspocus/provider 2.13.6 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hocuspocus-provider.cjs +116 -15
- package/dist/hocuspocus-provider.cjs.map +1 -1
- package/dist/hocuspocus-provider.esm.js +116 -15
- package/dist/hocuspocus-provider.esm.js.map +1 -1
- package/dist/packages/extension-redis/src/Redis.d.ts +6 -0
- package/dist/packages/provider/src/HocuspocusProvider.d.ts +2 -0
- package/dist/packages/provider/src/TiptapCollabProvider.d.ts +93 -6
- package/dist/packages/provider/src/types.d.ts +14 -2
- package/package.json +2 -2
- package/src/HocuspocusProvider.ts +8 -4
- package/src/TiptapCollabProvider.ts +122 -11
- package/src/types.ts +16 -2
|
@@ -2475,6 +2475,8 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2475
2475
|
forceSync: null,
|
|
2476
2476
|
};
|
|
2477
2477
|
this.isConnected = true;
|
|
2478
|
+
this.boundDocumentUpdateHandler = this.documentUpdateHandler.bind(this);
|
|
2479
|
+
this.boundAwarenessUpdateHandler = this.awarenessUpdateHandler.bind(this);
|
|
2478
2480
|
this.boundBroadcastChannelSubscriber = this.broadcastChannelSubscriber.bind(this);
|
|
2479
2481
|
this.boundPageHide = this.pageHide.bind(this);
|
|
2480
2482
|
this.boundOnOpen = this.onOpen.bind(this);
|
|
@@ -2516,8 +2518,8 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2516
2518
|
(_b = this.awareness) === null || _b === void 0 ? void 0 : _b.on('change', () => {
|
|
2517
2519
|
this.emit('awarenessChange', { states: common.awarenessStatesToArray(this.awareness.getStates()) });
|
|
2518
2520
|
});
|
|
2519
|
-
this.document.on('update', this.
|
|
2520
|
-
(_c = this.awareness) === null || _c === void 0 ? void 0 : _c.on('update', this.
|
|
2521
|
+
this.document.on('update', this.boundDocumentUpdateHandler);
|
|
2522
|
+
(_c = this.awareness) === null || _c === void 0 ? void 0 : _c.on('update', this.boundAwarenessUpdateHandler);
|
|
2521
2523
|
this.registerEventListeners();
|
|
2522
2524
|
if (this.configuration.forceSyncInterval
|
|
2523
2525
|
&& typeof this.configuration.forceSyncInterval === 'number') {
|
|
@@ -2708,10 +2710,10 @@ class HocuspocusProvider extends EventEmitter {
|
|
|
2708
2710
|
}
|
|
2709
2711
|
if (this.awareness) {
|
|
2710
2712
|
removeAwarenessStates(this.awareness, [this.document.clientID], 'provider destroy');
|
|
2711
|
-
this.awareness.off('update', this.
|
|
2713
|
+
this.awareness.off('update', this.boundAwarenessUpdateHandler);
|
|
2712
2714
|
this.awareness.destroy();
|
|
2713
2715
|
}
|
|
2714
|
-
this.document.off('update', this.
|
|
2716
|
+
this.document.off('update', this.boundDocumentUpdateHandler);
|
|
2715
2717
|
this.removeAllListeners();
|
|
2716
2718
|
this.configuration.websocketProvider.off('connect', this.configuration.onConnect);
|
|
2717
2719
|
this.configuration.websocketProvider.off('connect', this.forwardConnect);
|
|
@@ -2842,6 +2844,10 @@ class TiptapCollabProviderWebsocket extends HocuspocusProviderWebsocket {
|
|
|
2842
2844
|
}
|
|
2843
2845
|
}
|
|
2844
2846
|
|
|
2847
|
+
const defaultDeleteCommentOptions = {
|
|
2848
|
+
deleteContent: false,
|
|
2849
|
+
deleteThread: false,
|
|
2850
|
+
};
|
|
2845
2851
|
class TiptapCollabProvider extends HocuspocusProvider {
|
|
2846
2852
|
constructor(configuration) {
|
|
2847
2853
|
if (!configuration.websocketProvider) {
|
|
@@ -2898,12 +2904,25 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2898
2904
|
disableAutoVersioning() {
|
|
2899
2905
|
return this.configuration.document.getMap(`${this.tiptapCollabConfigurationPrefix}config`).set('autoVersioning', 0);
|
|
2900
2906
|
}
|
|
2907
|
+
/**
|
|
2908
|
+
* Returns all users in the document as Y.Map objects
|
|
2909
|
+
* @returns An array of Y.Map objects
|
|
2910
|
+
*/
|
|
2901
2911
|
getYThreads() {
|
|
2902
2912
|
return this.configuration.document.getArray(`${this.tiptapCollabConfigurationPrefix}threads`);
|
|
2903
2913
|
}
|
|
2914
|
+
/**
|
|
2915
|
+
* Finds all threads in the document and returns them as JSON objects
|
|
2916
|
+
* @returns An array of threads as JSON objects
|
|
2917
|
+
*/
|
|
2904
2918
|
getThreads() {
|
|
2905
2919
|
return this.getYThreads().toJSON();
|
|
2906
2920
|
}
|
|
2921
|
+
/**
|
|
2922
|
+
* Find the index of a thread by its id
|
|
2923
|
+
* @param id The thread id
|
|
2924
|
+
* @returns The index of the thread or null if not found
|
|
2925
|
+
*/
|
|
2907
2926
|
getThreadIndex(id) {
|
|
2908
2927
|
let index = null;
|
|
2909
2928
|
let i = 0;
|
|
@@ -2917,6 +2936,11 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2917
2936
|
}
|
|
2918
2937
|
return index;
|
|
2919
2938
|
}
|
|
2939
|
+
/**
|
|
2940
|
+
* Gets a single thread by its id
|
|
2941
|
+
* @param id The thread id
|
|
2942
|
+
* @returns The thread as a JSON object or null if not found
|
|
2943
|
+
*/
|
|
2920
2944
|
getThread(id) {
|
|
2921
2945
|
const index = this.getThreadIndex(id);
|
|
2922
2946
|
if (index === null) {
|
|
@@ -2924,6 +2948,11 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2924
2948
|
}
|
|
2925
2949
|
return this.getYThreads().get(index).toJSON();
|
|
2926
2950
|
}
|
|
2951
|
+
/**
|
|
2952
|
+
* Gets a single thread by its id as a Y.Map object
|
|
2953
|
+
* @param id The thread id
|
|
2954
|
+
* @returns The thread as a Y.Map object or null if not found
|
|
2955
|
+
*/
|
|
2927
2956
|
getYThread(id) {
|
|
2928
2957
|
const index = this.getThreadIndex(id);
|
|
2929
2958
|
if (index === null) {
|
|
@@ -2931,6 +2960,11 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2931
2960
|
}
|
|
2932
2961
|
return this.getYThreads().get(index);
|
|
2933
2962
|
}
|
|
2963
|
+
/**
|
|
2964
|
+
* Create a new thread
|
|
2965
|
+
* @param data The thread data
|
|
2966
|
+
* @returns The created thread
|
|
2967
|
+
*/
|
|
2934
2968
|
createThread(data) {
|
|
2935
2969
|
let createdThread = {};
|
|
2936
2970
|
this.document.transact(() => {
|
|
@@ -2938,11 +2972,18 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2938
2972
|
thread.set('id', uuidv4());
|
|
2939
2973
|
thread.set('createdAt', (new Date()).toISOString());
|
|
2940
2974
|
thread.set('comments', new Y__namespace.Array());
|
|
2975
|
+
thread.set('deletedComments', new Y__namespace.Array());
|
|
2941
2976
|
this.getYThreads().push([thread]);
|
|
2942
2977
|
createdThread = this.updateThread(String(thread.get('id')), data);
|
|
2943
2978
|
});
|
|
2944
2979
|
return createdThread;
|
|
2945
2980
|
}
|
|
2981
|
+
/**
|
|
2982
|
+
* Update a specific thread
|
|
2983
|
+
* @param id The thread id
|
|
2984
|
+
* @param data New data for the thread
|
|
2985
|
+
* @returns The updated thread or null if the thread is not found
|
|
2986
|
+
*/
|
|
2946
2987
|
updateThread(id, data) {
|
|
2947
2988
|
let updatedThread = {};
|
|
2948
2989
|
this.document.transact(() => {
|
|
@@ -2961,6 +3002,11 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2961
3002
|
});
|
|
2962
3003
|
return updatedThread;
|
|
2963
3004
|
}
|
|
3005
|
+
/**
|
|
3006
|
+
* Delete a specific thread and all its comments
|
|
3007
|
+
* @param id The thread id
|
|
3008
|
+
* @returns void
|
|
3009
|
+
*/
|
|
2964
3010
|
deleteThread(id) {
|
|
2965
3011
|
const index = this.getThreadIndex(id);
|
|
2966
3012
|
if (index === null) {
|
|
@@ -2968,22 +3014,46 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2968
3014
|
}
|
|
2969
3015
|
this.getYThreads().delete(index, 1);
|
|
2970
3016
|
}
|
|
2971
|
-
|
|
2972
|
-
|
|
3017
|
+
/**
|
|
3018
|
+
* Returns comments from a thread, either deleted or not
|
|
3019
|
+
* @param threadId The thread id
|
|
3020
|
+
* @param includeDeleted If you want to include deleted comments, defaults to `false`
|
|
3021
|
+
* @returns The comments or null if the thread is not found
|
|
3022
|
+
*/
|
|
3023
|
+
getThreadComments(threadId, includeDeleted) {
|
|
3024
|
+
var _a, _b, _c;
|
|
2973
3025
|
const index = this.getThreadIndex(threadId);
|
|
2974
3026
|
if (index === null) {
|
|
2975
3027
|
return null;
|
|
2976
3028
|
}
|
|
2977
|
-
|
|
3029
|
+
const comments = !includeDeleted ? (_a = this.getThread(threadId)) === null || _a === void 0 ? void 0 : _a.comments : [...(((_b = this.getThread(threadId)) === null || _b === void 0 ? void 0 : _b.comments) || []), ...(((_c = this.getThread(threadId)) === null || _c === void 0 ? void 0 : _c.deletedComments) || [])].sort((a, b) => {
|
|
3030
|
+
return a.createdAt.localeCompare(b.createdAt);
|
|
3031
|
+
});
|
|
3032
|
+
return comments !== null && comments !== void 0 ? comments : [];
|
|
2978
3033
|
}
|
|
2979
|
-
|
|
2980
|
-
|
|
3034
|
+
/**
|
|
3035
|
+
* Get a single comment from a specific thread
|
|
3036
|
+
* @param threadId The thread id
|
|
3037
|
+
* @param commentId The comment id
|
|
3038
|
+
* @param includeDeleted If you want to include deleted comments in the search
|
|
3039
|
+
* @returns The comment or null if not found
|
|
3040
|
+
*/
|
|
3041
|
+
getThreadComment(threadId, commentId, includeDeleted) {
|
|
3042
|
+
var _a;
|
|
2981
3043
|
const index = this.getThreadIndex(threadId);
|
|
2982
3044
|
if (index === null) {
|
|
2983
3045
|
return null;
|
|
2984
3046
|
}
|
|
2985
|
-
|
|
3047
|
+
const comments = this.getThreadComments(threadId, includeDeleted);
|
|
3048
|
+
return (_a = comments === null || comments === void 0 ? void 0 : comments.find(comment => comment.id === commentId)) !== null && _a !== void 0 ? _a : null;
|
|
2986
3049
|
}
|
|
3050
|
+
/**
|
|
3051
|
+
* Adds a comment to a thread
|
|
3052
|
+
* @param threadId The thread id
|
|
3053
|
+
* @param data The comment data
|
|
3054
|
+
* @returns The updated thread or null if the thread is not found
|
|
3055
|
+
* @example addComment('123', { content: 'Hello world', data: { author: 'Maria Doe' } })
|
|
3056
|
+
*/
|
|
2987
3057
|
addComment(threadId, data) {
|
|
2988
3058
|
let updatedThread = {};
|
|
2989
3059
|
this.document.transact(() => {
|
|
@@ -2999,6 +3069,14 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
2999
3069
|
});
|
|
3000
3070
|
return updatedThread;
|
|
3001
3071
|
}
|
|
3072
|
+
/**
|
|
3073
|
+
* Update a comment in a thread
|
|
3074
|
+
* @param threadId The thread id
|
|
3075
|
+
* @param commentId The comment id
|
|
3076
|
+
* @param data The new comment data
|
|
3077
|
+
* @returns The updated thread or null if the thread or comment is not found
|
|
3078
|
+
* @example updateComment('123', { content: 'The new content', data: { attachments: ['file1.jpg'] }})
|
|
3079
|
+
*/
|
|
3002
3080
|
updateComment(threadId, commentId, data) {
|
|
3003
3081
|
let updatedThread = {};
|
|
3004
3082
|
this.document.transact(() => {
|
|
@@ -3026,7 +3104,15 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
3026
3104
|
});
|
|
3027
3105
|
return updatedThread;
|
|
3028
3106
|
}
|
|
3029
|
-
|
|
3107
|
+
/**
|
|
3108
|
+
* Deletes a comment from a thread
|
|
3109
|
+
* @param threadId The thread id
|
|
3110
|
+
* @param commentId The comment id
|
|
3111
|
+
* @param options A set of options that control how the comment is deleted
|
|
3112
|
+
* @returns The updated thread or null if the thread or comment is not found
|
|
3113
|
+
*/
|
|
3114
|
+
deleteComment(threadId, commentId, options) {
|
|
3115
|
+
const { deleteContent, deleteThread } = { ...defaultDeleteCommentOptions, ...options };
|
|
3030
3116
|
const thread = this.getYThread(threadId);
|
|
3031
3117
|
if (thread === null)
|
|
3032
3118
|
return null;
|
|
@@ -3040,18 +3126,33 @@ class TiptapCollabProvider extends HocuspocusProvider {
|
|
|
3040
3126
|
}
|
|
3041
3127
|
// if the first comment of a thread is deleted we also
|
|
3042
3128
|
// delete the thread itself as the source comment is gone
|
|
3043
|
-
if (commentIndex === 0) {
|
|
3129
|
+
if (commentIndex === 0 && (deleteThread || this.configuration.deleteThreadOnFirstCommentDelete)) {
|
|
3044
3130
|
this.deleteThread(threadId);
|
|
3045
3131
|
return;
|
|
3046
3132
|
}
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3133
|
+
const comment = thread.get('comments').get(commentIndex);
|
|
3134
|
+
const newComment = new Y__namespace.Map();
|
|
3135
|
+
newComment.set('id', comment.get('id'));
|
|
3136
|
+
newComment.set('createdAt', comment.get('createdAt'));
|
|
3137
|
+
newComment.set('updatedAt', (new Date()).toISOString());
|
|
3138
|
+
newComment.set('deletedAt', (new Date()).toISOString());
|
|
3139
|
+
newComment.set('data', comment.get('data'));
|
|
3140
|
+
newComment.set('content', deleteContent ? null : comment.get('content'));
|
|
3141
|
+
thread.get('deletedComments').push([newComment]);
|
|
3142
|
+
thread.get('comments').delete(commentIndex);
|
|
3050
3143
|
return thread.toJSON();
|
|
3051
3144
|
}
|
|
3145
|
+
/**
|
|
3146
|
+
* Start watching threads for changes
|
|
3147
|
+
* @param callback The callback function to be called when a thread changes
|
|
3148
|
+
*/
|
|
3052
3149
|
watchThreads(callback) {
|
|
3053
3150
|
this.getYThreads().observeDeep(callback);
|
|
3054
3151
|
}
|
|
3152
|
+
/**
|
|
3153
|
+
* Stop watching threads for changes
|
|
3154
|
+
* @param callback The callback function to be removed
|
|
3155
|
+
*/
|
|
3055
3156
|
unwatchThreads(callback) {
|
|
3056
3157
|
this.getYThreads().unobserveDeep(callback);
|
|
3057
3158
|
}
|