@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
402 lines (401 loc) • 14.5 kB
TypeScript
import type { ReactElement } from 'react';
import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
import type { EditorState, ReadonlyTransaction, Transaction } from '@atlaskit/editor-prosemirror/state';
import type { Step } from '@atlaskit/editor-prosemirror/transform';
import type { Providers } from '../provider-factory';
export type NewCollabSyncUpErrorAttributes = {
lengthOfUnconfirmedSteps?: number;
tries: number;
maxRetries: number;
clientId?: number | string;
version: number;
};
export type ResolvedEditorState<T = any> = {
content: JSONDocNode | T;
title: string | null;
stepVersion: number;
};
export declare enum PROVIDER_ERROR_CODE {
NO_PERMISSION_ERROR = "NO_PERMISSION_ERROR",
INVALID_USER_TOKEN = "INVALID_USER_TOKEN",
DOCUMENT_NOT_FOUND = "DOCUMENT_NOT_FOUND",
LOCKED = "LOCKED",
FAIL_TO_SAVE = "FAIL_TO_SAVE",
DOCUMENT_RESTORE_ERROR = "DOCUMENT_RESTORE_ERROR",
INITIALISATION_ERROR = "INITIALISATION_ERROR",
NETWORK_ISSUE = "NETWORK_ISSUE",
INVALID_PROVIDER_CONFIGURATION = "INVALID_PROVIDER_CONFIGURATION",
INTERNAL_SERVICE_ERROR = "INTERNAL_SERVICE_ERROR",
DOCUMENT_UPDATE_ERROR = "DOCUMENT_UPDATE_ERROR"
}
/**
* This occurs when the provided user token is considered invalid for the given document ARI.
* It happens during initialisation of the provider.
* It could mean the document has been deleted (hence not found).
* @message Message returned to editor, i.e User does not have permissions to access this document or document is not found
* @recoverable It is recoverable, as we will try to refresh the token.
*/
type InsufficientEditingPermission = {
code: PROVIDER_ERROR_CODE.NO_PERMISSION_ERROR;
message: string;
recoverable: boolean;
reason?: string;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* Similar to InsufficientEditingPermission, but the user token is invalid because it has expired or been revoked.
* It may also be an invalid token format.
* This error is given to the provider by NCS.
* @message Message returned to editor, i.e. The user token was invalid
* @recoverable It is recoverable, as we will try to refresh the token.
*/
type InvalidUserToken = {
code: PROVIDER_ERROR_CODE.INVALID_USER_TOKEN;
message: string;
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* Document not found error, thrown when the provider is unable to find a document with the given ARI and user token.
* It occurs during fetchCatchup, a function that fetches the latest document state during catchup.
* We need to recieve a 404 from the document service to throw this error.
* @message Message returned to editor, i.e. The requested document is not found
* @recoverable It is recoverable, as the provider can try again later.
*/
type DocumentNotFound = {
code: PROVIDER_ERROR_CODE.DOCUMENT_NOT_FOUND;
message: string;
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* This error is thrown when the document is locked by another user.
* The error is passed to us by NCS.
* @message Message returned to editor, i.e. The document is currently not available, please try again later
* @recoverable It is recoverable, as the provider can try again later.
*/
type Locked = {
code: PROVIDER_ERROR_CODE.LOCKED;
message: string;
recoverable: boolean;
status?: number;
};
/**
* This error is thrown when the provider is unable to save the document.
* This can happen when the connection to dynamoDB is lost, or when we do not have sufficient permissions (DYNAMO ERROR).
* This error is given to us by NCS.
* @message Message returned to editor, i.e. Collab service is not able to save changes
* @recoverable It is not recoverable, as we don't want the user to continue editing a document that is not being saved.
*/
type FailToSave = {
code: PROVIDER_ERROR_CODE.FAIL_TO_SAVE;
message: string;
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* This error is thrown when the provider is unable to restore the document.
* It occurs during onRestore, a function that restores the document to a previous version and reapplies unconfirmed steps.
* onRestore is called when page recovery has emitted an 'init' event on a page client is currently connected to.
* It could mean we failed to update the page metadata, or we failed to reapply unconfirmed steps.
* @message Message returned to editor, i.e. Collab service unable to restore document
* @recoverable It is not recoverable, as the provider has no further options after this.
* The user will need to refresh the page to try again.
*/
type DocumentNotRestore = {
code: PROVIDER_ERROR_CODE.DOCUMENT_RESTORE_ERROR;
message: string;
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* The initial document couldn't be loaded from the collab service.
* This error is given to us by NCS.
* It could indicate either a network issue, or an internal service error in NCS.
* @message Message returned to editor, i.e. The initial document couldn't be loaded from the collab service
* @recoverable It is not recoverable, as the provider cannot do anything to fix it.
* The user will need to refresh the page to try again.
*/
type InitialisationError = {
code: PROVIDER_ERROR_CODE.INITIALISATION_ERROR;
message: string;
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* Couldn't reconnect to the collab service (NCS) due to network issues.
* NCS could be down, or the user could be offline. It's also possible the url is incorrect, or the user is behind a proxy blocking the connection.
* Fired upon a reconnection attempt error (from Socket.IO Manager)
* @message Message returned to editor, i.e. Couldn't reconnect to the collab service due to network issues
* @recoverable It is recoverable, as the provider will try to reconnect.
*/
type NetworkIssue = {
code: PROVIDER_ERROR_CODE.NETWORK_ISSUE;
message: string;
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* This error is thrown when the provider has an invalid configuration.
* It could happen due to these errors from NCS:
* NAMESPACE_INVALID
INVALID_ACTIVATION_ID
INVALID_DOCUMENT_ARI
INVALID_CLOUD_ID
* @message Message returned to editor, i.e. Invalid provider configuration
* @recoverable It is not recoverable, as the provider cannot do anything to fix it.
* The service using the provider will need to fix the configuration.
*/
type InvalidProviderConfiguration = {
code: PROVIDER_ERROR_CODE.INVALID_PROVIDER_CONFIGURATION;
message: string;
recoverable: boolean;
reason: string;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* This error is thrown when the provider encounters an internal service error, not otherwise accounted for.
* @message Message returned to editor, i.e. Collab Provider experienced an unrecoverable error
* @recoverable It is not recoverable, as the provider cannot do anything to fix it.
*/
type InternalServiceError = {
code: PROVIDER_ERROR_CODE.INTERNAL_SERVICE_ERROR;
message: string;
recoverable: boolean;
reason: string;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
type ProviderDocumentUpdateError = {
code: PROVIDER_ERROR_CODE.DOCUMENT_UPDATE_ERROR;
message: 'The provider failed to apply changes to the editor';
recoverable: boolean;
/**
* @deprecated switch to using either the error code or the recoverable flag
*/
status?: number;
};
/**
* A union of all possible provider errors that can be emitted back to the editor.
*/
export type ProviderError = InsufficientEditingPermission | InvalidUserToken | DocumentNotFound | Locked | FailToSave | DocumentNotRestore | InitialisationError | NetworkIssue | InvalidProviderConfiguration | InternalServiceError | ProviderDocumentUpdateError;
export interface Metadata {
[key: string]: string | number | boolean;
}
export type CollabMetadataPayload = Metadata;
export interface CollabEventInitData {
doc?: any;
json?: any;
version?: number;
sid?: string;
reserveCursor?: boolean;
}
export interface CollabInitPayload extends CollabEventInitData {
doc: any;
version: number;
metadata?: Metadata;
reserveCursor?: boolean;
}
export interface CollabEventConnectionData {
sid: string;
initial: boolean;
}
export type CollabConnectedPayload = CollabEventConnectionData;
export declare enum DisconnectReason {
CLIENT_DISCONNECT = "CLIENT_DISCONNECT",
SERVER_DISCONNECT = "SERVER_DISCONNECT",
SOCKET_CLOSED = "SOCKET_CLOSED",
SOCKET_ERROR = "SOCKET_ERROR",
SOCKET_TIMEOUT = "SOCKET_TIMEOUT",
UNKNOWN_DISCONNECT = "UNKNOWN_DISCONNECT"
}
export interface CollabDisconnectedPayload {
reason: DisconnectReason;
sid: string;
}
export interface CollabEventRemoteData {
json?: any;
newState?: EditorState;
userIds?: (number | string)[];
}
type MarkJson = {
type: string;
attrs: {
[key: string]: any;
};
};
type NodeJson = {
type: string;
attrs: {
[key: string]: any;
};
content: NodeJson[];
marks: MarkJson[];
text?: string;
};
type SliceJson = {
content: NodeJson[];
openStart: number;
openEnd: number;
};
export type StepJson = {
stepType?: string;
from?: number;
to?: number;
slice?: SliceJson;
clientId: number | string;
userId: string;
createdAt?: number;
structure?: boolean;
};
export interface CollabDataPayload extends CollabEventRemoteData {
version: number;
json: StepJson[];
userIds: (number | string)[];
}
export interface CollabSendableSelection {
type: 'textSelection' | 'nodeSelection';
anchor?: number | string;
head?: number | string;
}
export interface CollabEventTelepointerData {
type: 'telepointer';
selection: CollabSendableSelection;
sessionId: string;
}
export type CollabTelepointerPayload = CollabEventTelepointerData;
type ProviderParticipantPermitLevel = {
isPermittedToView?: boolean;
isPermittedToComment?: boolean;
isPermittedToEdit?: boolean;
};
export interface CollabParticipant {
lastActive: number;
sessionId: string;
avatar: string;
name: string;
cursorPos?: number;
permit?: ProviderParticipantPermitLevel;
}
export type ProviderParticipant = CollabParticipant & {
userId: string;
clientId: number | string;
email: string;
};
export interface CollabEventPresenceData {
joined?: ProviderParticipant[];
left?: {
sessionId: string;
}[];
}
export type CollabPresencePayload = CollabEventPresenceData;
export type CollabLocalStepsPayload = {
steps: readonly Step[];
};
export interface CollabEventConnectingData {
initial: boolean;
}
export type CollabConnectingPayload = CollabEventConnectingData;
export type CollabCommitStatusEventPayload = {
status: 'attempt' | 'success' | 'failure';
version: number;
};
export type UserPermitType = {
isPermittedToView: boolean;
isPermittedToComment: boolean;
isPermittedToEdit: boolean;
};
export type CollabPermissionEventPayload = UserPermitType;
export interface CollabEvents {
'metadata:changed': Metadata;
init: CollabInitPayload;
connected: CollabConnectedPayload;
disconnected: CollabDisconnectedPayload;
data: CollabDataPayload;
telepointer: CollabTelepointerPayload;
presence: CollabPresencePayload;
'local-steps': CollabLocalStepsPayload;
error: ProviderError;
entity: any;
connecting: CollabConnectingPayload;
permission: CollabPermissionEventPayload;
'commit-status': CollabCommitStatusEventPayload;
}
export type SyncUpErrorFunction = (attributes: NewCollabSyncUpErrorAttributes) => void;
export interface CollabEditProvider<Events extends CollabEvents = CollabEvents> {
initialize(getState: () => any, createStep: (json: object) => Step): this;
setup(props: {
getState?: () => EditorState;
onSyncUpError?: SyncUpErrorFunction;
}): this;
send(tr: Transaction, oldState: EditorState, newState: EditorState): void;
on(evt: keyof Events, handler: (...args: any) => void): this;
off(evt: keyof Events, handler: (...args: any) => void): this;
unsubscribeAll(evt: keyof Events): this;
sendMessage<K extends keyof Events>(data: {
type: K;
} & Events[K]): void;
getFinalAcknowledgedState(): Promise<ResolvedEditorState>;
}
export type CollabEditOptions = {
provider?: Providers['collabEditProvider'];
userId?: string;
useNativePlugin?: boolean;
} & CollabInviteToEditProps & CollabAnalyticsProps;
export type InviteToEditButtonProps = {
onClick: (event: React.MouseEvent<HTMLElement>) => void;
selected: boolean;
};
export type InviteToEditComponentProps = {
children: ReactElement<InviteToEditButtonProps>;
};
export interface CollabInviteToEditProps {
inviteToEditHandler?: (event: React.MouseEvent<HTMLElement>) => void;
isInviteToEditButtonSelected?: boolean;
inviteToEditComponent?: React.ComponentType<React.PropsWithChildren<InviteToEditComponentProps>>;
}
export interface CollabAnalyticsProps {
/**
* @description Control whether Synchrony entity error events are tracked
*/
EXPERIMENTAL_allowInternalErrorAnalytics?: boolean;
}
export interface CollabEventLocalStepData {
steps: Array<Step>;
}
export interface Color {
solid: string;
selection: string;
}
export declare const colors: Color[];
export declare const TELEPOINTER_DIM_CLASS = "telepointer-dim";
export declare const telepointerStyle: import("@emotion/react").SerializedStyles;
export declare const isDirtyTransaction: (tr: Transaction | ReadonlyTransaction) => boolean;
export declare const tintDirtyTransaction: (tr: Transaction) => void;
export {};