@atlaskit/collab-provider 8.8.2 → 8.9.1

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/cjs/analytics/analytics-helper.js +21 -12
  3. package/dist/cjs/channel.js +5 -3
  4. package/dist/cjs/document/document-service.js +1 -1
  5. package/dist/cjs/errors/error-code-mapper.js +9 -2
  6. package/dist/cjs/namespace/namespace-service.js +77 -0
  7. package/dist/cjs/participants/participants-helper.js +2 -0
  8. package/dist/cjs/participants/participants-service.js +94 -30
  9. package/dist/cjs/provider/index.js +91 -173
  10. package/dist/cjs/version-wrapper.js +1 -1
  11. package/dist/cjs/version.json +1 -1
  12. package/dist/es2019/analytics/analytics-helper.js +21 -12
  13. package/dist/es2019/channel.js +5 -3
  14. package/dist/es2019/document/document-service.js +1 -1
  15. package/dist/es2019/errors/error-code-mapper.js +9 -2
  16. package/dist/es2019/namespace/namespace-service.js +48 -0
  17. package/dist/es2019/participants/participants-helper.js +2 -0
  18. package/dist/es2019/participants/participants-service.js +88 -30
  19. package/dist/es2019/provider/index.js +82 -145
  20. package/dist/es2019/version-wrapper.js +1 -1
  21. package/dist/es2019/version.json +1 -1
  22. package/dist/esm/analytics/analytics-helper.js +21 -12
  23. package/dist/esm/channel.js +5 -3
  24. package/dist/esm/document/document-service.js +1 -1
  25. package/dist/esm/errors/error-code-mapper.js +9 -2
  26. package/dist/esm/namespace/namespace-service.js +69 -0
  27. package/dist/esm/participants/participants-helper.js +2 -0
  28. package/dist/esm/participants/participants-service.js +94 -30
  29. package/dist/esm/provider/index.js +91 -173
  30. package/dist/esm/version-wrapper.js +1 -1
  31. package/dist/esm/version.json +1 -1
  32. package/dist/types/namespace/namespace-service.d.ts +14 -0
  33. package/dist/types/participants/participants-helper.d.ts +2 -4
  34. package/dist/types/participants/participants-service.d.ts +40 -16
  35. package/dist/types/provider/index.d.ts +20 -36
  36. package/dist/types/types.d.ts +1 -1
  37. package/dist/types-ts4.5/analytics/analytics-helper.d.ts +11 -0
  38. package/dist/types-ts4.5/analytics/performance.d.ts +15 -0
  39. package/dist/types-ts4.5/analytics/ufo.d.ts +3 -0
  40. package/dist/types-ts4.5/channel.d.ts +47 -0
  41. package/dist/types-ts4.5/config.d.ts +5 -0
  42. package/dist/types-ts4.5/connectivity/network.d.ts +17 -0
  43. package/dist/types-ts4.5/connectivity/reconnect-helper.d.ts +8 -0
  44. package/dist/types-ts4.5/connectivity/singleton.d.ts +3 -0
  45. package/dist/types-ts4.5/disconnected-reason-mapper.d.ts +16 -0
  46. package/dist/types-ts4.5/document/catchup.d.ts +9 -0
  47. package/dist/types-ts4.5/document/document-service.d.ts +86 -0
  48. package/dist/types-ts4.5/document/step-queue-state.d.ts +16 -0
  49. package/dist/types-ts4.5/emitter.d.ts +19 -0
  50. package/dist/types-ts4.5/errors/error-code-mapper.d.ts +2 -0
  51. package/dist/types-ts4.5/errors/error-types.d.ts +443 -0
  52. package/dist/types-ts4.5/feature-flags/__test__/index.unit.d.ts +1 -0
  53. package/dist/types-ts4.5/feature-flags/index.d.ts +9 -0
  54. package/dist/types-ts4.5/feature-flags/types.d.ts +13 -0
  55. package/dist/types-ts4.5/helpers/const.d.ts +183 -0
  56. package/dist/types-ts4.5/helpers/utils.d.ts +5 -0
  57. package/dist/types-ts4.5/index.d.ts +4 -0
  58. package/dist/types-ts4.5/metadata/metadata-service.d.ts +25 -0
  59. package/dist/types-ts4.5/namespace/namespace-service.d.ts +14 -0
  60. package/dist/types-ts4.5/participants/participants-helper.d.ts +12 -0
  61. package/dist/types-ts4.5/participants/participants-service.d.ts +94 -0
  62. package/dist/types-ts4.5/participants/participants-state.d.ts +13 -0
  63. package/dist/types-ts4.5/participants/telepointers-helper.d.ts +4 -0
  64. package/dist/types-ts4.5/provider/commit-step.d.ts +25 -0
  65. package/dist/types-ts4.5/provider/index.d.ts +146 -0
  66. package/dist/types-ts4.5/socket-io-provider.d.ts +5 -0
  67. package/dist/types-ts4.5/types.d.ts +265 -0
  68. package/dist/types-ts4.5/version-wrapper.d.ts +3 -0
  69. package/package.json +3 -3
  70. package/report.api.md +4 -2
