@datalayer/lexical-loro 0.1.0 → 0.2.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 +1 -1
- package/package.json +7 -7
- package/lib/App.d.ts +0 -2
- package/lib/App.js +0 -141
- package/lib/Editor.d.ts +0 -2
- package/lib/Editor.js +0 -111
- package/lib/Settings.d.ts +0 -2
- package/lib/Settings.js +0 -57
- package/lib/appSettings.d.ts +0 -36
- package/lib/appSettings.js +0 -44
- package/lib/collab/loro/Bindings.d.ts +0 -41
- package/lib/collab/loro/Bindings.js +0 -95
- package/lib/collab/loro/Debug.d.ts +0 -33
- package/lib/collab/loro/Debug.js +0 -448
- package/lib/collab/loro/LexicalCollaborationContext.d.ts +0 -19
- package/lib/collab/loro/LexicalCollaborationContext.js +0 -48
- package/lib/collab/loro/LexicalCollaborationPlugin.d.ts +0 -24
- package/lib/collab/loro/LexicalCollaborationPlugin.js +0 -83
- package/lib/collab/loro/State.d.ts +0 -53
- package/lib/collab/loro/State.js +0 -90
- package/lib/collab/loro/components/LoroCollaborationUI.d.ts +0 -13
- package/lib/collab/loro/components/LoroCollaborationUI.js +0 -9
- package/lib/collab/loro/components/LoroCollaborators.d.ts +0 -8
- package/lib/collab/loro/components/LoroCollaborators.js +0 -97
- package/lib/collab/loro/components/index.d.ts +0 -2
- package/lib/collab/loro/components/index.js +0 -2
- package/lib/collab/loro/index.d.ts +0 -6
- package/lib/collab/loro/index.js +0 -6
- package/lib/collab/loro/integrators/BaseIntegrator.d.ts +0 -14
- package/lib/collab/loro/integrators/BaseIntegrator.js +0 -1
- package/lib/collab/loro/integrators/CounterIntegrator.d.ts +0 -23
- package/lib/collab/loro/integrators/CounterIntegrator.js +0 -40
- package/lib/collab/loro/integrators/ListIntegrator.d.ts +0 -23
- package/lib/collab/loro/integrators/ListIntegrator.js +0 -49
- package/lib/collab/loro/integrators/MapIntegrator.d.ts +0 -24
- package/lib/collab/loro/integrators/MapIntegrator.js +0 -177
- package/lib/collab/loro/integrators/TextIntegrator.d.ts +0 -25
- package/lib/collab/loro/integrators/TextIntegrator.js +0 -51
- package/lib/collab/loro/integrators/TreeIntegrator.d.ts +0 -25
- package/lib/collab/loro/integrators/TreeIntegrator.js +0 -201
- package/lib/collab/loro/nodes/NodeFactory.d.ts +0 -8
- package/lib/collab/loro/nodes/NodeFactory.js +0 -105
- package/lib/collab/loro/nodes/NodesMapper.d.ts +0 -111
- package/lib/collab/loro/nodes/NodesMapper.js +0 -258
- package/lib/collab/loro/propagators/DecoratorNodePropagator.d.ts +0 -60
- package/lib/collab/loro/propagators/DecoratorNodePropagator.js +0 -302
- package/lib/collab/loro/propagators/ElementNodePropagator.d.ts +0 -62
- package/lib/collab/loro/propagators/ElementNodePropagator.js +0 -335
- package/lib/collab/loro/propagators/LineBreakNodePropagator.d.ts +0 -57
- package/lib/collab/loro/propagators/LineBreakNodePropagator.js +0 -196
- package/lib/collab/loro/propagators/RootNodePropagator.d.ts +0 -55
- package/lib/collab/loro/propagators/RootNodePropagator.js +0 -168
- package/lib/collab/loro/propagators/TextNodePropagator.d.ts +0 -60
- package/lib/collab/loro/propagators/TextNodePropagator.js +0 -434
- package/lib/collab/loro/propagators/index.d.ts +0 -49
- package/lib/collab/loro/propagators/index.js +0 -32
- package/lib/collab/loro/provider/websocket.d.ts +0 -116
- package/lib/collab/loro/provider/websocket.js +0 -907
- package/lib/collab/loro/servers/index.d.ts +0 -0
- package/lib/collab/loro/servers/index.js +0 -0
- package/lib/collab/loro/servers/ws/callback.d.ts +0 -5
- package/lib/collab/loro/servers/ws/callback.js +0 -85
- package/lib/collab/loro/servers/ws/server.d.ts +0 -2
- package/lib/collab/loro/servers/ws/server.js +0 -25
- package/lib/collab/loro/servers/ws/utils.d.ts +0 -40
- package/lib/collab/loro/servers/ws/utils.js +0 -513
- package/lib/collab/loro/sync/SyncCursors.d.ts +0 -32
- package/lib/collab/loro/sync/SyncCursors.js +0 -435
- package/lib/collab/loro/sync/SyncLexicalToLoro.d.ts +0 -4
- package/lib/collab/loro/sync/SyncLexicalToLoro.js +0 -80
- package/lib/collab/loro/sync/SyncLoroToLexical.d.ts +0 -5
- package/lib/collab/loro/sync/SyncLoroToLexical.js +0 -96
- package/lib/collab/loro/types/LexicalNodeData.d.ts +0 -32
- package/lib/collab/loro/types/LexicalNodeData.js +0 -71
- package/lib/collab/loro/useCollaboration.d.ts +0 -12
- package/lib/collab/loro/useCollaboration.js +0 -248
- package/lib/collab/loro/utils/InitialContent.d.ts +0 -64
- package/lib/collab/loro/utils/InitialContent.js +0 -109
- package/lib/collab/loro/utils/LexicalToLoro.d.ts +0 -18
- package/lib/collab/loro/utils/LexicalToLoro.js +0 -96
- package/lib/collab/loro/utils/Utils.d.ts +0 -44
- package/lib/collab/loro/utils/Utils.js +0 -153
- package/lib/collab/loro/wsProvider.d.ts +0 -8
- package/lib/collab/loro/wsProvider.js +0 -31
- package/lib/collab/utils/invariant.d.ts +0 -1
- package/lib/collab/utils/invariant.js +0 -11
- package/lib/collab/utils/simpleDiffWithCursor.d.ts +0 -5
- package/lib/collab/utils/simpleDiffWithCursor.js +0 -31
- package/lib/collab/yjs/Bindings.d.ts +0 -23
- package/lib/collab/yjs/Bindings.js +0 -26
- package/lib/collab/yjs/Debug.d.ts +0 -23
- package/lib/collab/yjs/Debug.js +0 -213
- package/lib/collab/yjs/LexicalCollaborationContext.d.ts +0 -10
- package/lib/collab/yjs/LexicalCollaborationContext.js +0 -37
- package/lib/collab/yjs/LexicalCollaborationPlugin.d.ts +0 -21
- package/lib/collab/yjs/LexicalCollaborationPlugin.js +0 -63
- package/lib/collab/yjs/State.d.ts +0 -51
- package/lib/collab/yjs/State.js +0 -35
- package/lib/collab/yjs/nodes/AnyCollabNode.d.ts +0 -5
- package/lib/collab/yjs/nodes/AnyCollabNode.js +0 -1
- package/lib/collab/yjs/nodes/CollabDecoratorNode.d.ts +0 -22
- package/lib/collab/yjs/nodes/CollabDecoratorNode.js +0 -64
- package/lib/collab/yjs/nodes/CollabElementNode.d.ts +0 -40
- package/lib/collab/yjs/nodes/CollabElementNode.js +0 -462
- package/lib/collab/yjs/nodes/CollabLineBreakNode.d.ts +0 -19
- package/lib/collab/yjs/nodes/CollabLineBreakNode.js +0 -44
- package/lib/collab/yjs/nodes/CollabTextNode.d.ts +0 -25
- package/lib/collab/yjs/nodes/CollabTextNode.js +0 -103
- package/lib/collab/yjs/provider/websocket.d.ts +0 -88
- package/lib/collab/yjs/provider/websocket.js +0 -415
- package/lib/collab/yjs/servers/index.d.ts +0 -0
- package/lib/collab/yjs/servers/index.js +0 -0
- package/lib/collab/yjs/servers/ws/callback.d.ts +0 -5
- package/lib/collab/yjs/servers/ws/callback.js +0 -72
- package/lib/collab/yjs/servers/ws/server.d.ts +0 -2
- package/lib/collab/yjs/servers/ws/server.js +0 -25
- package/lib/collab/yjs/servers/ws/utils.d.ts +0 -49
- package/lib/collab/yjs/servers/ws/utils.js +0 -284
- package/lib/collab/yjs/sync/SyncCursors.d.ts +0 -39
- package/lib/collab/yjs/sync/SyncCursors.js +0 -351
- package/lib/collab/yjs/sync/SyncEditorStates.d.ts +0 -10
- package/lib/collab/yjs/sync/SyncEditorStates.js +0 -200
- package/lib/collab/yjs/useCollaboration.d.ts +0 -12
- package/lib/collab/yjs/useCollaboration.js +0 -255
- package/lib/collab/yjs/utils/Utils.d.ts +0 -25
- package/lib/collab/yjs/utils/Utils.js +0 -402
- package/lib/collab/yjs/wsProvider.d.ts +0 -3
- package/lib/collab/yjs/wsProvider.js +0 -21
- package/lib/commenting/index.d.ts +0 -41
- package/lib/commenting/index.js +0 -324
- package/lib/context/FlashMessageContext.d.ts +0 -7
- package/lib/context/FlashMessageContext.js +0 -24
- package/lib/context/SettingsContext.d.ts +0 -12
- package/lib/context/SettingsContext.js +0 -38
- package/lib/context/SharedHistoryContext.d.ts +0 -11
- package/lib/context/SharedHistoryContext.js +0 -11
- package/lib/context/ToolbarContext.d.ts +0 -65
- package/lib/context/ToolbarContext.js +0 -84
- package/lib/demo.d.ts +0 -12
- package/lib/demo.js +0 -41
- package/lib/hooks/useFlashMessage.d.ts +0 -2
- package/lib/hooks/useFlashMessage.js +0 -4
- package/lib/hooks/useModal.d.ts +0 -5
- package/lib/hooks/useModal.js +0 -26
- package/lib/hooks/useReport.d.ts +0 -1
- package/lib/hooks/useReport.js +0 -46
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -1
- package/lib/nodes/AutocompleteNode.d.ts +0 -27
- package/lib/nodes/AutocompleteNode.js +0 -56
- package/lib/nodes/CounterComponent.d.ts +0 -6
- package/lib/nodes/CounterComponent.js +0 -137
- package/lib/nodes/CounterNode.d.ts +0 -23
- package/lib/nodes/CounterNode.js +0 -47
- package/lib/nodes/DateTimeNode/DateTimeComponent.d.ts +0 -8
- package/lib/nodes/DateTimeNode/DateTimeComponent.js +0 -119
- package/lib/nodes/DateTimeNode/DateTimeNode.d.ts +0 -27
- package/lib/nodes/DateTimeNode/DateTimeNode.js +0 -82
- package/lib/nodes/EmojiNode.d.ts +0 -18
- package/lib/nodes/EmojiNode.js +0 -50
- package/lib/nodes/EquationComponent.d.ts +0 -9
- package/lib/nodes/EquationComponent.js +0 -75
- package/lib/nodes/EquationNode.d.ts +0 -26
- package/lib/nodes/EquationNode.js +0 -109
- package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.d.ts +0 -8
- package/lib/nodes/ExcalidrawNode/ExcalidrawComponent.js +0 -110
- package/lib/nodes/ExcalidrawNode/ExcalidrawImage.d.ts +0 -50
- package/lib/nodes/ExcalidrawNode/ExcalidrawImage.js +0 -55
- package/lib/nodes/ExcalidrawNode/index.d.ts +0 -32
- package/lib/nodes/ExcalidrawNode/index.js +0 -117
- package/lib/nodes/FigmaNode.d.ts +0 -20
- package/lib/nodes/FigmaNode.js +0 -52
- package/lib/nodes/ImageComponent.d.ts +0 -16
- package/lib/nodes/ImageComponent.js +0 -272
- package/lib/nodes/ImageNode.d.ts +0 -50
- package/lib/nodes/ImageNode.js +0 -151
- package/lib/nodes/InlineImageNode/InlineImageComponent.d.ts +0 -26
- package/lib/nodes/InlineImageNode/InlineImageComponent.js +0 -161
- package/lib/nodes/InlineImageNode/InlineImageNode.d.ts +0 -59
- package/lib/nodes/InlineImageNode/InlineImageNode.js +0 -162
- package/lib/nodes/KeywordNode.d.ts +0 -14
- package/lib/nodes/KeywordNode.js +0 -33
- package/lib/nodes/LayoutContainerNode.d.ts +0 -24
- package/lib/nodes/LayoutContainerNode.js +0 -91
- package/lib/nodes/LayoutItemNode.d.ts +0 -16
- package/lib/nodes/LayoutItemNode.js +0 -65
- package/lib/nodes/MentionNode.d.ts +0 -20
- package/lib/nodes/MentionNode.js +0 -81
- package/lib/nodes/PageBreakNode/index.d.ts +0 -17
- package/lib/nodes/PageBreakNode/index.js +0 -83
- package/lib/nodes/PlaygroundNodes.d.ts +0 -3
- package/lib/nodes/PlaygroundNodes.js +0 -71
- package/lib/nodes/PollComponent.d.ts +0 -9
- package/lib/nodes/PollComponent.js +0 -85
- package/lib/nodes/PollNode.d.ts +0 -43
- package/lib/nodes/PollNode.js +0 -153
- package/lib/nodes/SpecialTextNode.d.ts +0 -24
- package/lib/nodes/SpecialTextNode.js +0 -50
- package/lib/nodes/StickyComponent.d.ts +0 -10
- package/lib/nodes/StickyComponent.js +0 -162
- package/lib/nodes/StickyNode.d.ts +0 -31
- package/lib/nodes/StickyNode.js +0 -76
- package/lib/nodes/TweetNode.d.ts +0 -21
- package/lib/nodes/TweetNode.js +0 -119
- package/lib/nodes/YouTubeNode.d.ts +0 -22
- package/lib/nodes/YouTubeNode.js +0 -84
- package/lib/plugins/ActionsPlugin/index.d.ts +0 -5
- package/lib/plugins/ActionsPlugin/index.js +0 -168
- package/lib/plugins/AutoEmbedPlugin/index.d.ts +0 -19
- package/lib/plugins/AutoEmbedPlugin/index.js +0 -158
- package/lib/plugins/AutoLinkPlugin/index.d.ts +0 -2
- package/lib/plugins/AutoLinkPlugin/index.js +0 -15
- package/lib/plugins/AutocompletePlugin/index.d.ts +0 -10
- package/lib/plugins/AutocompletePlugin/index.js +0 -2473
- package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.d.ts +0 -7
- package/lib/plugins/CodeActionMenuPlugin/components/CopyButton/index.js +0 -42
- package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.d.ts +0 -17
- package/lib/plugins/CodeActionMenuPlugin/components/PrettierButton/index.js +0 -111
- package/lib/plugins/CodeActionMenuPlugin/index.d.ts +0 -5
- package/lib/plugins/CodeActionMenuPlugin/index.js +0 -104
- package/lib/plugins/CodeActionMenuPlugin/utils.d.ts +0 -1
- package/lib/plugins/CodeActionMenuPlugin/utils.js +0 -18
- package/lib/plugins/CodeHighlightPrismPlugin/index.d.ts +0 -2
- package/lib/plugins/CodeHighlightPrismPlugin/index.js +0 -10
- package/lib/plugins/CodeHighlightShikiPlugin/index.d.ts +0 -2
- package/lib/plugins/CodeHighlightShikiPlugin/index.js +0 -10
- package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.d.ts +0 -25
- package/lib/plugins/CollapsiblePlugin/CollapsibleContainerNode.js +0 -131
- package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.d.ts +0 -16
- package/lib/plugins/CollapsiblePlugin/CollapsibleContentNode.js +0 -79
- package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.d.ts +0 -16
- package/lib/plugins/CollapsiblePlugin/CollapsibleTitleNode.js +0 -81
- package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.d.ts +0 -2
- package/lib/plugins/CollapsiblePlugin/CollapsibleUtils.js +0 -8
- package/lib/plugins/CollapsiblePlugin/index.d.ts +0 -3
- package/lib/plugins/CollapsiblePlugin/index.js +0 -128
- package/lib/plugins/CommentPlugin/index.d.ts +0 -9
- package/lib/plugins/CommentPlugin/index.js +0 -460
- package/lib/plugins/ComponentPickerPlugin/index.d.ts +0 -2
- package/lib/plugins/ComponentPickerPlugin/index.js +0 -276
- package/lib/plugins/ContextMenuPlugin/index.d.ts +0 -2
- package/lib/plugins/ContextMenuPlugin/index.js +0 -112
- package/lib/plugins/CounterPlugin/index.d.ts +0 -3
- package/lib/plugins/CounterPlugin/index.js +0 -20
- package/lib/plugins/DatalayerPlugin/index.d.ts +0 -2
- package/lib/plugins/DatalayerPlugin/index.js +0 -218
- package/lib/plugins/DateTimePlugin/index.d.ts +0 -8
- package/lib/plugins/DateTimePlugin/index.js +0 -24
- package/lib/plugins/DocsPlugin/index.d.ts +0 -2
- package/lib/plugins/DocsPlugin/index.js +0 -4
- package/lib/plugins/DragDropPastePlugin/index.d.ts +0 -1
- package/lib/plugins/DragDropPastePlugin/index.js +0 -33
- package/lib/plugins/DraggableBlockPlugin/index.d.ts +0 -12
- package/lib/plugins/DraggableBlockPlugin/index.js +0 -36
- package/lib/plugins/EmojiPickerPlugin/index.d.ts +0 -1
- package/lib/plugins/EmojiPickerPlugin/index.js +0 -80
- package/lib/plugins/EmojisPlugin/index.d.ts +0 -2
- package/lib/plugins/EmojisPlugin/index.js +0 -52
- package/lib/plugins/EquationsPlugin/index.d.ts +0 -14
- package/lib/plugins/EquationsPlugin/index.js +0 -34
- package/lib/plugins/ExcalidrawPlugin/index.d.ts +0 -5
- package/lib/plugins/ExcalidrawPlugin/index.js +0 -44
- package/lib/plugins/FigmaPlugin/index.d.ts +0 -4
- package/lib/plugins/FigmaPlugin/index.js +0 -20
- package/lib/plugins/FloatingLinkEditorPlugin/index.d.ts +0 -15
- package/lib/plugins/FloatingLinkEditorPlugin/index.js +0 -280
- package/lib/plugins/FloatingTextFormatToolbarPlugin/index.d.ts +0 -7
- package/lib/plugins/FloatingTextFormatToolbarPlugin/index.js +0 -219
- package/lib/plugins/ImagesPlugin/index.d.ts +0 -24
- package/lib/plugins/ImagesPlugin/index.js +0 -195
- package/lib/plugins/InlineImagePlugin/index.d.ts +0 -17
- package/lib/plugins/InlineImagePlugin/index.js +0 -180
- package/lib/plugins/KeywordsPlugin/index.d.ts +0 -2
- package/lib/plugins/KeywordsPlugin/index.js +0 -31
- package/lib/plugins/LayoutPlugin/InsertLayoutDialog.d.ts +0 -6
- package/lib/plugins/LayoutPlugin/InsertLayoutDialog.js +0 -21
- package/lib/plugins/LayoutPlugin/LayoutPlugin.d.ts +0 -7
- package/lib/plugins/LayoutPlugin/LayoutPlugin.js +0 -131
- package/lib/plugins/LinkPlugin/index.d.ts +0 -6
- package/lib/plugins/LinkPlugin/index.js +0 -11
- package/lib/plugins/MarkdownShortcutPlugin/index.d.ts +0 -2
- package/lib/plugins/MarkdownShortcutPlugin/index.js +0 -6
- package/lib/plugins/MarkdownTransformers/index.d.ts +0 -8
- package/lib/plugins/MarkdownTransformers/index.js +0 -234
- package/lib/plugins/MaxLengthPlugin/index.d.ts +0 -3
- package/lib/plugins/MaxLengthPlugin/index.js +0 -37
- package/lib/plugins/MentionsPlugin/index.d.ts +0 -2
- package/lib/plugins/MentionsPlugin/index.js +0 -564
- package/lib/plugins/PageBreakPlugin/index.d.ts +0 -4
- package/lib/plugins/PageBreakPlugin/index.js +0 -27
- package/lib/plugins/PasteLogPlugin/index.d.ts +0 -2
- package/lib/plugins/PasteLogPlugin/index.js +0 -27
- package/lib/plugins/PollPlugin/index.d.ts +0 -8
- package/lib/plugins/PollPlugin/index.js +0 -38
- package/lib/plugins/ShortcutsPlugin/index.d.ts +0 -6
- package/lib/plugins/ShortcutsPlugin/index.js +0 -112
- package/lib/plugins/ShortcutsPlugin/shortcuts.d.ts +0 -59
- package/lib/plugins/ShortcutsPlugin/shortcuts.js +0 -169
- package/lib/plugins/SpecialTextPlugin/index.d.ts +0 -2
- package/lib/plugins/SpecialTextPlugin/index.js +0 -46
- package/lib/plugins/SpeechToTextPlugin/index.d.ts +0 -5
- package/lib/plugins/SpeechToTextPlugin/index.js +0 -82
- package/lib/plugins/StickyPlugin/index.d.ts +0 -2
- package/lib/plugins/StickyPlugin/index.js +0 -12
- package/lib/plugins/TabFocusPlugin/index.d.ts +0 -1
- package/lib/plugins/TabFocusPlugin/index.js +0 -34
- package/lib/plugins/TableActionMenuPlugin/index.d.ts +0 -5
- package/lib/plugins/TableActionMenuPlugin/index.js +0 -492
- package/lib/plugins/TableCellResizer/index.d.ts +0 -3
- package/lib/plugins/TableCellResizer/index.js +0 -297
- package/lib/plugins/TableHoverActionsPlugin/index.d.ts +0 -4
- package/lib/plugins/TableHoverActionsPlugin/index.js +0 -188
- package/lib/plugins/TableOfContentsPlugin/index.d.ts +0 -2
- package/lib/plugins/TableOfContentsPlugin/index.js +0 -116
- package/lib/plugins/TablePlugin.d.ts +0 -31
- package/lib/plugins/TablePlugin.js +0 -63
- package/lib/plugins/TestRecorderPlugin/index.d.ts +0 -3
- package/lib/plugins/TestRecorderPlugin/index.js +0 -346
- package/lib/plugins/ToolbarPlugin/fontSize.d.ts +0 -9
- package/lib/plugins/ToolbarPlugin/fontSize.js +0 -80
- package/lib/plugins/ToolbarPlugin/index.d.ts +0 -9
- package/lib/plugins/ToolbarPlugin/index.js +0 -500
- package/lib/plugins/ToolbarPlugin/utils.d.ts +0 -26
- package/lib/plugins/ToolbarPlugin/utils.js +0 -243
- package/lib/plugins/TreeViewPlugin/index.d.ts +0 -2
- package/lib/plugins/TreeViewPlugin/index.js +0 -7
- package/lib/plugins/TwitterPlugin/index.d.ts +0 -4
- package/lib/plugins/TwitterPlugin/index.js +0 -20
- package/lib/plugins/TypingPerfPlugin/index.d.ts +0 -2
- package/lib/plugins/TypingPerfPlugin/index.js +0 -93
- package/lib/plugins/YouTubePlugin/index.d.ts +0 -4
- package/lib/plugins/YouTubePlugin/index.js +0 -20
- package/lib/server/validation.d.ts +0 -1
- package/lib/server/validation.js +0 -111
- package/lib/setupEnv.d.ts +0 -2
- package/lib/setupEnv.js +0 -25
- package/lib/themes/CommentEditorTheme.d.ts +0 -4
- package/lib/themes/CommentEditorTheme.js +0 -7
- package/lib/themes/PlaygroundEditorTheme.d.ts +0 -4
- package/lib/themes/PlaygroundEditorTheme.js +0 -120
- package/lib/themes/StickyEditorTheme.d.ts +0 -4
- package/lib/themes/StickyEditorTheme.js +0 -7
- package/lib/tyes.dt.d.ts +0 -12
- package/lib/tyes.dt.js +0 -0
- package/lib/ui/Button.d.ts +0 -12
- package/lib/ui/Button.js +0 -6
- package/lib/ui/ColorPicker.d.ts +0 -14
- package/lib/ui/ColorPicker.js +0 -219
- package/lib/ui/ContentEditable.d.ts +0 -9
- package/lib/ui/ContentEditable.js +0 -6
- package/lib/ui/Dialog.d.ts +0 -10
- package/lib/ui/Dialog.js +0 -8
- package/lib/ui/DropDown.d.ts +0 -18
- package/lib/ui/DropDown.js +0 -133
- package/lib/ui/DropdownColorPicker.d.ts +0 -13
- package/lib/ui/DropdownColorPicker.js +0 -6
- package/lib/ui/EquationEditor.d.ts +0 -8
- package/lib/ui/EquationEditor.js +0 -11
- package/lib/ui/ExcalidrawModal.d.ts +0 -42
- package/lib/ui/ExcalidrawModal.js +0 -103
- package/lib/ui/FileInput.d.ts +0 -10
- package/lib/ui/FileInput.js +0 -5
- package/lib/ui/FlashMessage.d.ts +0 -7
- package/lib/ui/FlashMessage.js +0 -6
- package/lib/ui/ImageResizer.d.ts +0 -17
- package/lib/ui/ImageResizer.js +0 -171
- package/lib/ui/KatexEquationAlterer.d.ts +0 -8
- package/lib/ui/KatexEquationAlterer.js +0 -23
- package/lib/ui/KatexRenderer.d.ts +0 -6
- package/lib/ui/KatexRenderer.js +0 -24
- package/lib/ui/Modal.d.ts +0 -9
- package/lib/ui/Modal.js +0 -48
- package/lib/ui/Select.d.ts +0 -8
- package/lib/ui/Select.js +0 -5
- package/lib/ui/Switch.d.ts +0 -8
- package/lib/ui/Switch.js +0 -6
- package/lib/ui/TextInput.d.ts +0 -13
- package/lib/ui/TextInput.js +0 -7
- package/lib/utils/docSerialization.d.ts +0 -3
- package/lib/utils/docSerialization.js +0 -56
- package/lib/utils/emoji-list.d.ts +0 -20
- package/lib/utils/emoji-list.js +0 -16605
- package/lib/utils/getDOMRangeRect.d.ts +0 -8
- package/lib/utils/getDOMRangeRect.js +0 -22
- package/lib/utils/getSelectedNode.d.ts +0 -2
- package/lib/utils/getSelectedNode.js +0 -24
- package/lib/utils/getThemeSelector.d.ts +0 -2
- package/lib/utils/getThemeSelector.js +0 -10
- package/lib/utils/isMobileWidth.d.ts +0 -7
- package/lib/utils/isMobileWidth.js +0 -7
- package/lib/utils/joinClasses.d.ts +0 -1
- package/lib/utils/joinClasses.js +0 -3
- package/lib/utils/setFloatingElemPosition.d.ts +0 -1
- package/lib/utils/setFloatingElemPosition.js +0 -55
- package/lib/utils/setFloatingElemPositionForLinkEditor.d.ts +0 -1
- package/lib/utils/setFloatingElemPositionForLinkEditor.js +0 -32
- package/lib/utils/swipe.d.ts +0 -4
- package/lib/utils/swipe.js +0 -90
- package/lib/utils/url.d.ts +0 -2
- package/lib/utils/url.js +0 -27
|
File without changes
|
|
File without changes
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import http from 'http';
|
|
2
|
-
import * as number from 'lib0/number';
|
|
3
|
-
const CALLBACK_URL = process.env.CALLBACK_URL ? new URL(process.env.CALLBACK_URL) : null;
|
|
4
|
-
const CALLBACK_TIMEOUT = number.parseInt(process.env.CALLBACK_TIMEOUT || '5000');
|
|
5
|
-
const CALLBACK_OBJECTS = process.env.CALLBACK_OBJECTS ? JSON.parse(process.env.CALLBACK_OBJECTS) : {};
|
|
6
|
-
export const isCallbackSet = !!CALLBACK_URL;
|
|
7
|
-
/**
|
|
8
|
-
* @param {import('./utils.ts').WSSharedDoc} doc
|
|
9
|
-
*/
|
|
10
|
-
export const callbackIntegrator = (doc) => {
|
|
11
|
-
const room = doc.name;
|
|
12
|
-
const dataToSend = {
|
|
13
|
-
room,
|
|
14
|
-
data: {}
|
|
15
|
-
};
|
|
16
|
-
const sharedObjectList = Object.keys(CALLBACK_OBJECTS);
|
|
17
|
-
sharedObjectList.forEach(sharedObjectName => {
|
|
18
|
-
const sharedObjectType = CALLBACK_OBJECTS[sharedObjectName];
|
|
19
|
-
const content = getContent(sharedObjectName, sharedObjectType, doc);
|
|
20
|
-
dataToSend.data[sharedObjectName] = {
|
|
21
|
-
type: sharedObjectType,
|
|
22
|
-
content: content && typeof content.toJSON === 'function' ? content.toJSON() : content
|
|
23
|
-
};
|
|
24
|
-
});
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* @param {URL} url
|
|
28
|
-
* @param {number} timeout
|
|
29
|
-
* @param {Object} data
|
|
30
|
-
*/
|
|
31
|
-
const callbackRequest = (url, timeout, data) => {
|
|
32
|
-
data = JSON.stringify(data);
|
|
33
|
-
const options = {
|
|
34
|
-
hostname: url.hostname,
|
|
35
|
-
port: url.port,
|
|
36
|
-
path: url.pathname,
|
|
37
|
-
timeout,
|
|
38
|
-
method: 'POST',
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'application/json',
|
|
41
|
-
'Content-Length': Buffer.byteLength(data)
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
|
-
const req = http.request(options);
|
|
45
|
-
req.on('timeout', () => {
|
|
46
|
-
console.warn('Callback request timed out.');
|
|
47
|
-
req.abort();
|
|
48
|
-
});
|
|
49
|
-
req.on('error', (e) => {
|
|
50
|
-
console.warn('Callback request error.', e);
|
|
51
|
-
req.abort();
|
|
52
|
-
});
|
|
53
|
-
req.write(data);
|
|
54
|
-
req.end();
|
|
55
|
-
};
|
|
56
|
-
/**
|
|
57
|
-
* @param {string} objName
|
|
58
|
-
* @param {string} objType
|
|
59
|
-
* @param {import('./utils.ts').WSSharedDoc} doc
|
|
60
|
-
*/
|
|
61
|
-
const getContent = (objName, objType, doc) => {
|
|
62
|
-
// Loro uses a different API than YJS
|
|
63
|
-
// Get the container by name and type
|
|
64
|
-
try {
|
|
65
|
-
switch (objType) {
|
|
66
|
-
case 'List':
|
|
67
|
-
case 'Array':
|
|
68
|
-
return doc.doc.getList(objName);
|
|
69
|
-
case 'Map':
|
|
70
|
-
return doc.doc.getMap(objName);
|
|
71
|
-
case 'Text':
|
|
72
|
-
return doc.doc.getText(objName);
|
|
73
|
-
case 'Tree':
|
|
74
|
-
return doc.doc.getTree(objName);
|
|
75
|
-
default: {
|
|
76
|
-
// For unknown types, return the entire document state
|
|
77
|
-
return doc.doc.toJSON();
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch (error) {
|
|
82
|
-
console.warn(`Failed to get content for ${objName} of type ${objType}:`, error);
|
|
83
|
-
return {};
|
|
84
|
-
}
|
|
85
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { WebSocketServer } from 'ws';
|
|
3
|
-
import http from 'http';
|
|
4
|
-
import * as number from 'lib0/number';
|
|
5
|
-
import { setupWSConnection } from './utils';
|
|
6
|
-
const wss = new WebSocketServer({ noServer: true });
|
|
7
|
-
const host = process.env.HOST || 'localhost';
|
|
8
|
-
const port = number.parseInt(process.env.PORT || '1235');
|
|
9
|
-
const server = http.createServer((_request, response) => {
|
|
10
|
-
response.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
11
|
-
response.end('okay');
|
|
12
|
-
});
|
|
13
|
-
wss.on('connection', setupWSConnection);
|
|
14
|
-
server.on('upgrade', (request, socket, head) => {
|
|
15
|
-
// You may check auth of request here..
|
|
16
|
-
// Call `wss.HandleUpgrade` *after* you checked whether the client has access
|
|
17
|
-
// (e.g. by checking cookies, or url parameters).
|
|
18
|
-
// See https://github.com/websockets/ws#client-authentication
|
|
19
|
-
wss.handleUpgrade(request, socket, head, /** @param {any} ws */ /** @param {any} ws */ ws => {
|
|
20
|
-
wss.emit('connection', ws, request);
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
server.listen(port, host, () => {
|
|
24
|
-
console.log(`running at '${host}' on port ${port}`);
|
|
25
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { LoroDoc, EphemeralStore } from 'loro-crdt';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
*/
|
|
5
|
-
export declare const setPersistence: (persistence_: any) => void;
|
|
6
|
-
/**
|
|
7
|
-
*
|
|
8
|
-
*/
|
|
9
|
-
export declare const getPersistence: () => any;
|
|
10
|
-
/**
|
|
11
|
-
*
|
|
12
|
-
*/
|
|
13
|
-
export declare const docs: Map<string, WSSharedDoc>;
|
|
14
|
-
/**
|
|
15
|
-
* This function is called once every time a Loro document is created. You can
|
|
16
|
-
* use it to pull data from an external source or initialize content.
|
|
17
|
-
*/
|
|
18
|
-
export declare const setContentInitializor: (f: any) => void;
|
|
19
|
-
/**
|
|
20
|
-
* Gets a Doc by name, whether in memory or on disk
|
|
21
|
-
*/
|
|
22
|
-
export declare const getDoc: (docname: any) => WSSharedDoc;
|
|
23
|
-
/**
|
|
24
|
-
* @param {import('ws').WebSocket} conn
|
|
25
|
-
* @param {import('http').IncomingMessage} req
|
|
26
|
-
* @param {any} opts
|
|
27
|
-
*/
|
|
28
|
-
export declare const setupWSConnection: (conn: any, req: any, { docName }?: {
|
|
29
|
-
docName?: any;
|
|
30
|
-
}) => void;
|
|
31
|
-
export declare class WSSharedDoc {
|
|
32
|
-
name: string;
|
|
33
|
-
doc: LoroDoc;
|
|
34
|
-
connections: Map<any, Set<string>>;
|
|
35
|
-
ephemeralStore: EphemeralStore;
|
|
36
|
-
conns: Map<any, Set<any>>;
|
|
37
|
-
private _conns;
|
|
38
|
-
lastEphemeralSender: any;
|
|
39
|
-
constructor(name: any);
|
|
40
|
-
}
|
|
@@ -1,513 +0,0 @@
|
|
|
1
|
-
import { LoroDoc, EphemeralStore } from 'loro-crdt';
|
|
2
|
-
import * as map from 'lib0/map';
|
|
3
|
-
import * as eventloop from 'lib0/eventloop';
|
|
4
|
-
import { messageEphemeral, messageQueryEphemeral, messageQuerySnapshot, messageUpdate, } from '../../provider/websocket';
|
|
5
|
-
import { callbackIntegrator, isCallbackSet } from './callback';
|
|
6
|
-
import { initializeLoroDocWithLexicalContent } from '../../utils/InitialContent';
|
|
7
|
-
const pingTimeout = 30000;
|
|
8
|
-
const CALLBACK_DEBOUNCE_WAIT = parseInt(process.env.CALLBACK_DEBOUNCE_WAIT || '2000');
|
|
9
|
-
const CALLBACK_DEBOUNCE_MAXWAIT = parseInt(process.env.CALLBACK_DEBOUNCE_MAXWAIT || '10000');
|
|
10
|
-
const debouncer = eventloop.createDebouncer(CALLBACK_DEBOUNCE_WAIT, CALLBACK_DEBOUNCE_MAXWAIT);
|
|
11
|
-
const wsReadyStateConnecting = 0;
|
|
12
|
-
const wsReadyStateOpen = 1;
|
|
13
|
-
const wsReadyStateClosing = 2;
|
|
14
|
-
const wsReadyStateClosed = 3;
|
|
15
|
-
const persistenceDir = process.env.YPERSISTENCE;
|
|
16
|
-
// Helper function to log tree structure for debugging
|
|
17
|
-
const logTreeStructure = (doc, context) => {
|
|
18
|
-
try {
|
|
19
|
-
console.log(`[Server] ${context} - Tree Structure Debug:`);
|
|
20
|
-
// Try to get the tree container using getTree method
|
|
21
|
-
try {
|
|
22
|
-
const tree = doc.getTree('tree');
|
|
23
|
-
if (tree) {
|
|
24
|
-
const nodes = tree.nodes();
|
|
25
|
-
console.log(`[Server] Total nodes in tree: ${nodes.length}`);
|
|
26
|
-
// Helper function to recursively log tree structure
|
|
27
|
-
const logTreeStructureRecursive = (node, prefix = '', isLast = true, depth = 0) => {
|
|
28
|
-
const data = Object.fromEntries(node.data.entries());
|
|
29
|
-
const treeId = node.id;
|
|
30
|
-
const elementType = data.elementType || 'no-type';
|
|
31
|
-
const connector = depth === 0 ? '' : (isLast ? '└── ' : '├── ');
|
|
32
|
-
const nodeInfo = `TreeID(${treeId.slice(0, 8)}...) [${elementType}]`;
|
|
33
|
-
console.log(`[Server] ${prefix}${connector}${nodeInfo}`);
|
|
34
|
-
const children = node.children();
|
|
35
|
-
if (children && children.length > 0) {
|
|
36
|
-
children.forEach((child, index) => {
|
|
37
|
-
const isLastChild = index === children.length - 1;
|
|
38
|
-
const childPrefix = prefix + (depth === 0 ? '' : (isLast ? ' ' : '│ '));
|
|
39
|
-
logTreeStructureRecursive(child, childPrefix, isLastChild, depth + 1);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
// Find and display all root nodes
|
|
44
|
-
const rootNodes = nodes.filter((node) => {
|
|
45
|
-
const parent = node.parent();
|
|
46
|
-
const data = Object.fromEntries(node.data.entries());
|
|
47
|
-
return !parent || data.isRoot;
|
|
48
|
-
});
|
|
49
|
-
console.log(`[Server] Root nodes: ${rootNodes.length}`);
|
|
50
|
-
console.log('');
|
|
51
|
-
if (rootNodes.length === 0) {
|
|
52
|
-
console.log('[Server] ⚠️ No root nodes found!');
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
rootNodes.forEach((root, index) => {
|
|
56
|
-
const isLastRoot = index === rootNodes.length - 1;
|
|
57
|
-
logTreeStructureRecursive(root, '', isLastRoot, 0);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
console.log(`[Server] No tree container found`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
catch (treeError) {
|
|
66
|
-
console.log(`[Server] Error accessing tree container:`, treeError.message);
|
|
67
|
-
}
|
|
68
|
-
// Try export with different modes for debugging
|
|
69
|
-
try {
|
|
70
|
-
const snapshot = doc.export({ mode: 'snapshot' });
|
|
71
|
-
console.log(`[Server] Snapshot size: ${snapshot.length} bytes`);
|
|
72
|
-
const update = doc.export({ mode: 'update' });
|
|
73
|
-
console.log(`[Server] Update size: ${update.length} bytes`);
|
|
74
|
-
}
|
|
75
|
-
catch (exportError) {
|
|
76
|
-
console.log(`[Server] Error exporting:`, exportError.message);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch (error) {
|
|
80
|
-
console.warn(`[Server] Error logging tree structure:`, error);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
*
|
|
85
|
-
*/
|
|
86
|
-
let persistence = null;
|
|
87
|
-
if (typeof persistenceDir === 'string') {
|
|
88
|
-
console.log('Persistence directory configured: "' + persistenceDir + '" but Loro persistence not yet implemented');
|
|
89
|
-
// TODO: Implement actual Loro document persistence
|
|
90
|
-
// For now, disable persistence to keep documents in memory
|
|
91
|
-
console.log('Disabling persistence - documents will be kept in memory only');
|
|
92
|
-
persistence = null;
|
|
93
|
-
// Uncomment and implement when ready for actual persistence:
|
|
94
|
-
// persistence = {
|
|
95
|
-
// provider: null, // Replace with Loro-compatible persistence provider
|
|
96
|
-
// bindState: async (docName, doc: WSSharedDoc) => {
|
|
97
|
-
// // TODO: Implement Loro document persistence loading
|
|
98
|
-
// console.warn(`Loading state for document: ${docName}`)
|
|
99
|
-
// },
|
|
100
|
-
// writeState: async (docName, doc: WSSharedDoc) => {
|
|
101
|
-
// // TODO: Implement Loro document state writing
|
|
102
|
-
// console.warn(`Saving state for document: ${docName}`)
|
|
103
|
-
// }
|
|
104
|
-
// }
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
*
|
|
108
|
-
*/
|
|
109
|
-
export const setPersistence = persistence_ => {
|
|
110
|
-
persistence = persistence_;
|
|
111
|
-
};
|
|
112
|
-
/**
|
|
113
|
-
*
|
|
114
|
-
*/
|
|
115
|
-
export const getPersistence = () => persistence;
|
|
116
|
-
/**
|
|
117
|
-
*
|
|
118
|
-
*/
|
|
119
|
-
export const docs = new Map();
|
|
120
|
-
/**
|
|
121
|
-
* @type {(ydoc: Y.Doc) => Promise<void>}
|
|
122
|
-
*/
|
|
123
|
-
let contentInitializor = _ydoc => Promise.resolve();
|
|
124
|
-
/**
|
|
125
|
-
* This function is called once every time a Loro document is created. You can
|
|
126
|
-
* use it to pull data from an external source or initialize content.
|
|
127
|
-
*/
|
|
128
|
-
export const setContentInitializor = (f) => {
|
|
129
|
-
contentInitializor = f;
|
|
130
|
-
};
|
|
131
|
-
/**
|
|
132
|
-
* Gets a Doc by name, whether in memory or on disk
|
|
133
|
-
*/
|
|
134
|
-
export const getDoc = (docname) => map.setIfUndefined(docs, docname, () => {
|
|
135
|
-
const doc = new WSSharedDoc(docname);
|
|
136
|
-
if (persistence !== null) {
|
|
137
|
-
persistence.bindState(docname, doc);
|
|
138
|
-
}
|
|
139
|
-
docs.set(docname, doc);
|
|
140
|
-
return doc;
|
|
141
|
-
});
|
|
142
|
-
/**
|
|
143
|
-
*
|
|
144
|
-
*/
|
|
145
|
-
const sendMessage = (doc, conn, message) => {
|
|
146
|
-
if (conn.readyState === wsReadyStateClosing || conn.readyState === wsReadyStateClosed) {
|
|
147
|
-
closeConn(doc, conn);
|
|
148
|
-
}
|
|
149
|
-
try {
|
|
150
|
-
// console.log(`Sending message to ${conn.id || 'unknown'}`)
|
|
151
|
-
conn.send(JSON.stringify(message), {}, err => { if (err != null)
|
|
152
|
-
closeConn(doc, conn); });
|
|
153
|
-
}
|
|
154
|
-
catch (e) {
|
|
155
|
-
console.warn(e);
|
|
156
|
-
closeConn(doc, conn);
|
|
157
|
-
}
|
|
158
|
-
};
|
|
159
|
-
/**
|
|
160
|
-
*
|
|
161
|
-
*/
|
|
162
|
-
const sendMessageBinary = (doc, conn, message) => {
|
|
163
|
-
if (conn.readyState === wsReadyStateClosing || conn.readyState === wsReadyStateClosed) {
|
|
164
|
-
closeConn(doc, conn);
|
|
165
|
-
}
|
|
166
|
-
try {
|
|
167
|
-
// console.log(`Sending message to ${conn.id || 'unknown'}`)
|
|
168
|
-
conn.send(message, {}, err => { if (err != null)
|
|
169
|
-
closeConn(doc, conn); });
|
|
170
|
-
}
|
|
171
|
-
catch (e) {
|
|
172
|
-
console.warn(e);
|
|
173
|
-
closeConn(doc, conn);
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
/**
|
|
177
|
-
*
|
|
178
|
-
*/
|
|
179
|
-
const messageListener = (conn, doc, message) => {
|
|
180
|
-
try {
|
|
181
|
-
let messageData = null;
|
|
182
|
-
let messageStr = '';
|
|
183
|
-
if (typeof message === 'string') {
|
|
184
|
-
messageStr = message;
|
|
185
|
-
}
|
|
186
|
-
else if (message instanceof ArrayBuffer) {
|
|
187
|
-
try {
|
|
188
|
-
const decoder = new TextDecoder();
|
|
189
|
-
messageStr = decoder.decode(message);
|
|
190
|
-
}
|
|
191
|
-
catch (decodeError) {
|
|
192
|
-
console.warn(`[Server] messageListener - Failed to decode ArrayBuffer as string, treating as binary Loro update`);
|
|
193
|
-
// If decoding fails, treat as raw binary Loro update
|
|
194
|
-
const updateBytes = new Uint8Array(message);
|
|
195
|
-
doc.doc.import(updateBytes);
|
|
196
|
-
// Broadcast the update to other connections
|
|
197
|
-
doc.conns.forEach((_, c) => {
|
|
198
|
-
if (c !== conn) {
|
|
199
|
-
sendMessageBinary(doc, c, new Uint8Array(message));
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
else if (message instanceof Uint8Array) {
|
|
206
|
-
try {
|
|
207
|
-
const decoder = new TextDecoder();
|
|
208
|
-
messageStr = decoder.decode(message);
|
|
209
|
-
}
|
|
210
|
-
catch (decodeError) {
|
|
211
|
-
console.warn(`[Server] messageListener - Failed to decode Uint8Array as string, treating as binary Loro update`);
|
|
212
|
-
// If decoding fails, treat as raw binary Loro update
|
|
213
|
-
doc.doc.import(message);
|
|
214
|
-
// Broadcast the update to other connections
|
|
215
|
-
doc.conns.forEach((_, c) => {
|
|
216
|
-
if (c !== conn) {
|
|
217
|
-
sendMessageBinary(doc, c, message);
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
return;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
else {
|
|
224
|
-
console.warn(`[Server] messageListener - Unknown message type:`, typeof message);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
if (!messageStr || messageStr.length === 0) {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
try {
|
|
231
|
-
messageData = JSON.parse(messageStr);
|
|
232
|
-
}
|
|
233
|
-
catch (parseError) {
|
|
234
|
-
console.warn(`[Server] messageListener - JSON parse error:`, parseError.message);
|
|
235
|
-
console.warn(`[Server] messageListener - Raw message:`, messageStr.substring(0, 500));
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
console.log(`[Server] Received message type: ${messageData.type} for doc: ${doc.name}`);
|
|
239
|
-
switch (messageData.type) {
|
|
240
|
-
case messageQuerySnapshot:
|
|
241
|
-
// Client is requesting a snapshot - send current document state
|
|
242
|
-
const requestId = Math.random().toString(36).substr(2, 9);
|
|
243
|
-
console.log(`[Server] Client requesting snapshot for doc: ${doc.name} (Request ID: ${requestId})`);
|
|
244
|
-
// Log tree structure before creating snapshot
|
|
245
|
-
// logTreeStructure(doc.doc, `Before creating snapshot (Request ID: ${requestId})`)
|
|
246
|
-
try {
|
|
247
|
-
const snapshot = doc.doc.export({ mode: 'snapshot' });
|
|
248
|
-
console.log(`[Server] Sending snapshot response: ${snapshot.length} bytes (Request ID: ${requestId})`);
|
|
249
|
-
// Verify the snapshot contains expected content
|
|
250
|
-
const tree = doc.doc.getTree('tree');
|
|
251
|
-
const nodes = tree.nodes();
|
|
252
|
-
console.log(`[Server] Snapshot contains ${nodes.length} nodes from server document`);
|
|
253
|
-
// Send binary snapshot data directly instead of wrapped message
|
|
254
|
-
conn.send(snapshot);
|
|
255
|
-
}
|
|
256
|
-
catch (snapshotError) {
|
|
257
|
-
console.error(`[Server] ERROR creating/sending snapshot:`, snapshotError.message);
|
|
258
|
-
console.error(`[Server] Stack:`, snapshotError.stack);
|
|
259
|
-
}
|
|
260
|
-
break;
|
|
261
|
-
case messageEphemeral:
|
|
262
|
-
try {
|
|
263
|
-
const ephemeralBytes = new Uint8Array(messageData.ephemeral);
|
|
264
|
-
// Mark this connection as the sender to avoid echo
|
|
265
|
-
doc.lastEphemeralSender = conn;
|
|
266
|
-
// Debug: Check ephemeral store state before and after
|
|
267
|
-
const beforeStates = doc.ephemeralStore.getAllStates();
|
|
268
|
-
const beforeKeys = Object.keys(beforeStates);
|
|
269
|
-
doc.ephemeralStore.apply(ephemeralBytes);
|
|
270
|
-
const afterStates = doc.ephemeralStore.getAllStates();
|
|
271
|
-
const afterKeys = Object.keys(afterStates);
|
|
272
|
-
console.log(`📡 SERVER DEBUG - Applied ephemeral update from ${conn.id}:`, {
|
|
273
|
-
bytesLength: ephemeralBytes.length,
|
|
274
|
-
beforeKeys,
|
|
275
|
-
afterKeys,
|
|
276
|
-
newKeys: afterKeys.filter(k => !beforeKeys.includes(k)),
|
|
277
|
-
totalConnections: doc.conns.size
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
catch (ephemeralError) {
|
|
281
|
-
console.warn('messageEphemeral - ERROR applying ephemeral update');
|
|
282
|
-
// Clear sender reference on error
|
|
283
|
-
doc.lastEphemeralSender = null;
|
|
284
|
-
}
|
|
285
|
-
break;
|
|
286
|
-
case messageQueryEphemeral:
|
|
287
|
-
// Send current ephemeral state to requesting client
|
|
288
|
-
try {
|
|
289
|
-
const allStates = doc.ephemeralStore.getAllStates();
|
|
290
|
-
const allKeys = Object.keys(allStates);
|
|
291
|
-
const ephemeralUpdate = doc.ephemeralStore.encodeAll();
|
|
292
|
-
console.log(`📡 SERVER DEBUG - Client ${conn.id} requesting ephemeral state:`, {
|
|
293
|
-
allKeysAvailable: allKeys,
|
|
294
|
-
encodedLength: ephemeralUpdate.length,
|
|
295
|
-
totalConnections: doc.conns.size
|
|
296
|
-
});
|
|
297
|
-
const ephemeralResponse = {
|
|
298
|
-
type: 'ephemeral',
|
|
299
|
-
ephemeral: Array.from(ephemeralUpdate),
|
|
300
|
-
docId: doc.name
|
|
301
|
-
};
|
|
302
|
-
sendMessage(doc, conn, ephemeralResponse);
|
|
303
|
-
}
|
|
304
|
-
catch (error) {
|
|
305
|
-
console.warn('[Server] messageQueryEphemeral - ERROR encoding/sending ephemeral state:', error);
|
|
306
|
-
}
|
|
307
|
-
break;
|
|
308
|
-
case messageUpdate:
|
|
309
|
-
// Apply the Loro update to the document.
|
|
310
|
-
const updateBytes = new Uint8Array(messageData.update);
|
|
311
|
-
const i = doc.doc.import(updateBytes);
|
|
312
|
-
// logTreeStructure(doc.doc, `After applying update from client ${conn.id || 'unknown'}`)
|
|
313
|
-
// Create properly formatted message for broadcasting
|
|
314
|
-
// Send the update to all other connections
|
|
315
|
-
let broadcastCount = 0;
|
|
316
|
-
doc.conns.forEach((_, c) => {
|
|
317
|
-
if (c !== conn) {
|
|
318
|
-
console.log(`Broadcasting Update to connection: ${c.id}`);
|
|
319
|
-
sendMessage(doc, c, messageData);
|
|
320
|
-
broadcastCount++;
|
|
321
|
-
}
|
|
322
|
-
});
|
|
323
|
-
// Trigger callback if configured
|
|
324
|
-
if (isCallbackSet) {
|
|
325
|
-
debouncer(() => callbackIntegrator(doc));
|
|
326
|
-
}
|
|
327
|
-
break;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
catch (err) {
|
|
331
|
-
console.warn(err);
|
|
332
|
-
// Note: LoroDoc doesn't have emit method, using console.warn instead
|
|
333
|
-
console.warn('Message handling error:', err);
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
/**
|
|
337
|
-
* @param {WSSharedDoc} doc
|
|
338
|
-
* @param {any} conn
|
|
339
|
-
*/
|
|
340
|
-
const closeConn = (doc, conn) => {
|
|
341
|
-
if (doc.conns.has(conn)) {
|
|
342
|
-
console.log(`Closing connection: ${conn.id || 'unknown'} for document: ${doc.name}`);
|
|
343
|
-
/**
|
|
344
|
-
* @type {Set<string>}
|
|
345
|
-
*/
|
|
346
|
-
const controlledKeys = doc.conns.get(conn);
|
|
347
|
-
doc.conns.delete(conn);
|
|
348
|
-
// Remove ephemeral state controlled by this connection
|
|
349
|
-
if (controlledKeys) {
|
|
350
|
-
controlledKeys.forEach(key => {
|
|
351
|
-
doc.ephemeralStore.delete(key);
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
console.log(`Remaining connections for document ${doc.name}: ${doc.conns.size}`);
|
|
355
|
-
if (doc.conns.size === 0) {
|
|
356
|
-
if (persistence !== null) {
|
|
357
|
-
// if persisted, we store state and cleanup document
|
|
358
|
-
console.log(`[Server] Persisting document ${doc.name} before cleanup`);
|
|
359
|
-
persistence.writeState(doc.name, doc).then(() => {
|
|
360
|
-
// Cleanup WSSharedDoc resources (no destroy method needed for Loro)
|
|
361
|
-
console.log(`[Server] Document ${doc.name} persisted and cleaned up`);
|
|
362
|
-
});
|
|
363
|
-
docs.delete(doc.name);
|
|
364
|
-
}
|
|
365
|
-
else {
|
|
366
|
-
// No persistence configured - keep document in memory for reconnections
|
|
367
|
-
console.log(`[Server] No persistence configured - keeping document ${doc.name} in memory for future connections`);
|
|
368
|
-
// logTreeStructure(doc.doc, `Document ${doc.name} structure before keeping in memory`)
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
conn.close();
|
|
373
|
-
};
|
|
374
|
-
/**
|
|
375
|
-
* @param {import('ws').WebSocket} conn
|
|
376
|
-
* @param {import('http').IncomingMessage} req
|
|
377
|
-
* @param {any} opts
|
|
378
|
-
*/
|
|
379
|
-
export const setupWSConnection = (conn, req, { docName = (req.url || '').slice(1).split('?')[0] } = {}) => {
|
|
380
|
-
conn.binaryType = 'arraybuffer';
|
|
381
|
-
// get doc, initialize if it does not exist yet
|
|
382
|
-
const doc = getDoc(docName);
|
|
383
|
-
// Assign a unique ID to the connection for logging
|
|
384
|
-
conn.id = `conn-${conn._socket?.remoteAddress || 'unknown'}:${conn._socket?.remotePort || Math.random()}`;
|
|
385
|
-
console.log(`New connection established: ${conn.id} for document: ${docName} (LoroDoc peerId: ${doc.doc.peerId})`);
|
|
386
|
-
doc.conns.set(conn, new Set());
|
|
387
|
-
// listen and reply to events
|
|
388
|
-
conn.on('message', message => messageListener(conn, doc, message));
|
|
389
|
-
// Check if connection is still alive
|
|
390
|
-
let pongReceived = true;
|
|
391
|
-
const pingInterval = setInterval(() => {
|
|
392
|
-
if (!pongReceived) {
|
|
393
|
-
if (doc.conns.has(conn)) {
|
|
394
|
-
closeConn(doc, conn);
|
|
395
|
-
}
|
|
396
|
-
clearInterval(pingInterval);
|
|
397
|
-
}
|
|
398
|
-
else if (doc.conns.has(conn)) {
|
|
399
|
-
pongReceived = false;
|
|
400
|
-
try {
|
|
401
|
-
conn.ping();
|
|
402
|
-
}
|
|
403
|
-
catch (e) {
|
|
404
|
-
closeConn(doc, conn);
|
|
405
|
-
clearInterval(pingInterval);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}, pingTimeout);
|
|
409
|
-
conn.on('close', () => {
|
|
410
|
-
closeConn(doc, conn);
|
|
411
|
-
clearInterval(pingInterval);
|
|
412
|
-
});
|
|
413
|
-
conn.on('pong', () => {
|
|
414
|
-
pongReceived = true;
|
|
415
|
-
});
|
|
416
|
-
// put the following in a variables in a block so the interval integrators don't keep in in
|
|
417
|
-
// scope
|
|
418
|
-
{
|
|
419
|
-
// Send initial snapshot to new client
|
|
420
|
-
// Log tree structure before creating initial snapshot
|
|
421
|
-
// logTreeStructure(doc.doc, `Before creating initial snapshot for new client ${conn.id}`)
|
|
422
|
-
try {
|
|
423
|
-
const snapshot = doc.doc.export({ mode: 'snapshot' });
|
|
424
|
-
console.log(`[Server] Sending initial snapshot to new client: ${snapshot.length} bytes`);
|
|
425
|
-
// Verify the snapshot contains expected content
|
|
426
|
-
const tree = doc.doc.getTree('tree');
|
|
427
|
-
const nodes = tree.nodes();
|
|
428
|
-
console.log(`[Server] Initial snapshot contains ${nodes.length} nodes from server document`);
|
|
429
|
-
// Send binary snapshot data directly instead of wrapped message
|
|
430
|
-
conn.send(snapshot);
|
|
431
|
-
}
|
|
432
|
-
catch (snapshotError) {
|
|
433
|
-
console.error(`[Server] ERROR creating/sending initial snapshot:`, snapshotError.message);
|
|
434
|
-
console.error(`[Server] Stack:`, snapshotError.stack);
|
|
435
|
-
}
|
|
436
|
-
// Send current ephemeral state if any
|
|
437
|
-
const ephemeralUpdate = doc.ephemeralStore.encodeAll();
|
|
438
|
-
if (ephemeralUpdate.length > 0) {
|
|
439
|
-
const ephemeralMessage = {
|
|
440
|
-
type: 'ephemeral',
|
|
441
|
-
ephemeral: Array.from(ephemeralUpdate),
|
|
442
|
-
docId: doc.name
|
|
443
|
-
};
|
|
444
|
-
sendMessage(doc, conn, ephemeralMessage);
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
export class WSSharedDoc {
|
|
449
|
-
name;
|
|
450
|
-
doc;
|
|
451
|
-
connections;
|
|
452
|
-
ephemeralStore;
|
|
453
|
-
conns;
|
|
454
|
-
_conns;
|
|
455
|
-
lastEphemeralSender;
|
|
456
|
-
constructor(name) {
|
|
457
|
-
this.name = name;
|
|
458
|
-
this.doc = new LoroDoc();
|
|
459
|
-
// Initialize the document with default Lexical content
|
|
460
|
-
console.log(`[Server] Initializing document '${name}' with default content`);
|
|
461
|
-
initializeLoroDocWithLexicalContent(this.doc);
|
|
462
|
-
/**
|
|
463
|
-
* Maps from conn to set of controlled ephemeral keys. Delete all keys when this conn is closed
|
|
464
|
-
* @type {Map<Object, Set<string>>}
|
|
465
|
-
*/
|
|
466
|
-
this.connections = new Map();
|
|
467
|
-
this.conns = new Map();
|
|
468
|
-
this._conns = new Set();
|
|
469
|
-
/**
|
|
470
|
-
* @type {EphemeralStore}
|
|
471
|
-
*/
|
|
472
|
-
this.ephemeralStore = new EphemeralStore(30000); // 30 second timeout
|
|
473
|
-
// Store the last sender to avoid echo loops
|
|
474
|
-
this.lastEphemeralSender = null;
|
|
475
|
-
/**
|
|
476
|
-
* @type {Array<function>}
|
|
477
|
-
*/
|
|
478
|
-
const ephemeralChangeIntegrator = (event) => {
|
|
479
|
-
// Only broadcast if there are actual changes
|
|
480
|
-
if (event.added.length > 0 || event.updated.length > 0 || event.removed.length > 0) {
|
|
481
|
-
try {
|
|
482
|
-
const encodedData = this.ephemeralStore.encodeAll();
|
|
483
|
-
// Skip broadcast if no actual data to send
|
|
484
|
-
if (encodedData.length === 0) {
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
const message = {
|
|
488
|
-
type: 'ephemeral',
|
|
489
|
-
ephemeral: Array.from(encodedData),
|
|
490
|
-
docId: this.name
|
|
491
|
-
};
|
|
492
|
-
// Broadcast to all connections EXCEPT the one that sent the last ephemeral update
|
|
493
|
-
this.conns.forEach((_, conn) => {
|
|
494
|
-
if (conn !== this.lastEphemeralSender) {
|
|
495
|
-
sendMessage(this, conn, message);
|
|
496
|
-
}
|
|
497
|
-
});
|
|
498
|
-
// Clear the sender reference after broadcast
|
|
499
|
-
this.lastEphemeralSender = null;
|
|
500
|
-
}
|
|
501
|
-
catch (broadcastError) {
|
|
502
|
-
console.warn(`[Server] ephemeralChangeIntegrator - ERROR broadcasting:`, {
|
|
503
|
-
error: broadcastError.message,
|
|
504
|
-
stack: broadcastError.stack
|
|
505
|
-
});
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
this.ephemeralStore.subscribe(ephemeralChangeIntegrator);
|
|
510
|
-
// Note: LoroDoc doesn't have 'on' method like Y.Doc
|
|
511
|
-
// Update handling will be done through message processing
|
|
512
|
-
}
|
|
513
|
-
}
|