@mml-io/networked-dom-document 0.18.1 → 0.19.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.
package/README.md ADDED
@@ -0,0 +1,10 @@
1
+ # Networked DOM Document
2
+ #### `@mml-io/networked-dom-document`
3
+
4
+ [![npm version](https://img.shields.io/npm/v/@mml-io/networked-dom-document.svg?style=flat)](https://www.npmjs.com/package/@mml-io/networked-dom-document)
5
+
6
+ This package contains classes `NetworkedDOM` and `EditableNetworkedDOM` that provide a way to accept websocket connections and synchronize a DOM document across multiple clients using WebSockets.
7
+
8
+ The WebSocket protocol used by this package, `networked-dom-v0.1`, is defined in `@mml-io/networked-dom-protocol`.
9
+
10
+ A client for the `networked-dom-v0.1` protocol is provided by `@mml-io/networked-dom-web`.
@@ -1,8 +1,8 @@
1
- import { ClientMessage, PongMessage } from "@mml-io/networked-dom-protocol";
2
- import { LogMessage, ObservableDOMInterface, ObservableDOMMessage, ObservableDOMParameters, StaticVirtualDOMElement } from "@mml-io/observable-dom-common";
3
- import { VirtualDOMDiffStruct } from "./common";
4
- export declare const networkedDOMProtocolSubProtocol_v0_1 = "networked-dom-v0.1";
5
- export declare const defaultWebsocketSubProtocol = "networked-dom-v0.1";
1
+ import { NetworkedDOMV02Diff } from "@mml-io/networked-dom-protocol";
2
+ import { LogMessage, ObservableDOMInterface, ObservableDOMMessage, ObservableDOMParameters, ObservableDOMRemoteEvent, StaticVirtualDOMElement } from "@mml-io/observable-dom-common";
3
+ import { VirtualDOMDiffStruct } from "./diffing/calculateStaticVirtualDOMDiff";
4
+ import { NetworkedDOMV01Connection } from "./NetworkedDOMV01Connection";
5
+ import { NetworkedDOMV02Connection } from "./NetworkedDOMV02Connection";
6
6
  export type ObservableDOMFactory = (observableDOMParameters: ObservableDOMParameters, callback: (message: ObservableDOMMessage, observableDOM: ObservableDOMInterface) => void) => ObservableDOMInterface;
7
7
  /**
8
8
  * NetworkedDOM is the main class for the networked-dom-document package. It is responsible for managing the state of
@@ -12,47 +12,52 @@ export type ObservableDOMFactory = (observableDOMParameters: ObservableDOMParame
12
12
  * implementation that is used to run the document.
13
13
  */
14
14
  export declare class NetworkedDOM {
15
- static SupportedWebsocketSubProtocolsPreferenceOrder: string[];
16
- private internalNodeIdToClientNodeId;
17
- private clientNodeIdToInternalNodeId;
15
+ private visibilityManager;
16
+ private nodeManager;
18
17
  private currentConnectionId;
19
- private connectionIdToWebSocketContext;
20
- private webSocketToConnectionId;
21
- private visibleNodeIdsByConnectionId;
18
+ private connectionIdToNetworkedDOMConnection;
19
+ private networkedDOMV01Connections;
20
+ private networkedDOMV02Connections;
21
+ private webSocketToNetworkedDOMConnection;
22
22
  private initialLoad;
23
23
  private readonly htmlPath;
24
- private disposed;
25
24
  private ignoreTextNodes;
26
25
  private documentRoot;
27
- private nodeIdToNode;
28
- private nodeIdToParentNodeId;
29
26
  private observableDOM;
30
27
  private documentEffectiveStartTime;
31
28
  private latestDocumentTime;
32
29
  private pingCounter;
33
- private maximumNodeId;
34
30
  private logCallback?;
31
+ private disposed;
35
32
  constructor(observableDOMFactory: ObservableDOMFactory, htmlPath: string, htmlContents: string, oldInstanceDocumentRoot: StaticVirtualDOMElement | null, onLoad: (domDiff: VirtualDOMDiffStruct | null, networkedDOM: NetworkedDOM) => void, params?: {}, ignoreTextNodes?: boolean, logCallback?: (message: LogMessage) => void);
36
- private defaultLogCallback;
37
- private addRemappedNodeId;
38
- private sendPings;
39
- private getInitialSnapshot;
40
- getDocumentTime(): number;
41
- addExistingWebsockets(websockets: Array<WebSocket>, existingWebsocketMap: Map<WebSocket, number> | null, domDiff: VirtualDOMDiffStruct | null): void;
42
- private findParentNodeOfNodeId;
43
- private registerWebsocket;
44
33
  static handleWebsocketSubprotocol(protocols: Set<string> | Array<string>): string | false;
45
34
  addWebSocket(webSocket: WebSocket): void;
46
35
  removeWebSocket(webSocket: WebSocket): void;
47
- dispose(): void;
48
- private processModification;
49
- private removeKnownNodesInMutation;
50
- private removeVirtualDOMElement;
51
- static IsPongMessage(message: ClientMessage): message is PongMessage;
52
- private dispatchRemoteEvent;
53
- private getStaticVirtualDOMElementByInternalNodeIdOrThrow;
54
- private addKnownNodesInMutation;
36
+ addExistingNetworkedDOMConnections(networkedDOMConnections: Set<NetworkedDOMV01Connection | NetworkedDOMV02Connection>, domDiff: VirtualDOMDiffStruct | null): void;
37
+ addNetworkedDOMConnection(networkedDOMConnection: NetworkedDOMV01Connection | NetworkedDOMV02Connection): void;
38
+ removeNetworkedDOMConnection(networkedDOMConnection: NetworkedDOMV01Connection | NetworkedDOMV02Connection): void;
39
+ connectUsers(networkedDOMConnection: NetworkedDOMV01Connection | NetworkedDOMV02Connection, addedExternalUserIds: Set<number>): Map<number, number>;
40
+ announceConnectedUsers(userIds: Set<number>): void;
41
+ disconnectUsers(networkedDOMConnection: NetworkedDOMV02Connection, removedExternalToInternalUserIds: Map<number, number>): Array<NetworkedDOMV02Diff>;
42
+ private defaultLogCallback;
43
+ private sendPings;
44
+ private getInitialV01Snapshot;
45
+ private getInitialV02Snapshot;
46
+ getDocumentTime(): number;
47
+ dispatchRemoteEvent(networkedDOMConnection: NetworkedDOMV01Connection | NetworkedDOMV02Connection, internalConnectionId: number, externalConnectionId: number, remoteEvent: ObservableDOMRemoteEvent): void;
55
48
  getSnapshot(): StaticVirtualDOMElement;
56
- private addAndRemapNodeFromInstance;
57
- getWebsocketConnectionIdMap(): Map<WebSocket, number>;
49
+ dispose(): void;
50
+ private handleAddedNodes;
51
+ private handleRemovedNodes;
52
+ private handleAttributeMutation;
53
+ private handleAttributeChange;
54
+ private handleVisibleToChange;
55
+ private handleHiddenFromChange;
56
+ private handleCharacterData;
57
+ private calculatePreVisibilityChangeRecords;
58
+ private applyVisibilityAfterChanges;
59
+ private reprojectStaticVirtualDOMElementWithMappings;
60
+ private reprojectMutationWithMappings;
61
+ private handleMutation;
62
+ private removeNodeAndChildren;
58
63
  }
@@ -0,0 +1,15 @@
1
+ import { NetworkedDOMV01ServerMessage } from "@mml-io/networked-dom-protocol";
2
+ import { NetworkedDOM } from "./NetworkedDOM";
3
+ export declare class NetworkedDOMV01Connection {
4
+ readonly webSocket: WebSocket;
5
+ private websocketListener;
6
+ internalConnectionId: number | null;
7
+ internalIdToExternalId: Map<number, number>;
8
+ networkedDOM: NetworkedDOM | null;
9
+ constructor(webSocket: WebSocket);
10
+ setNetworkedDOM(networkedDOM: NetworkedDOM | null): void;
11
+ initAsNewV01Connection(): void;
12
+ stringifyAndSendSingleMessage(message: NetworkedDOMV01ServerMessage): void;
13
+ sendStringifiedJSONArray(jsonArray: string): void;
14
+ dispose(): void;
15
+ }
@@ -0,0 +1,23 @@
1
+ import { NetworkedDOMV02ServerMessage } from "@mml-io/networked-dom-protocol";
2
+ import { NetworkedDOM } from "./NetworkedDOM";
3
+ export declare class NetworkedDOMV02Connection {
4
+ readonly webSocket: WebSocket;
5
+ private websocketListener;
6
+ externalIdToInternalId: Map<number, number>;
7
+ internalIdToExternalId: Map<number, number>;
8
+ private batchMode;
9
+ private batchMessages;
10
+ externalConnectionIds: Set<number>;
11
+ networkedDOM: NetworkedDOM | null;
12
+ private messagesAwaitingNetworkedDOM;
13
+ constructor(webSocket: WebSocket);
14
+ setNetworkedDOM(networkedDOM: NetworkedDOM | null): void;
15
+ setBatchStart(): void;
16
+ setBatchEnd(): void;
17
+ sendMessage(message: NetworkedDOMV02ServerMessage): void;
18
+ sendMessages(messages: Array<NetworkedDOMV02ServerMessage>): void;
19
+ sendEncodedBytes(bytes: Uint8Array): void;
20
+ dispose(): void;
21
+ private handleClientMessage;
22
+ handleBufferedMessages(): void;
23
+ }
@@ -0,0 +1,19 @@
1
+ import { StaticVirtualDOMElement } from "@mml-io/observable-dom-common";
2
+ import { NodeWithSubjectivity } from "./NodeWithSubjectivity";
3
+ import { VisibilityManager } from "./VisibilityManager";
4
+ export declare class NodeManager {
5
+ private visibilityManager;
6
+ private nodeIdToNode;
7
+ private maximumNodeId;
8
+ private internalNodeIdToClientNodeId;
9
+ private clientNodeIdToInternalNodeId;
10
+ constructor(visibilityManager: VisibilityManager);
11
+ getNode(nodeId: number): NodeWithSubjectivity | undefined;
12
+ deleteNode(nodeId: number): void;
13
+ addNodeFromInstance(node: StaticVirtualDOMElement, parentNode: NodeWithSubjectivity | null): [NodeWithSubjectivity, boolean];
14
+ addRemappedNodeId(clientFacingNodeId: number, internalNodeId: number): void;
15
+ hasAnyRemappings(): boolean;
16
+ getPotentiallyRemappedNode(nodeId: number, createIfCollided?: boolean): number;
17
+ getStaticVirtualDOMElementByInternalNodeIdOrThrow(internalNodeId: number): NodeWithSubjectivity;
18
+ getInternalRemappedNodeId(nodeId: number): number | undefined;
19
+ }
@@ -0,0 +1,19 @@
1
+ export type Subjectivity = {
2
+ visibleTo: Set<number>;
3
+ hiddenFrom: Set<number>;
4
+ ancestorSubjectivity: Subjectivity | null;
5
+ };
6
+ export declare function IsVisibleToAll(s: Subjectivity, applyV01Semantics: boolean): boolean;
7
+ export declare function IsVisibleToAnyOneOfConnectionIds(s: Subjectivity, connectionIdsMap: Map<number, number>, applyV01Semantics: boolean): boolean;
8
+ export type NodeWithSubjectivity = {
9
+ nodeId: number;
10
+ tag: string;
11
+ textContent?: string;
12
+ attributes: {
13
+ [key: string]: string;
14
+ };
15
+ childNodes: Array<NodeWithSubjectivity>;
16
+ subjectivity: Subjectivity;
17
+ parent: NodeWithSubjectivity | null;
18
+ };
19
+ export declare function applySubjectivityToChildren(node: NodeWithSubjectivity, newSubjectivity: Subjectivity, previousSubjectivity: Subjectivity): void;
@@ -0,0 +1,6 @@
1
+ export declare class VisibilityManager {
2
+ private connectionIdToSpecificallyVisibleNodes;
3
+ addSpecificallyVisibleNode(internalConnectionId: number, nodeId: number): void;
4
+ removeSpecificallyVisibleNode(internalConnectionId: number, nodeId: number): void;
5
+ getSpecificallyVisibleNodes(internalConnectionId: number): Set<number> | undefined;
6
+ }
@@ -0,0 +1,5 @@
1
+ import { NetworkedDOMV01Connection } from "./NetworkedDOMV01Connection";
2
+ import { NetworkedDOMV02Connection } from "./NetworkedDOMV02Connection";
3
+ export declare const SupportedWebsocketSubProtocolsPreferenceOrder: readonly ["networked-dom-v0.2", "networked-dom-v0.1"];
4
+ export declare const defaultWebsocketSubProtocol = "networked-dom-v0.1";
5
+ export declare function createNetworkedDOMConnectionForWebsocket(webSocket: WebSocket): NetworkedDOMV01Connection | NetworkedDOMV02Connection | null;
@@ -1,5 +1,5 @@
1
1
  import { StaticVirtualDOMElement } from "@mml-io/observable-dom-common";
2
- import * as rfc6902 from "./rfc6902";
2
+ import * as rfc6902 from "../rfc6902";
3
3
  export type NodeMapping = {
4
4
  clientFacingNodeId: number;
5
5
  internalNodeId: number;
@@ -14,15 +14,4 @@ export type VirtualDOMDiffStruct = {
14
14
  nodeIdRemappings: Array<NodeMapping>;
15
15
  virtualDOMDiffs: Array<rfc6902.Operation>;
16
16
  };
17
- /**
18
- * StaticVirtualDOMMutationRecord is a plain object representation of a MutationRecord that can be serialized as it
19
- * contains no references to DOM elements and instead uses node IDs to refer to elements.
20
- */
21
- export type StaticVirtualDOMMutationRecord = {
22
- type: "attributes" | "characterData" | "childList" | "snapshot";
23
- target: StaticVirtualDOMElement;
24
- addedNodes: Array<StaticVirtualDOMElement>;
25
- removedNodes: Array<StaticVirtualDOMElement>;
26
- previousSibling: StaticVirtualDOMElement | null;
27
- attributeName: string | null;
28
- };
17
+ export declare function calculateStaticVirtualDOMDiff(originalState: StaticVirtualDOMElement, latestState: StaticVirtualDOMElement): VirtualDOMDiffStruct;
@@ -0,0 +1,8 @@
1
+ import { NetworkedDOMV01NodeDescription, NetworkedDOMV02NodeDescription } from "@mml-io/networked-dom-protocol";
2
+ import { NetworkedDOMV01Connection } from "../NetworkedDOMV01Connection";
3
+ import { NetworkedDOMV02Connection } from "../NetworkedDOMV02Connection";
4
+ import { NodeWithSubjectivity } from "../NodeWithSubjectivity";
5
+ export declare const visibleToAttrName = "visible-to";
6
+ export declare const hiddenFromAttrName = "hidden-from";
7
+ export declare function describeNodeWithChildrenForV01Connection(virtualDOMElement: NodeWithSubjectivity, networkedDOMConnection: NetworkedDOMV01Connection | null): NetworkedDOMV01NodeDescription | null;
8
+ export declare function describeNodeWithChildrenForV02Connection(virtualDOMElement: NodeWithSubjectivity, networkedDOMConnection: NetworkedDOMV02Connection | null): NetworkedDOMV02NodeDescription | null;
@@ -0,0 +1 @@
1
+ export declare function listAttributeToSet(attr?: string | null): Set<number>;
@@ -0,0 +1,2 @@
1
+ import { StaticVirtualDOMMutationIdsRecord } from "@mml-io/observable-dom-common";
2
+ export declare function mergeMutations(mutations: Array<StaticVirtualDOMMutationIdsRecord>): StaticVirtualDOMMutationIdsRecord[];
@@ -0,0 +1,3 @@
1
+ import { StaticVirtualDOMElement, StaticVirtualDOMMutationIdsRecord } from "@mml-io/observable-dom-common";
2
+ import * as rfc6902 from "../rfc6902";
3
+ export declare function virtualDOMDiffToVirtualDOMMutationRecord(virtualStructure: StaticVirtualDOMElement, domDiff: rfc6902.Operation): Array<StaticVirtualDOMMutationIdsRecord>;
package/build/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from "./EditableNetworkedDOM";
2
2
  export * from "./NetworkedDOM";
3
+ export { NetworkedDOMV01Connection } from "./NetworkedDOMV01Connection";
4
+ export { NetworkedDOMV02Connection } from "./NetworkedDOMV02Connection";