@@ -13,7 +13,7 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
13
13
  private isChannelInitialized;
14
14
  private initialDraft?;
15
15
  private isProviderInitialized;
16
- private isNamespaceLocked;
16
+ private isPreinitializing;
17
17
  private sessionId?;
18
18
  private clientId?;
19
19
  private userId?;
@@ -22,7 +22,16 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
22
22
  private readonly participantsService;
23
23
  private readonly metadataService;
24
24
  private readonly documentService;
25
+ private readonly namespaceService;
26
+ /**
27
+ * Wrapper for this.emit, it binds scope for callbacks and waits for initialising of the editor before emitting events.
28
+ * Waiting for the collab provider to become connected to the editor ensures the editor doesn't miss any events.
29
+ * @param evt - Event name to emit to subscribers
30
+ * @param data - Event data to emit to subscribers
31
+ */
25
32
  private readonly emitCallback;
33
+ private getStatePromise;
34
+ getStatePromiseResolve: (value: void | PromiseLike<void>) => void;
26
35
  constructor(config: Config);
27
36
  private initializeChannel;
28
37
  /**
@@ -33,14 +42,19 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
33
42
  */
34
43
  initialize(getState: () => EditorState): this;
35
44
  /**
36
- * Initialisation logic, called by the editor in the collab-edit plugin
37
- * @param {Object} parameters ...
38
- * @param {Function} parameters.getState Function that returns the editor state, used to retrieve collab-edit properties and to interact with prosemirror-collab
39
- * @param {SyncUpErrorFunction} parameters.onSyncUpError (Optional) Function that gets called when the sync of steps fails after retrying 30 times, used by Editor to log to analytics
45
+ * Initialisation logic, called by the editor in the collab-edit plugin.
46
+ *
47
+ * When getState is nullish and a initialDraft is provided the collab provider is in a state of pre-initialization,
48
+ * the provider starts to enable the connection to NCS, but the provider will not emit any events until this function
49
+ * is called again with a getState function, indicating that the editor is loaded and ready to receive the emits.
50
+ *
51
+ * @param {Object} options ...
52
+ * @param {Function} options.getState Function that returns the editor state, used to retrieve collab-edit properties and to interact with prosemirror-collab
53
+ * @param {SyncUpErrorFunction} options.onSyncUpError (Optional) Function that gets called when the sync of steps fails after retrying 30 times, used by Editor to log to analytics
40
54
  * @throws {ProviderInitialisationError} Something went wrong during provider initialisation
41
55
  */
42
56
  setup({ getState, onSyncUpError, }: {
43
- getState: () => EditorState;
57
+ getState?: () => EditorState;
44
58
  onSyncUpError?: SyncUpErrorFunction;
45
59
  }): this;
46
60
  private checkForCookies;
@@ -65,32 +79,6 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
65
79
  * @param {string} data.sessionId Identifier identifying the session
66
80
  */
67
81
  sendMessage(data: CollabEventTelepointerData): void;
68
- private sendPresence;
69
- /**
70
- * Called when a participant joins the session.
71
- *
72
- * We keep track of participants internally in this class, and emit the `presence` event to update
73
- * the active avatars in the editor.
74
- * This method will be triggered from backend to notify all participants to exchange presence
75
- */
76
- private onPresenceJoined;
77
- private onPresence;
78
- /**
79
- * Called when a participant leaves the session.
80
- *
81
- * We emit the `presence` event to update the active avatars in the editor.
82
- */
83
- private onParticipantLeft;
84
- private startInactiveRemover;
85
- /**
86
- * Called when we receive an update event from another participant.
87
- */
88
- private onParticipantUpdated;
89
- /**
90
- * Called when we receive a telepointer update from another
91
- * participant.
92
- */
93
- private onParticipantTelepointer;
94
82
  private onDisconnected;
95
83
  /**
96
84
  * "Destroy" the provider, disconnect it's connection to the back-end service and unsubscribe all event listeners on the provider.
@@ -150,10 +138,6 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
150
138
  */
151
139
  getFinalAcknowledgedState: () => Promise<ResolvedEditorState>;
152
140
  getUnconfirmedSteps: () => readonly ProseMirrorStep[] | undefined;
153
- /**
154
- * ESS-2916 namespace status event- lock/unlock
155
- */
156
- private onNamespaceStatusChanged;
157
141
  /**
158
142
  * Used when the provider is disconnected or destroyed to prevent perpetual timers from continuously running
159
143
  */
@@ -250,7 +250,7 @@ export interface CollabSendableSelection {
250
250
  export interface CollabEditProvider<Events extends CollabEvents = CollabEvents> {
251
251
  initialize(getState: () => any, createStep: (json: object) => Step): this;
252
252
  setup(props: {
253
- getState: () => EditorState;
253
+ getState?: () => EditorState;
254
254
  onSyncUpError?: SyncUpErrorFunction;
255
255
  }): this;
256
256
  send(tr: Transaction, oldState: EditorState, newState: EditorState): void;
@@ -0,0 +1,11 @@
1
+ import type { AnalyticsWebClient } from '@atlaskit/analytics-listeners';
2
+ import type { ActionAnalyticsEvent, EVENT_STATUS } from '../helpers/const';
3
+ export default class AnalyticsHelper {
4
+ analyticsClient: AnalyticsWebClient | undefined;
5
+ getAnalyticsClient: Promise<AnalyticsWebClient> | undefined;
6
+ documentAri: string;
7
+ constructor(documentAri: string, analyticsClient?: AnalyticsWebClient, getAnalyticsClient?: Promise<AnalyticsWebClient>);
8
+ sendErrorEvent(error: unknown, errorMessage: string): void;
9
+ sendActionEvent(action: ActionAnalyticsEvent['eventAction'], status: EVENT_STATUS, attributes?: Omit<ActionAnalyticsEvent['attributes'], 'documentAri' | 'eventStatus'>): void;
10
+ private sendEvent;
11
+ }
@@ -0,0 +1,15 @@
1
+ import AnalyticsHelper from './analytics-helper';
2
+ export declare enum MEASURE_NAME {
3
+ SOCKET_CONNECT = "socketConnect",
4
+ DOCUMENT_INIT = "documentInit",
5
+ COMMIT_UNCONFIRMED_STEPS = "commitUnconfirmedSteps",
6
+ PUBLISH_PAGE = "publishPage",
7
+ GET_CURRENT_STATE = "getCurrentState"
8
+ }
9
+ export declare const isPerformanceAPIAvailable: () => boolean;
10
+ export declare const measureMap: Map<string, number>;
11
+ export declare function startMeasure(measureName: MEASURE_NAME, analyticsHelper: AnalyticsHelper | undefined): void;
12
+ export declare function stopMeasure(measureName: MEASURE_NAME, analyticsHelper: AnalyticsHelper | undefined, onMeasureComplete?: (duration: number, startTime: number) => void): {
13
+ duration: number;
14
+ startTime: number;
15
+ } | undefined;
@@ -0,0 +1,3 @@
1
+ import { UFOExperience } from '@atlaskit/ufo';
2
+ import AnalyticsHelper from './analytics-helper';
3
+ export declare const createDocInitExp: (analyticsHelper: AnalyticsHelper | undefined) => UFOExperience | undefined;
@@ -0,0 +1,47 @@
1
+ import { Emitter } from './emitter';
2
+ import type { Config, ChannelEvent, CatchupResponse, Metadata } from './types';
3
+ import type { Socket } from 'socket.io-client';
4
+ import AnalyticsHelper from './analytics/analytics-helper';
5
+ export declare class Channel extends Emitter<ChannelEvent> {
6
+ private connected;
7
+ private config;
8
+ private socket;
9
+ private reconnectHelper?;
10
+ private initialized;
11
+ private analyticsHelper?;
12
+ private initExperience?;
13
+ private token?;
14
+ private network;
15
+ constructor(config: Config, analyticsHelper: AnalyticsHelper);
16
+ getInitialized: () => boolean;
17
+ getConnected: () => boolean;
18
+ getSocket: () => Socket<import("@socket.io/component-emitter").DefaultEventsMap, import("@socket.io/component-emitter").DefaultEventsMap> | null;
19
+ getToken: () => string | undefined;
20
+ private setToken;
21
+ private unsetToken;
22
+ /**
23
+ * Connect to collab service using websockets
24
+ */
25
+ connect(shouldInitialize?: boolean): void;
26
+ private handlePermissionInvalidateToken;
27
+ private onConnectError;
28
+ private onReconnectError;
29
+ private onConnect;
30
+ private onReceiveData;
31
+ fetchCatchup: (fromVersion: number) => Promise<CatchupResponse>;
32
+ /**
33
+ * Send message to the back-end service over the channel. Timestamp will be added server side.
34
+ * @throws {NotInitializedError} Channel not initialized
35
+ * @throws {NotConnectedError} Channel not connected
36
+ */
37
+ broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], "timestamp">, callback?: Function) => void;
38
+ /**
39
+ * Send metadata to the back-end service over the channel
40
+ * @throws {NotInitializedError} Channel not initialized
41
+ * @throws {NotConnectedError} Channel not connected
42
+ */
43
+ sendMetadata: (metadata: Metadata) => void;
44
+ sendPresenceJoined(): void;
45
+ onOnlineHandler: () => void;
46
+ disconnect(): void;
47
+ }
@@ -0,0 +1,5 @@
1
+ export declare const SOCKET_IO_OPTIONS: {
2
+ RECONNECTION_DELAY_MAX: number;
3
+ RECONNECTION_DELAY: number;
4
+ RANDOMIZATION_FACTOR: number;
5
+ };
@@ -0,0 +1,17 @@
1
+ export declare enum NetworkStatus {
2
+ ONLINE = "ONLINE",
3
+ OFFLINE = "OFFLINE"
4
+ }
5
+ export interface NetworkProps {
6
+ initialStatus?: NetworkStatus;
7
+ onlineCallback?: () => void;
8
+ }
9
+ export default class Network {
10
+ status?: NetworkStatus;
11
+ onlineCallback?: () => void;
12
+ constructor(props?: NetworkProps);
13
+ private offlineHandler;
14
+ private onlineHandler;
15
+ getStatus(): NetworkStatus | null;
16
+ destroy(): void;
17
+ }
@@ -0,0 +1,8 @@
1
+ export default class ReconnectHelper {
2
+ failedReconnectCount: number;
3
+ constructor();
4
+ private onlineHandler;
5
+ countReconnectError(): void;
6
+ isLikelyNetworkIssue(): boolean;
7
+ destroy(): void;
8
+ }
@@ -0,0 +1,3 @@
1
+ import Network from './network';
2
+ declare const network: Network;
3
+ export { network };
@@ -0,0 +1,16 @@
1
+ export declare const socketIOReasons: {
2
+ IO_CLIENT_DISCONNECT: string;
3
+ IO_SERVER_DISCONNECT: string;
4
+ TRANSPORT_CLOSED: string;
5
+ TRANSPORT_ERROR: string;
6
+ PING_TIMEOUT: string;
7
+ };
8
+ export declare enum DisconnectReason {
9
+ CLIENT_DISCONNECT = "CLIENT_DISCONNECT",
10
+ SERVER_DISCONNECT = "SERVER_DISCONNECT",
11
+ SOCKET_CLOSED = "SOCKET_CLOSED",
12
+ SOCKET_ERROR = "SOCKET_ERROR",
13
+ SOCKET_TIMEOUT = "SOCKET_TIMEOUT",
14
+ UNKNOWN_DISCONNECT = "UNKNOWN_DISCONNECT"
15
+ }
16
+ export declare const disconnectedReasonMapper: (reason: string) => DisconnectReason;
@@ -0,0 +1,9 @@
1
+ import type { CatchupOptions } from '../types';
2
+ import { Mapping, Step } from 'prosemirror-transform';
3
+ /**
4
+ * Rebase the steps based on the mapping pipeline.
5
+ * Some steps could be lost, if they are no longer
6
+ * invalid after rebased.
7
+ */
8
+ export declare function rebaseSteps(steps: readonly Step[], mapping: Mapping): Step[];
9
+ export declare const catchup: (opt: CatchupOptions) => Promise<void>;
@@ -0,0 +1,86 @@
1
+ /// <reference types="lodash" />
2
+ import AnalyticsHelper from '../analytics/analytics-helper';
3
+ import { CatchupResponse, ChannelEvent, CollabEvents, CollabInitPayload, StepsPayload } from '../types';
4
+ import type { Step as ProseMirrorStep } from 'prosemirror-transform';
5
+ import type { MetadataService } from '../metadata/metadata-service';
6
+ import { SyncUpErrorFunction } from '@atlaskit/editor-common/types';
7
+ import type { EditorState, Transaction } from 'prosemirror-state';
8
+ import { ResolvedEditorState } from '@atlaskit/editor-common/collab';
9
+ import { ParticipantsService } from '../participants/participants-service';
10
+ import type { InternalError } from '../errors/error-types';
11
+ export declare class DocumentService {
12
+ private participantsService;
13
+ private analyticsHelper;
14
+ private fetchCatchup;
15
+ private providerEmitCallback;
16
+ private broadcast;
17
+ private getUserId;
18
+ private onErrorHandled;
19
+ private metadataService;
20
+ private getState;
21
+ private onSyncUpError?;
22
+ private stepQueue;
23
+ private stepRejectCounter;
24
+ private clientId?;
25
+ /**
26
+ *
27
+ * @param participantsService - The participants service, used when users are detected active when making changes to the document
28
+ * and to emit their telepointers from steps they add
29
+ * @param analyticsHelper - Helper for analytics events
30
+ * @param fetchCatchup - Function to fetch "catchup" data, data required to rebase current steps to the latest version.
31
+ * @param providerEmitCallback - Callback for emitting events to listeners on the provider
32
+ * @param broadcastMetadata - Callback for broadcasting metadata changes to other clients
33
+ * @param broadcast - Callback for broadcasting events to other clients
34
+ * @param getUserId - Callback to fetch the current user's ID
35
+ * @param onErrorHandled - Callback to handle
36
+ */
37
+ constructor(participantsService: ParticipantsService, analyticsHelper: AnalyticsHelper | undefined, fetchCatchup: (fromVersion: number) => Promise<CatchupResponse>, providerEmitCallback: (evt: keyof CollabEvents, data: any) => void, broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, getUserId: () => string | undefined, onErrorHandled: (error: InternalError) => void, metadataService: MetadataService);
38
+ /**
39
+ * To prevent calling catchup to often, use lodash throttle to reduce the frequency
40
+ */
41
+ throttledCatchup: import("lodash").DebouncedFunc<() => Promise<void>>;
42
+ /**
43
+ * Called when:
44
+ * * session established(offline -> online)
45
+ * * try to accept steps but version is behind.
46
+ */
47
+ private catchup;
48
+ getCurrentPmVersion: () => number;
49
+ private processQueue;
50
+ getCurrentState: () => Promise<ResolvedEditorState>;
51
+ private processSteps;
52
+ getUnconfirmedStepsOrigins: () => readonly Transaction<any>[] | undefined;
53
+ getUnconfirmedSteps: () => readonly ProseMirrorStep[] | undefined;
54
+ private applyLocalSteps;
55
+ /**
56
+ * Called when we receive steps from the service
57
+ */
58
+ onStepsAdded: (data: StepsPayload) => void;
59
+ onRestore: ({ doc, version, metadata }: CollabInitPayload) => void;
60
+ getFinalAcknowledgedState: () => Promise<ResolvedEditorState>;
61
+ updateDocument: ({ doc, version, metadata, reserveCursor, }: CollabInitPayload) => void;
62
+ /**
63
+ * Commit the unconfirmed local steps to the back-end service
64
+ * @throws {Error} Couldn't sync the steps after retrying 30 times
65
+ */
66
+ commitUnconfirmedSteps: () => Promise<void>;
67
+ setup({ getState, onSyncUpError, clientId, }: {
68
+ getState: () => EditorState;
69
+ onSyncUpError?: SyncUpErrorFunction;
70
+ clientId: number | string | undefined;
71
+ }): this;
72
+ /**
73
+ * We can use this function to throttle/delay
74
+ * Any send steps operation
75
+ *
76
+ * The getState function will return the current EditorState
77
+ * from the EditorView.
78
+ */
79
+ sendStepsFromCurrentState(): void;
80
+ onStepRejectedError: () => void;
81
+ /**
82
+ * Send steps from transaction to other participants
83
+ * It needs the superfluous arguments because we keep the interface of the send API the same as the Synchrony plugin
84
+ */
85
+ send(_tr: Transaction | null, _oldState: EditorState | null, newState: EditorState): void;
86
+ }
@@ -0,0 +1,16 @@
1
+ import { StepsPayload } from '../types';
2
+ export declare class StepQueueState {
3
+ private queuePaused;
4
+ private queue;
5
+ queueSteps(data: StepsPayload): void;
6
+ getQueue: () => StepsPayload[];
7
+ filterQueue: (condition: (stepsPayload: StepsPayload) => boolean) => void;
8
+ /**
9
+ * Get whether the document service has stopped processing new steps whilst it carries out processes such as catchup.
10
+ * Exposed for testing
11
+ */
12
+ isPaused: () => boolean;
13
+ pauseQueue: () => void;
14
+ resumeQueue: () => void;
15
+ shift: () => StepsPayload | undefined;
16
+ }
@@ -0,0 +1,19 @@
1
+ export declare class Emitter<T = any> {
2
+ private eventEmitter;
3
+ /**
4
+ * Emit events to subscribers
5
+ */
6
+ protected emit<K extends keyof T>(evt: K, data: T[K]): this;
7
+ /**
8
+ * Subscribe to events emitted by this provider
9
+ */
10
+ on<K extends keyof T>(evt: K, handler: (args: T[K]) => void): this;
11
+ /**
12
+ * Unsubscribe from events emitted by this provider
13
+ */
14
+ off<K extends keyof T>(evt: K, handler: (args: T[K]) => void): this;
15
+ /**
16
+ * Unsubscribe from all events emitted by this provider.
17
+ */
18
+ unsubscribeAll<K extends keyof T>(evt?: K): this;
19
+ }
@@ -0,0 +1,2 @@
1
+ import { InternalError, ProviderError } from './error-types';
2
+ export declare const errorCodeMapper: (error: InternalError) => ProviderError | undefined;