@ecsplico/editor 2.1.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -1
- package/README.md +39 -156
- package/dist/adapters/comments/drizzle.d.ts +1 -1
- package/dist/adapters/comments/record.d.ts +15 -0
- package/dist/adapters/comments/{client.js → rest-model.js} +3 -3
- package/dist/adapters/comments/rest-model.js.map +1 -0
- package/dist/adapters/comments/server.d.ts +2 -1
- package/dist/adapters/comments/server.js +2 -1
- package/dist/adapters/comments/server.js.map +1 -1
- package/dist/adapters/comments/types.d.ts +2 -2
- package/dist/adapters/document-state.d.ts +23 -0
- package/dist/adapters/document-state.js +66 -0
- package/dist/adapters/document-state.js.map +1 -0
- package/dist/adapters/documents.js +14 -11
- package/dist/adapters/documents.js.map +1 -1
- package/dist/adapters/drizzle.d.ts +2 -2
- package/dist/adapters/drizzle.js +97 -88
- package/dist/adapters/drizzle.js.map +1 -1
- package/dist/adapters/forge.d.ts +12 -7
- package/dist/adapters/forge.js +38 -45
- package/dist/adapters/forge.js.map +1 -1
- package/dist/adapters/http.d.ts +20 -0
- package/dist/adapters/http.js +68 -0
- package/dist/adapters/http.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -5
- package/dist/adapters/json.d.ts +3 -3
- package/dist/adapters/json.js +58 -49
- package/dist/adapters/json.js.map +1 -1
- package/dist/adapters/memory.d.ts +21 -0
- package/dist/adapters/memory.js +53 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/nitro.d.ts +27 -20
- package/dist/adapters/nitro.js +59 -163
- package/dist/adapters/nitro.js.map +1 -1
- package/dist/adapters/react.d.ts +55 -0
- package/dist/adapters/react.js +209 -0
- package/dist/adapters/react.js.map +1 -0
- package/dist/adapters/shared.d.ts +15 -21
- package/dist/adapters/shared.js +10 -8
- package/dist/adapters/shared.js.map +1 -1
- package/dist/adapters/vue.d.ts +15 -30
- package/dist/adapters/vue.js +36 -87
- package/dist/adapters/vue.js.map +1 -1
- package/dist/code/CodeSurface.vue.d.ts +2 -2
- package/dist/config/index.d.ts +105 -0
- package/dist/config/index.js +95 -0
- package/dist/config/index.js.map +1 -0
- package/dist/core/abilities.js +1 -0
- package/dist/core/abilities.js.map +1 -1
- package/dist/{adapters/routes.js → core/api-routes.js} +5 -3
- package/dist/core/api-routes.js.map +1 -0
- package/dist/core/backend-capability.d.ts +7 -0
- package/dist/core/backend-capability.js +17 -0
- package/dist/core/backend-capability.js.map +1 -0
- package/dist/core/backend-types.d.ts +245 -0
- package/dist/core/backend-types.js +17 -0
- package/dist/core/backend-types.js.map +1 -0
- package/dist/core/backend.d.ts +108 -0
- package/dist/core/backend.js +14 -0
- package/dist/core/backend.js.map +1 -0
- package/dist/core/block-convert.d.ts +7 -5
- package/dist/core/block-convert.js +28 -5
- package/dist/core/block-convert.js.map +1 -1
- package/dist/core/command-types.d.ts +96 -0
- package/dist/core/commands.d.ts +40 -0
- package/dist/core/commands.js +151 -0
- package/dist/core/commands.js.map +1 -0
- package/dist/core/context.d.ts +17 -20
- package/dist/core/context.js +24 -21
- package/dist/core/context.js.map +1 -1
- package/dist/core/core-feature.d.ts +22 -7
- package/dist/core/core-feature.js +51 -18
- package/dist/core/core-feature.js.map +1 -1
- package/dist/core/define-editor.d.ts +4 -3
- package/dist/core/define-editor.js +14 -7
- package/dist/core/define-editor.js.map +1 -1
- package/dist/core/document-markdown.js +12 -3
- package/dist/core/document-markdown.js.map +1 -1
- package/dist/core/editor-ui.d.ts +8 -1
- package/dist/core/editor-ui.js +9 -8
- package/dist/core/editor-ui.js.map +1 -1
- package/dist/core/extension-points.d.ts +3 -15
- package/dist/core/feature-context.d.ts +8 -7
- package/dist/core/feature-context.js +12 -11
- package/dist/core/feature-context.js.map +1 -1
- package/dist/core/feature.d.ts +41 -19
- package/dist/core/feature.js.map +1 -1
- package/dist/core/fences.d.ts +2 -1
- package/dist/core/fences.js +3 -2
- package/dist/core/fences.js.map +1 -1
- package/dist/core/fetch-error.d.ts +1 -1
- package/dist/core/fetch-error.js +3 -1
- package/dist/core/fetch-error.js.map +1 -1
- package/dist/core/hash.d.ts +5 -0
- package/dist/core/hash.js +11 -0
- package/dist/core/hash.js.map +1 -0
- package/dist/core/http-backend.d.ts +11 -0
- package/dist/core/http-backend.js +195 -0
- package/dist/core/http-backend.js.map +1 -0
- package/dist/core/index.d.ts +15 -9
- package/dist/core/index.js +13 -9
- package/dist/core/palette.d.ts +48 -0
- package/dist/core/palette.js +95 -0
- package/dist/core/palette.js.map +1 -0
- package/dist/core/schema/abilities.d.ts +2 -1
- package/dist/core/schema/abilities.js +5 -1
- package/dist/core/schema/abilities.js.map +1 -1
- package/dist/core/schema/index.d.ts +11 -5
- package/dist/core/schema/index.js +13 -8
- package/dist/core/schema/index.js.map +1 -1
- package/dist/core/schema/mark-flags.d.ts +8 -1
- package/dist/core/schema/of-features.d.ts +13 -0
- package/dist/core/schema/of-features.js +14 -0
- package/dist/core/schema/of-features.js.map +1 -0
- package/dist/core/slash.d.ts +8 -6
- package/dist/core/slash.js +24 -16
- package/dist/core/slash.js.map +1 -1
- package/dist/core/surface-session.js +15 -5
- package/dist/core/surface-session.js.map +1 -1
- package/dist/core/toolbar-items.d.ts +10 -4
- package/dist/core/toolbar-items.js +269 -195
- package/dist/core/toolbar-items.js.map +1 -1
- package/dist/core/transaction-guards.d.ts +21 -0
- package/dist/core/transaction-guards.js +49 -0
- package/dist/core/transaction-guards.js.map +1 -0
- package/dist/core/util.js +11 -0
- package/dist/core/util.js.map +1 -0
- package/dist/document/DocumentSurface.d.ts +1 -1
- package/dist/document/DocumentSurface.vue.d.ts +2 -2
- package/dist/features/ai/agent-op-review.d.ts +1 -1
- package/dist/features/ai/agent-op-review.js +1 -1
- package/dist/features/ai/agent-ops.js +1 -1
- package/dist/features/ai/ai-apply.d.ts +2 -2
- package/dist/features/ai/ai-apply.js +1 -1
- package/dist/features/ai/ai-review.js +1 -1
- package/dist/features/ai/ai-sse.d.ts +6 -6
- package/dist/features/ai/ai-sse.js +20 -63
- package/dist/features/ai/ai-sse.js.map +1 -1
- package/dist/features/ai/assistant.d.ts +8 -7
- package/dist/features/ai/assistant.js +3 -3
- package/dist/features/ai/assistant.js.map +1 -1
- package/dist/features/ai/block-actions.d.ts +3 -2
- package/dist/features/ai/block-actions.js +3 -2
- package/dist/features/ai/block-actions.js.map +1 -1
- package/dist/features/ai/components/AiSelectionMenu.js +1 -1
- package/dist/features/ai/components/DocumentChatAnswer.js +1 -1
- package/dist/features/ai/components/DocumentChatOps.vue.d.ts +1 -1
- package/dist/features/ai/components/SettingsModelProfiles.js +8 -8
- package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/document-chat-model.d.ts +8 -7
- package/dist/features/ai/document-chat-model.js +5 -5
- package/dist/features/ai/document-chat-model.js.map +1 -1
- package/dist/features/ai/document-chat.js +1 -1
- package/dist/features/ai/feature.js +27 -14
- package/dist/features/ai/feature.js.map +1 -1
- package/dist/features/ai/ghost-autocomplete.d.ts +7 -6
- package/dist/features/ai/ghost-autocomplete.js +6 -9
- package/dist/features/ai/ghost-autocomplete.js.map +1 -1
- package/dist/features/ai/index.d.ts +4 -3
- package/dist/features/ai/index.js +10 -10
- package/dist/features/ai/model-profiles.d.ts +5 -4
- package/dist/features/ai/model-profiles.js +2 -2
- package/dist/features/ai/model-profiles.js.map +1 -1
- package/dist/features/ai/protocol/block-lines.js +1 -1
- package/dist/features/ai/protocol/block-lines.js.map +1 -1
- package/dist/features/ai/protocol/chat.js +6 -2
- package/dist/features/ai/protocol/chat.js.map +1 -1
- package/dist/features/ai/protocol/index.d.ts +3 -2
- package/dist/features/ai/protocol/models.d.ts +2 -16
- package/dist/features/ai/protocol/models.js.map +1 -1
- package/dist/features/ai/rate-limit.d.ts +1 -1
- package/dist/features/ai/rate-limit.js +3 -1
- package/dist/features/ai/rate-limit.js.map +1 -1
- package/dist/features/ai/react/AiSelectionMenu.js +2 -2
- package/dist/features/ai/react/AiSidebar.js +4 -4
- package/dist/features/ai/react/DocumentChatAnswer.js +1 -1
- package/dist/features/ai/react/DocumentChatOps.d.ts +1 -1
- package/dist/features/ai/react/DocumentChatOps.js +1 -1
- package/dist/features/ai/react/SettingsModelProfiles.js +8 -10
- package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
- package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/react/use-ai-assistant.js +3 -3
- package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/react/use-document-chat.js +2 -2
- package/dist/features/ai/react/use-document-chat.js.map +1 -1
- package/dist/features/ai/react/use-model-profiles.d.ts +2 -1
- package/dist/features/ai/selection-flow.d.ts +1 -1
- package/dist/features/ai/selection-flow.js +1 -1
- package/dist/features/ai/sidebar-flow.d.ts +1 -1
- package/dist/features/ai/sidebar-flow.js +1 -1
- package/dist/features/ai/use-ai-assistant.d.ts +1 -1
- package/dist/features/ai/use-ai-assistant.js +3 -3
- package/dist/features/ai/use-ai-assistant.js.map +1 -1
- package/dist/features/ai/use-document-chat.js +2 -2
- package/dist/features/ai/use-document-chat.js.map +1 -1
- package/dist/features/ai/use-model-profiles.d.ts +2 -1
- package/dist/features/authors/attribution.d.ts +1 -1
- package/dist/features/authors/feature.js +12 -11
- package/dist/features/authors/feature.js.map +1 -1
- package/dist/features/block-ui/block-actions.d.ts +1 -1
- package/dist/features/block-ui/block-actions.js +1 -1
- package/dist/features/block-ui/block-actions.js.map +1 -1
- package/dist/features/block-ui/components/BlockUi.js +1 -1
- package/dist/features/block-ui/feature.js +1 -0
- package/dist/features/block-ui/feature.js.map +1 -1
- package/dist/features/block-ui/react/BlockUi.js +1 -1
- package/dist/features/collab/anchor-resolver.js +1 -1
- package/dist/features/collab/feature.js +2 -0
- package/dist/features/collab/feature.js.map +1 -1
- package/dist/features/comments/components/CommentThreadView.vue.d.ts +2 -1
- package/dist/features/comments/feature.js +12 -11
- package/dist/features/comments/feature.js.map +1 -1
- package/dist/features/comments/index.d.ts +3 -2
- package/dist/features/comments/index.js +1 -1
- package/dist/features/comments/margin-layout.d.ts +3 -2
- package/dist/features/comments/model.d.ts +3 -67
- package/dist/features/comments/model.js +2 -2
- package/dist/features/comments/model.js.map +1 -1
- package/dist/features/comments/react/CommentThreadView.d.ts +3 -2
- package/dist/features/comments/react/use-comments.d.ts +2 -1
- package/dist/features/comments/react.d.ts +1 -1
- package/dist/features/comments/schema.d.ts +2 -52
- package/dist/features/comments/schema.js.map +1 -1
- package/dist/features/comments/snapshot-equality.js.map +1 -1
- package/dist/features/comments/use-comments.d.ts +3 -2
- package/dist/features/comments/vue.d.ts +1 -1
- package/dist/features/composites/accepted-children.d.ts +1 -0
- package/dist/features/composites/accepted-children.js +16 -1
- package/dist/features/composites/accepted-children.js.map +1 -1
- package/dist/features/composites/ai-brief.js +39 -0
- package/dist/features/composites/ai-brief.js.map +1 -1
- package/dist/features/composites/bibliography-command.d.ts +11 -0
- package/dist/features/composites/bibliography-form.js +90 -0
- package/dist/features/composites/bibliography-form.js.map +1 -0
- package/dist/features/composites/bibliography.d.ts +33 -0
- package/dist/features/composites/bibliography.js +120 -0
- package/dist/features/composites/bibliography.js.map +1 -0
- package/dist/features/composites/components/BibliographyEditor.js +261 -0
- package/dist/features/composites/components/BibliographyEditor.js.map +1 -0
- package/dist/features/composites/components/CompositeChrome.js +78 -29
- package/dist/features/composites/components/CompositeChrome.js.map +1 -1
- package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
- package/dist/features/composites/components/CompositeDetails.js +46 -11
- package/dist/features/composites/components/CompositeDetails.js.map +1 -1
- package/dist/features/composites/components/CompositeDetails.vue.d.ts +2 -1
- package/dist/features/composites/components/CompositeFieldEditor.js +64 -5
- package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/components/CompositeInspector.js +20 -7
- package/dist/features/composites/components/CompositeInspector.js.map +1 -1
- package/dist/features/composites/components/CompositeTable.js +13 -4
- package/dist/features/composites/components/CompositeTable.js.map +1 -1
- package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
- package/dist/features/composites/components/CompositeView.js +11 -1
- package/dist/features/composites/components/CompositeView.js.map +1 -1
- package/dist/features/composites/components/DerivationBadge.js +103 -0
- package/dist/features/composites/components/DerivationBadge.js.map +1 -0
- package/dist/features/composites/components/ReferenceFieldSelect.js +60 -0
- package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -0
- package/dist/features/composites/components/ReferenceView.js +122 -0
- package/dist/features/composites/components/ReferenceView.js.map +1 -0
- package/dist/features/composites/components/ReferenceView.vue.d.ts +96 -0
- package/dist/features/composites/components/SettingsEditingTab.js +1 -1
- package/dist/features/composites/convert.js +2 -2
- package/dist/features/composites/convert.js.map +1 -1
- package/dist/features/composites/derivation.d.ts +61 -0
- package/dist/features/composites/derivation.js +98 -0
- package/dist/features/composites/derivation.js.map +1 -0
- package/dist/features/composites/derived-chrome.js +69 -0
- package/dist/features/composites/derived-chrome.js.map +1 -0
- package/dist/features/composites/feature.js +159 -109
- package/dist/features/composites/feature.js.map +1 -1
- package/dist/features/composites/fences.d.ts +4 -3
- package/dist/features/composites/fences.js +51 -7
- package/dist/features/composites/fences.js.map +1 -1
- package/dist/features/composites/index.d.ts +12 -3
- package/dist/features/composites/index.js +15 -6
- package/dist/features/composites/inspector-model.d.ts +4 -1
- package/dist/features/composites/inspector-model.js +8 -4
- package/dist/features/composites/inspector-model.js.map +1 -1
- package/dist/features/composites/kinds.d.ts +16 -2
- package/dist/features/composites/kinds.js +145 -6
- package/dist/features/composites/kinds.js.map +1 -1
- package/dist/features/composites/legacy.d.ts +4 -1
- package/dist/features/composites/legacy.js +56 -1
- package/dist/features/composites/legacy.js.map +1 -1
- package/dist/features/composites/meta-display.js +45 -2
- package/dist/features/composites/meta-display.js.map +1 -1
- package/dist/features/composites/meta-keys.d.ts +7 -0
- package/dist/features/composites/meta-keys.js +21 -0
- package/dist/features/composites/meta-keys.js.map +1 -0
- package/dist/features/composites/node-views.d.ts +6 -3
- package/dist/features/composites/node-views.js +7 -3
- package/dist/features/composites/node-views.js.map +1 -1
- package/dist/features/composites/nodes.d.ts +6 -1
- package/dist/features/composites/nodes.js +33 -7
- package/dist/features/composites/nodes.js.map +1 -1
- package/dist/features/composites/react/BibliographyEditor.js +229 -0
- package/dist/features/composites/react/BibliographyEditor.js.map +1 -0
- package/dist/features/composites/react/CompositeChrome.js +67 -19
- package/dist/features/composites/react/CompositeChrome.js.map +1 -1
- package/dist/features/composites/react/CompositeDetails.d.ts +2 -1
- package/dist/features/composites/react/CompositeDetails.js +45 -6
- package/dist/features/composites/react/CompositeDetails.js.map +1 -1
- package/dist/features/composites/react/CompositeFieldEditor.d.ts +1 -1
- package/dist/features/composites/react/CompositeFieldEditor.js +43 -1
- package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
- package/dist/features/composites/react/CompositeInspector.js +12 -6
- package/dist/features/composites/react/CompositeInspector.js.map +1 -1
- package/dist/features/composites/react/CompositeStatusMenu.js +1 -1
- package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
- package/dist/features/composites/react/CompositeTable.js +16 -2
- package/dist/features/composites/react/CompositeTable.js.map +1 -1
- package/dist/features/composites/react/CompositeTagsEditor.js +2 -2
- package/dist/features/composites/react/CompositeView.js +6 -1
- package/dist/features/composites/react/CompositeView.js.map +1 -1
- package/dist/features/composites/react/DerivationBadge.js +116 -0
- package/dist/features/composites/react/DerivationBadge.js.map +1 -0
- package/dist/features/composites/react/ReferenceFieldSelect.js +52 -0
- package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -0
- package/dist/features/composites/react/ReferenceView.d.ts +11 -0
- package/dist/features/composites/react/ReferenceView.js +115 -0
- package/dist/features/composites/react/ReferenceView.js.map +1 -0
- package/dist/features/composites/react/SettingsEditingTab.js +2 -2
- package/dist/features/composites/react.d.ts +2 -1
- package/dist/features/composites/react.js +7 -3
- package/dist/features/composites/react.js.map +1 -1
- package/dist/features/composites/reference-ai.js +16 -0
- package/dist/features/composites/reference-ai.js.map +1 -0
- package/dist/features/composites/reference-label.d.ts +19 -0
- package/dist/features/composites/reference-label.js +58 -0
- package/dist/features/composites/reference-label.js.map +1 -0
- package/dist/features/composites/reference-suggestion.d.ts +10 -0
- package/dist/features/composites/reference-suggestion.js +41 -0
- package/dist/features/composites/reference-suggestion.js.map +1 -0
- package/dist/features/composites/reference-text.d.ts +18 -0
- package/dist/features/composites/reference-text.js +89 -0
- package/dist/features/composites/reference-text.js.map +1 -0
- package/dist/features/composites/reference.d.ts +44 -0
- package/dist/features/composites/reference.js +148 -0
- package/dist/features/composites/reference.js.map +1 -0
- package/dist/features/composites/reveal-source.d.ts +32 -0
- package/dist/features/composites/reveal-source.js +89 -0
- package/dist/features/composites/reveal-source.js.map +1 -0
- package/dist/features/composites/rows.d.ts +25 -3
- package/dist/features/composites/rows.js +72 -10
- package/dist/features/composites/rows.js.map +1 -1
- package/dist/features/composites/schema.d.ts +9 -3
- package/dist/features/composites/schema.js +11 -4
- package/dist/features/composites/schema.js.map +1 -1
- package/dist/features/composites/table-model.js +12 -21
- package/dist/features/composites/table-model.js.map +1 -1
- package/dist/features/composites/vue.d.ts +3 -2
- package/dist/features/composites/vue.js +8 -4
- package/dist/features/composites/vue.js.map +1 -1
- package/dist/features/media/assets.d.ts +2 -0
- package/dist/features/media/assets.js +3 -2
- package/dist/features/media/assets.js.map +1 -1
- package/dist/features/media/components/FileView.js +13 -4
- package/dist/features/media/components/FileView.js.map +1 -1
- package/dist/features/media/feature.d.ts +3 -3
- package/dist/features/media/feature.js +21 -28
- package/dist/features/media/feature.js.map +1 -1
- package/dist/features/media/file-import.js +2 -2
- package/dist/features/media/file-import.js.map +1 -1
- package/dist/features/media/index.d.ts +2 -2
- package/dist/features/media/index.js +3 -3
- package/dist/features/media/react/AudioRecorderModal.js +1 -1
- package/dist/features/media/react/FileView.js +19 -2
- package/dist/features/media/react/FileView.js.map +1 -1
- package/dist/features/media/react.js +1 -1
- package/dist/features/media/schema.d.ts +8 -0
- package/dist/features/media/schema.js +126 -11
- package/dist/features/media/schema.js.map +1 -1
- package/dist/features/media/upload.d.ts +16 -14
- package/dist/features/media/upload.js +13 -19
- package/dist/features/media/upload.js.map +1 -1
- package/dist/features/mentions/index.d.ts +4 -3
- package/dist/features/mentions/index.js +4 -1
- package/dist/features/mentions/index.js.map +1 -1
- package/dist/features/mentions/mention-text.d.ts +1 -1
- package/dist/features/mentions/mention-text.js.map +1 -1
- package/dist/features/mentions/mention.d.ts +0 -6
- package/dist/features/mentions/mention.js.map +1 -1
- package/dist/features/mentions/metadata-defaults.d.ts +2 -2
- package/dist/features/mentions/metadata-defaults.js +3 -9
- package/dist/features/mentions/metadata-defaults.js.map +1 -1
- package/dist/features/mentions/schema.d.ts +2 -1
- package/dist/features/mentions/schema.js.map +1 -1
- package/dist/features/tables/feature.d.ts +2 -1
- package/dist/features/tables/feature.js +90 -70
- package/dist/features/tables/feature.js.map +1 -1
- package/dist/features/themes/components/SettingsAppearanceTab.js +6 -9
- package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/feature.js +2 -0
- package/dist/features/themes/feature.js.map +1 -1
- package/dist/features/themes/index.d.ts +2 -1
- package/dist/features/themes/react/SettingsAppearanceTab.js +7 -10
- package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
- package/dist/features/themes/schema.d.ts +2 -6
- package/dist/features/themes/schema.js.map +1 -1
- package/dist/features/themes/theme-runtime.d.ts +1 -1
- package/dist/features/themes/theme-runtime.js +4 -2
- package/dist/features/themes/theme-runtime.js.map +1 -1
- package/dist/features/transcript/TranscriptSegmentView.js +48 -28
- package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/feature.js +21 -19
- package/dist/features/transcript/feature.js.map +1 -1
- package/dist/features/transcript/react/TranscriptSegmentView.js +55 -36
- package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
- package/dist/features/transcript/segment-node.d.ts +2 -0
- package/dist/features/transcript/segment-node.js +35 -7
- package/dist/features/transcript/segment-node.js.map +1 -1
- package/dist/i18n/de/composites.js +91 -1
- package/dist/i18n/de/composites.js.map +1 -1
- package/dist/i18n/de/integrations.js +49 -8
- package/dist/i18n/de/integrations.js.map +1 -1
- package/dist/i18n/de/media.js +0 -1
- package/dist/i18n/de/media.js.map +1 -1
- package/dist/i18n/de/palette.js +22 -0
- package/dist/i18n/de/palette.js.map +1 -0
- package/dist/i18n/de/tables.js +0 -1
- package/dist/i18n/de/tables.js.map +1 -1
- package/dist/i18n/de/transcript.js +2 -1
- package/dist/i18n/de/transcript.js.map +1 -1
- package/dist/i18n/de/tree.js +3 -0
- package/dist/i18n/de/tree.js.map +1 -1
- package/dist/i18n/de.d.ts +157 -11
- package/dist/i18n/de.js +3 -1
- package/dist/i18n/de.js.map +1 -1
- package/dist/i18n/en/composites.js +89 -1
- package/dist/i18n/en/composites.js.map +1 -1
- package/dist/i18n/en/integrations.js +49 -8
- package/dist/i18n/en/integrations.js.map +1 -1
- package/dist/i18n/en/media.js +0 -1
- package/dist/i18n/en/media.js.map +1 -1
- package/dist/i18n/en/palette.js +22 -0
- package/dist/i18n/en/palette.js.map +1 -0
- package/dist/i18n/en/tables.js +0 -1
- package/dist/i18n/en/tables.js.map +1 -1
- package/dist/i18n/en/transcript.js +2 -1
- package/dist/i18n/en/transcript.js.map +1 -1
- package/dist/i18n/en/tree.js +3 -0
- package/dist/i18n/en/tree.js.map +1 -1
- package/dist/i18n/en.js +3 -1
- package/dist/i18n/en.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/integrations/composite-ai/bibliography-fetch.d.ts +31 -0
- package/dist/integrations/composite-ai/bibliography-fetch.js +159 -0
- package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -0
- package/dist/integrations/composite-ai/composite-fill.d.ts +30 -8
- package/dist/integrations/composite-ai/composite-fill.js +97 -56
- package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
- package/dist/integrations/composite-ai/composite-summary.d.ts +4 -12
- package/dist/integrations/composite-ai/composite-summary.js +7 -26
- package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
- package/dist/integrations/composite-ai/derive.d.ts +29 -0
- package/dist/integrations/composite-ai/derive.js +173 -0
- package/dist/integrations/composite-ai/derive.js.map +1 -0
- package/dist/integrations/composite-ai/index.d.ts +11 -7
- package/dist/integrations/composite-ai/index.js +72 -14
- package/dist/integrations/composite-ai/index.js.map +1 -1
- package/dist/integrations/composite-ai/rendition.d.ts +45 -0
- package/dist/integrations/composite-ai/rendition.js +314 -0
- package/dist/integrations/composite-ai/rendition.js.map +1 -0
- package/dist/integrations/composite-media/index.d.ts +7 -5
- package/dist/integrations/composite-media/index.js +86 -13
- package/dist/integrations/composite-media/index.js.map +1 -1
- package/dist/integrations/transcript-ai/index.d.ts +1 -1
- package/dist/integrations/transcript-ai/index.js +5 -2
- package/dist/integrations/transcript-ai/index.js.map +1 -1
- package/dist/integrations/transcript-ai/protocol.d.ts +2 -12
- package/dist/integrations/transcript-ai/protocol.js +0 -2
- package/dist/integrations/transcript-ai/protocol.js.map +1 -1
- package/dist/integrations/transcript-ai/transcript-cleanup.d.ts +5 -5
- package/dist/integrations/transcript-ai/transcript-cleanup.js +7 -10
- package/dist/integrations/transcript-ai/transcript-cleanup.js.map +1 -1
- package/dist/markdown/MarkdownSurface.vue.d.ts +12 -11
- package/dist/markdown/MarkdownSurface2.js +3 -6
- package/dist/markdown/MarkdownSurface2.js.map +1 -1
- package/dist/markdown/document.js +1 -1
- package/dist/markdown/source-mode.d.ts +1 -1
- package/dist/nuxt/module.d.ts +1402 -54
- package/dist/nuxt/module.js +6 -49
- package/dist/nuxt/module.js.map +1 -1
- package/dist/nuxt/runtime/install-context.d.ts +7 -3
- package/dist/nuxt/runtime/install-context.js +14 -8
- package/dist/nuxt/runtime/install-context.js.map +1 -1
- package/dist/nuxt/runtime/plugins/editor-context-nuxt-ui.client.ts +2 -2
- package/dist/nuxt/runtime/server/plugins/editor-server.js +20 -12
- package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
- package/dist/presets/compose.d.ts +94 -0
- package/dist/presets/compose.js +164 -0
- package/dist/presets/compose.js.map +1 -0
- package/dist/react/AdvancedEditor.d.ts +15 -15
- package/dist/react/AdvancedEditor.js +15 -13
- package/dist/react/AdvancedEditor.js.map +1 -1
- package/dist/react/EditorCommandPalette.d.ts +13 -0
- package/dist/react/EditorCommandPalette.js +118 -0
- package/dist/react/EditorCommandPalette.js.map +1 -0
- package/dist/react/EditorSettingsModal.d.ts +5 -5
- package/dist/react/EditorSettingsModal.js +7 -4
- package/dist/react/EditorSettingsModal.js.map +1 -1
- package/dist/react/EditorSettingsPanel.d.ts +7 -7
- package/dist/react/EditorSettingsPanel.js +8 -5
- package/dist/react/EditorSettingsPanel.js.map +1 -1
- package/dist/react/EditorSurface.d.ts +7 -7
- package/dist/react/EditorSurface.js +10 -6
- package/dist/react/EditorSurface.js.map +1 -1
- package/dist/react/EditorToolbar.d.ts +4 -6
- package/dist/react/EditorToolbar.js +29 -37
- package/dist/react/EditorToolbar.js.map +1 -1
- package/dist/react/SimpleEditor.d.ts +22 -23
- package/dist/react/SimpleEditor.js +21 -7
- package/dist/react/SimpleEditor.js.map +1 -1
- package/dist/react/advanced.d.ts +4 -3
- package/dist/react/advanced.js +2 -2
- package/dist/react/compose.d.ts +20 -0
- package/dist/react/compose.js +49 -0
- package/dist/react/compose.js.map +1 -0
- package/dist/react/composed-surface.d.ts +39 -0
- package/dist/react/composed-surface.js +71 -0
- package/dist/react/composed-surface.js.map +1 -0
- package/dist/react/context.js +6 -2
- package/dist/react/context.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +2 -1
- package/dist/react/key-labels.js +15 -0
- package/dist/react/key-labels.js.map +1 -0
- package/dist/react/settings.d.ts +1 -1
- package/dist/react/simple.d.ts +2 -2
- package/dist/react/ui/command.js +36 -1
- package/dist/react/ui/command.js.map +1 -1
- package/dist/schema/advanced.d.ts +6 -6
- package/dist/schema/advanced.js +26 -29
- package/dist/schema/advanced.js.map +1 -1
- package/dist/server/ai.d.ts +5 -16
- package/dist/server/ai.js.map +1 -1
- package/dist/server/auth.d.ts +9 -0
- package/dist/server/collab-state.d.ts +1 -1
- package/dist/server/collab-state.js.map +1 -1
- package/dist/server/collab.d.ts +13 -13
- package/dist/server/collab.js +34 -18
- package/dist/server/collab.js.map +1 -1
- package/dist/server/crossref.js +78 -0
- package/dist/server/crossref.js.map +1 -0
- package/dist/server/errors.d.ts +1 -1
- package/dist/server/errors.js +1 -1
- package/dist/server/errors.js.map +1 -1
- package/dist/server/extract.js +308 -0
- package/dist/server/extract.js.map +1 -0
- package/dist/server/h3.d.ts +8 -0
- package/dist/{nuxt/runtime/server/utils/editor-route.js → server/h3.js} +8 -16
- package/dist/server/h3.js.map +1 -0
- package/dist/server/handlers/ai.d.ts +32 -10
- package/dist/server/handlers/ai.js +172 -37
- package/dist/server/handlers/ai.js.map +1 -1
- package/dist/server/handlers/context.d.ts +12 -5
- package/dist/server/handlers/context.js +10 -4
- package/dist/server/handlers/context.js.map +1 -1
- package/dist/server/handlers/editor.d.ts +19 -13
- package/dist/server/handlers/editor.js +49 -38
- package/dist/server/handlers/editor.js.map +1 -1
- package/dist/server/handlers/index.d.ts +4 -4
- package/dist/server/handlers/index.js +4 -4
- package/dist/server/host.d.ts +16 -25
- package/dist/server/host.js +58 -41
- package/dist/server/host.js.map +1 -1
- package/dist/server/index.d.ts +6 -4
- package/dist/server/index.js +3 -2
- package/dist/server/pdf.js +97 -0
- package/dist/server/pdf.js.map +1 -0
- package/dist/server/{adapter.d.ts → ports.d.ts} +81 -30
- package/dist/server/ports.js +29 -0
- package/dist/server/ports.js.map +1 -0
- package/dist/server/routes.d.ts +22 -0
- package/dist/server/routes.js +144 -0
- package/dist/server/routes.js.map +1 -0
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/index.js.map +1 -1
- package/dist/styles/composites.css +25 -0
- package/dist/tree/DocumentTree.js +56 -29
- package/dist/tree/DocumentTree.js.map +1 -1
- package/dist/tree/react/DocumentTree.js +23 -0
- package/dist/tree/react/DocumentTree.js.map +1 -1
- package/dist/tree/tree-host.js +2 -2
- package/dist/tree/tree-items.js +1 -1
- package/dist/vue/AdvancedEditor.js +30 -9
- package/dist/vue/AdvancedEditor.js.map +1 -1
- package/dist/vue/AdvancedEditor.vue.d.ts +32 -12
- package/dist/vue/SimpleEditor.js +62 -16
- package/dist/vue/SimpleEditor.js.map +1 -1
- package/dist/vue/SimpleEditor.vue.d.ts +39 -9
- package/dist/vue/advanced.d.ts +3 -2
- package/dist/vue/advanced.js +2 -2
- package/dist/vue/components/EditorCommandPalette.js +91 -0
- package/dist/vue/components/EditorCommandPalette.js.map +1 -0
- package/dist/vue/components/EditorCommandPalette.vue.d.ts +15 -0
- package/dist/vue/components/EditorSettingsModal.js +10 -6
- package/dist/vue/components/EditorSettingsModal.js.map +1 -1
- package/dist/vue/components/EditorSettingsModal.vue.d.ts +4 -4
- package/dist/vue/components/EditorSettingsPanel.js +10 -6
- package/dist/vue/components/EditorSettingsPanel.js.map +1 -1
- package/dist/vue/components/EditorSettingsPanel.vue.d.ts +6 -6
- package/dist/vue/components/EditorSurface.js +11 -6
- package/dist/vue/components/EditorSurface.js.map +1 -1
- package/dist/vue/components/EditorSurface.vue.d.ts +11 -11
- package/dist/vue/components/EditorToolbar.js +41 -49
- package/dist/vue/components/EditorToolbar.js.map +1 -1
- package/dist/vue/components/EditorToolbar.vue.d.ts +2 -4
- package/dist/vue/compose.d.ts +17 -0
- package/dist/vue/compose.js +51 -0
- package/dist/vue/compose.js.map +1 -0
- package/dist/vue/context-key.d.ts +6 -0
- package/dist/vue/context-key.js +6 -0
- package/dist/vue/context-key.js.map +1 -0
- package/dist/vue/context.d.ts +8 -6
- package/dist/vue/context.js +6 -5
- package/dist/vue/context.js.map +1 -1
- package/dist/vue/index.d.ts +10 -8
- package/dist/vue/index.js +10 -8
- package/dist/vue/kit/index.d.ts +2 -2
- package/dist/vue/kit/nuxt-ui.js +23 -0
- package/dist/vue/kit/nuxt-ui.js.map +1 -1
- package/dist/vue/kit/types.d.ts +40 -1
- package/package.json +30 -16
- package/dist/adapters/comments/client.d.ts +0 -64
- package/dist/adapters/comments/client.js.map +0 -1
- package/dist/adapters/routes.js.map +0 -1
- package/dist/core/toolbar.d.ts +0 -74
- package/dist/core/toolbar.js +0 -45
- package/dist/core/toolbar.js.map +0 -1
- package/dist/integrations/composite-ai/document-transcribe.d.ts +0 -14
- package/dist/integrations/composite-ai/document-transcribe.js +0 -89
- package/dist/integrations/composite-ai/document-transcribe.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/chat.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/chat.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/chat.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/complete.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/complete.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/complete.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/generate.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/generate.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/generate.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/models.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/models.get.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/models.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/transcribe.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/transcribe.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/transcribe.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js +0 -8
- package/dist/nuxt/runtime/server/api/ai/transcript-cleanup.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/assets/[id]/[name].get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/assets/[id].post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/assets/[id].post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/settings.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/settings.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/settings.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/settings.put.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/settings.put.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/settings.put.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/tags.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/tags.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/tags.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/[id].delete.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/[id].get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/[id].get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/index.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/index.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/index.get.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/themes/index.post.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/themes/index.post.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/themes/index.post.js.map +0 -1
- package/dist/nuxt/runtime/server/api/editor/users.get.d.ts +0 -5
- package/dist/nuxt/runtime/server/api/editor/users.get.js +0 -8
- package/dist/nuxt/runtime/server/api/editor/users.get.js.map +0 -1
- package/dist/nuxt/runtime/server/plugins/collab.d.ts +0 -5
- package/dist/nuxt/runtime/server/plugins/collab.js +0 -10
- package/dist/nuxt/runtime/server/plugins/collab.js.map +0 -1
- package/dist/nuxt/runtime/server/routes/collab/[id].d.ts +0 -5
- package/dist/nuxt/runtime/server/routes/collab/[id].js +0 -35
- package/dist/nuxt/runtime/server/routes/collab/[id].js.map +0 -1
- package/dist/nuxt/runtime/server/utils/editor-route.d.ts +0 -11
- package/dist/nuxt/runtime/server/utils/editor-route.js.map +0 -1
- package/dist/presets/advanced.d.ts +0 -33
- package/dist/presets/advanced.js +0 -50
- package/dist/presets/advanced.js.map +0 -1
- package/dist/presets/simple.d.ts +0 -9
- package/dist/presets/simple.js +0 -12
- package/dist/presets/simple.js.map +0 -1
- package/dist/react/advanced-preset.d.ts +0 -11
- package/dist/react/advanced-preset.js +0 -31
- package/dist/react/advanced-preset.js.map +0 -1
- package/dist/vue/advanced-preset.d.ts +0 -13
- package/dist/vue/advanced-preset.js +0 -33
- package/dist/vue/advanced-preset.js.map +0 -1
- package/docs/extending.md +0 -538
- package/docs/integration.md +0 -632
- package/docs/llms.md +0 -383
- package/docs/usage.md +0 -1076
package/dist/adapters/nitro.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { EditorAdapter } from "../server/adapter.js";
|
|
2
1
|
import { AiModels, AiModelsConfig } from "../server/ai.js";
|
|
2
|
+
import { EditorPorts } from "../server/ports.js";
|
|
3
3
|
import { CollabServer, CollabServerOptions } from "../server/collab.js";
|
|
4
4
|
import { RateLimiterOptions } from "../server/rate-limit.js";
|
|
5
5
|
import "../server/index.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { RouteDef } from "../server/routes.js";
|
|
7
|
+
import { AnyExtension } from "@tiptap/core";
|
|
8
8
|
import { Router } from "h3";
|
|
9
9
|
//#region src/adapters/nitro.d.ts
|
|
10
10
|
/** The part of a Nitro app this entry uses; `nitroApp` of a Nitro plugin fits. */
|
|
@@ -15,28 +15,33 @@ export interface NitroHost {
|
|
|
15
15
|
};
|
|
16
16
|
}
|
|
17
17
|
export interface EditorServerOptions {
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/** Identity, storage and everything else the backend serves, one port per capability: a route is mounted only when its port is present. A documents port that also manages documents (`json`, `drizzle`) lets `PUT /api/editor/documents/:id` create them; the `comments` port mounts the comments endpoint, `models` the host's language models. */
|
|
19
|
+
ports: EditorPorts;
|
|
20
20
|
/**
|
|
21
|
-
* The collaboration websocket (`/collab/:id`).
|
|
22
|
-
* `{}` takes everything from the
|
|
21
|
+
* The collaboration websocket (`/collab/:id`). Schema, hooks and Hocuspocus configuration of `createCollabServer`;
|
|
22
|
+
* `{}` takes everything from the ports (the `collabState` port is required). `false` mounts no websocket (documents then only load and save over HTTP).
|
|
23
|
+
* `authenticateUpgrade`: authenticate the upgrade request itself (`Identity.authenticate` with its headers; cookies,
|
|
24
|
+
* not the provider's `token`) and refuse it with HTTP 401, instead of closing an unauthenticated socket with 4401
|
|
25
|
+
* after the upgrade; the user then travels with the connection and is not authenticated a second time.
|
|
23
26
|
* Needs `experimental: { websocket: true }` in the Nitro config.
|
|
24
27
|
*/
|
|
25
|
-
collab: Omit<CollabServerOptions, '
|
|
28
|
+
collab: (Omit<CollabServerOptions, 'ports'> & {
|
|
29
|
+
authenticateUpgrade?: boolean;
|
|
30
|
+
}) | false;
|
|
26
31
|
/**
|
|
27
32
|
* Mounts the AI endpoints (`/api/ai/*`): presets, shared key, transcription, slots of `createAiModels`; `languageModel`
|
|
28
|
-
* and `listModels` default to the
|
|
33
|
+
* and `listModels` default to those of the `models` port. Omitted: no AI routes.
|
|
29
34
|
*/
|
|
30
35
|
ai?: Partial<AiModelsConfig>;
|
|
31
|
-
/** Per-user limit of the AI endpoints; default 30 requests per minute. */
|
|
36
|
+
/** Per-user limit of the AI endpoints; default: that of `defineEditorConfig` (30 requests per minute). */
|
|
32
37
|
rateLimit?: RateLimiterOptions;
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
/** Filters or reorders the routes before they are mounted (a host that serves `/api/editor/assets/*` itself drops them); default: all. Receives what `serverRoutesOf(ports, { ai })` returns, so a route of an absent port, or an AI route without the `ai` option, is not in it. */
|
|
39
|
+
routes?: (routes: readonly RouteDef[]) => readonly RouteDef[];
|
|
40
|
+
/** The collaboration schema (see `CollabServerOptions.schema`); default `advancedSchemaExtensions()`, host nodes: `() => [...advancedSchemaExtensions(), Callout]`. */
|
|
41
|
+
schema?: () => AnyExtension[];
|
|
37
42
|
}
|
|
38
43
|
export interface EditorServer {
|
|
39
|
-
|
|
44
|
+
ports: EditorPorts;
|
|
40
45
|
/** The collaboration server, `undefined` with `collab: false`. */
|
|
41
46
|
collab: CollabServer | undefined;
|
|
42
47
|
/** The AI models, `undefined` without `ai`. */
|
|
@@ -47,15 +52,17 @@ export interface EditorServer {
|
|
|
47
52
|
/**
|
|
48
53
|
* Wires the editor backend into `nitroApp` (call it from a Nitro plugin):
|
|
49
54
|
*
|
|
50
|
-
* /api/editor/{settings,users,tags,assets/…,themes/…} the editor's own endpoints
|
|
55
|
+
* /api/editor/{capabilities,settings,users,tags,assets/…,themes/…} the editor's own endpoints, each with its port; `capabilities` lists what is served
|
|
51
56
|
* /api/editor/documents/:id GET/PUT a document's TipTap JSON (what `useEditorDocument` uses)
|
|
52
|
-
* /api/editor/comments/:id GET/POST comments, with `comments`
|
|
53
|
-
* /api/ai/{models,chat,complete,generate,
|
|
57
|
+
* /api/editor/comments/:id GET/POST comments, with `ports.comments`
|
|
58
|
+
* /api/ai/{models,chat,complete,generate,extract,transcript-cleanup} with `ai`
|
|
54
59
|
* /collab/:id the collaboration websocket, unless `collab: false`
|
|
55
60
|
*
|
|
56
|
-
* Every route authenticates through `
|
|
57
|
-
* hook. The
|
|
61
|
+
* Every route authenticates through `ports.identity.authenticate`. The collaboration server is closed with Nitro's `close`
|
|
62
|
+
* hook. The installed server is also the process-wide one of `@ecsplico/editor/server` (`useCollabServer`, `useAiModels`,
|
|
63
|
+
* `liveContent`, …) until it closes. The paths are the ones the editor's client (`createHttpBackend`) calls.
|
|
58
64
|
*/
|
|
59
65
|
export declare function installEditorServer(nitroApp: NitroHost, options: EditorServerOptions): EditorServer;
|
|
60
66
|
//#endregion
|
|
67
|
+
export type { RouteDef };
|
|
61
68
|
//# sourceMappingURL=nitro.d.ts.map
|
package/dist/adapters/nitro.js
CHANGED
|
@@ -1,135 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { COLLAB_PATH } from "../core/api-routes.js";
|
|
2
2
|
import { createAiModels } from "../server/ai.js";
|
|
3
3
|
import { createCollabServer } from "../server/collab.js";
|
|
4
4
|
import { createRateLimiter } from "../server/rate-limit.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { adoptEditorServer } from "../server/host.js";
|
|
6
|
+
import { defineEditorConfig } from "../config/index.js";
|
|
7
|
+
import { routeOf } from "../server/h3.js";
|
|
8
|
+
import { serverRoutesOf } from "../server/routes.js";
|
|
9
|
+
import { defineWebSocketHandler } from "h3";
|
|
10
10
|
//#region src/adapters/nitro.ts
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
readForm: () => readFormData(event),
|
|
22
|
-
signal: abort.signal
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
/** An event handler that runs `handler` with `ctx` and sends its `HandlerResponse`; an `HttpError` becomes Nitro's error response. */
|
|
26
|
-
function routeOf(ctx, handler) {
|
|
27
|
-
return defineEventHandler(async (event) => {
|
|
28
|
-
let response;
|
|
29
|
-
try {
|
|
30
|
-
response = await handler(ctx, requestOf(event));
|
|
31
|
-
} catch (error) {
|
|
32
|
-
if (!(error instanceof HttpError)) throw error;
|
|
33
|
-
setResponseHeaders(event, error.headers);
|
|
34
|
-
throw createError({
|
|
35
|
-
statusCode: error.statusCode,
|
|
36
|
-
statusMessage: error.statusMessage,
|
|
37
|
-
message: error.statusMessage,
|
|
38
|
-
data: error.data
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
setResponseStatus(event, response.status);
|
|
42
|
-
setResponseHeaders(event, response.headers);
|
|
43
|
-
return response.body;
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
const editorRoutes = [
|
|
47
|
-
[
|
|
48
|
-
"get",
|
|
49
|
-
`${API}/settings`,
|
|
50
|
-
settingsGet
|
|
51
|
-
],
|
|
52
|
-
[
|
|
53
|
-
"put",
|
|
54
|
-
`${API}/settings`,
|
|
55
|
-
settingsPut
|
|
56
|
-
],
|
|
57
|
-
[
|
|
58
|
-
"get",
|
|
59
|
-
`${API}/users`,
|
|
60
|
-
usersGet
|
|
61
|
-
],
|
|
62
|
-
[
|
|
63
|
-
"get",
|
|
64
|
-
`${API}/tags`,
|
|
65
|
-
tagsGet
|
|
66
|
-
],
|
|
67
|
-
[
|
|
68
|
-
"post",
|
|
69
|
-
`${API}/assets/:id`,
|
|
70
|
-
assetPost
|
|
71
|
-
],
|
|
72
|
-
[
|
|
73
|
-
"get",
|
|
74
|
-
`${API}/assets/:id/:name`,
|
|
75
|
-
assetGet
|
|
76
|
-
],
|
|
77
|
-
[
|
|
78
|
-
"get",
|
|
79
|
-
`${API}/themes`,
|
|
80
|
-
themesGet
|
|
81
|
-
],
|
|
82
|
-
[
|
|
83
|
-
"post",
|
|
84
|
-
`${API}/themes`,
|
|
85
|
-
themePost
|
|
86
|
-
],
|
|
87
|
-
[
|
|
88
|
-
"get",
|
|
89
|
-
`${API}/themes/:id`,
|
|
90
|
-
themeGet
|
|
91
|
-
],
|
|
92
|
-
[
|
|
93
|
-
"delete",
|
|
94
|
-
`${API}/themes/:id`,
|
|
95
|
-
themeDelete
|
|
96
|
-
]
|
|
97
|
-
];
|
|
98
|
-
const aiRoutes = [
|
|
99
|
-
[
|
|
100
|
-
"get",
|
|
101
|
-
`${AI_API}/models`,
|
|
102
|
-
modelsGet
|
|
103
|
-
],
|
|
104
|
-
[
|
|
105
|
-
"post",
|
|
106
|
-
`${AI_API}/chat`,
|
|
107
|
-
chatPost
|
|
108
|
-
],
|
|
109
|
-
[
|
|
110
|
-
"post",
|
|
111
|
-
`${AI_API}/complete`,
|
|
112
|
-
completePost
|
|
113
|
-
],
|
|
114
|
-
[
|
|
115
|
-
"post",
|
|
116
|
-
`${AI_API}/generate`,
|
|
117
|
-
generatePost
|
|
118
|
-
],
|
|
119
|
-
[
|
|
120
|
-
"post",
|
|
121
|
-
`${AI_API}/transcribe`,
|
|
122
|
-
transcribePost
|
|
123
|
-
],
|
|
124
|
-
[
|
|
125
|
-
"post",
|
|
126
|
-
`${AI_API}/transcript-cleanup`,
|
|
127
|
-
transcriptCleanupPost
|
|
128
|
-
]
|
|
129
|
-
];
|
|
130
|
-
const collabRoute = (collab) => defineWebSocketHandler({
|
|
11
|
+
const collabRoute = (collab, ports, authenticateUpgrade) => defineWebSocketHandler({
|
|
12
|
+
async upgrade(request) {
|
|
13
|
+
if (!authenticateUpgrade) return;
|
|
14
|
+
const user = await ports.identity.authenticate({ headers: request.headers });
|
|
15
|
+
if (!user) return new Response(null, {
|
|
16
|
+
status: 401,
|
|
17
|
+
statusText: "Unauthorized"
|
|
18
|
+
});
|
|
19
|
+
request.context.user = user;
|
|
20
|
+
},
|
|
131
21
|
open(peer) {
|
|
132
|
-
|
|
22
|
+
const user = peer.context.user;
|
|
23
|
+
peer._hocuspocus = collab.handleConnection(peer.websocket, peer.request, user && { user });
|
|
133
24
|
},
|
|
134
25
|
message(peer, message) {
|
|
135
26
|
peer._hocuspocus?.handleMessage(message.uint8Array());
|
|
@@ -147,60 +38,65 @@ const collabRoute = (collab) => defineWebSocketHandler({
|
|
|
147
38
|
/**
|
|
148
39
|
* Wires the editor backend into `nitroApp` (call it from a Nitro plugin):
|
|
149
40
|
*
|
|
150
|
-
* /api/editor/{settings,users,tags,assets/…,themes/…} the editor's own endpoints
|
|
41
|
+
* /api/editor/{capabilities,settings,users,tags,assets/…,themes/…} the editor's own endpoints, each with its port; `capabilities` lists what is served
|
|
151
42
|
* /api/editor/documents/:id GET/PUT a document's TipTap JSON (what `useEditorDocument` uses)
|
|
152
|
-
* /api/editor/comments/:id GET/POST comments, with `comments`
|
|
153
|
-
* /api/ai/{models,chat,complete,generate,
|
|
43
|
+
* /api/editor/comments/:id GET/POST comments, with `ports.comments`
|
|
44
|
+
* /api/ai/{models,chat,complete,generate,extract,transcript-cleanup} with `ai`
|
|
154
45
|
* /collab/:id the collaboration websocket, unless `collab: false`
|
|
155
46
|
*
|
|
156
|
-
* Every route authenticates through `
|
|
157
|
-
* hook. The
|
|
47
|
+
* Every route authenticates through `ports.identity.authenticate`. The collaboration server is closed with Nitro's `close`
|
|
48
|
+
* hook. The installed server is also the process-wide one of `@ecsplico/editor/server` (`useCollabServer`, `useAiModels`,
|
|
49
|
+
* `liveContent`, …) until it closes. The paths are the ones the editor's client (`createHttpBackend`) calls.
|
|
158
50
|
*/
|
|
159
51
|
function installEditorServer(nitroApp, options) {
|
|
160
|
-
const {
|
|
52
|
+
const { ports, schema } = options;
|
|
53
|
+
const { authenticateUpgrade = false, ...collabOptions } = options.collab || {};
|
|
161
54
|
const collab = options.collab === false ? void 0 : createCollabServer({
|
|
162
|
-
|
|
163
|
-
...
|
|
55
|
+
ports,
|
|
56
|
+
...schema && { schema },
|
|
57
|
+
...collabOptions
|
|
164
58
|
});
|
|
59
|
+
const provider = ports.models;
|
|
165
60
|
const models = options.ai && createAiModels({
|
|
166
61
|
presets: {},
|
|
167
|
-
languageModel:
|
|
168
|
-
listModels:
|
|
62
|
+
languageModel: provider?.languageModel && ((ref, user) => provider.languageModel(ref, user)),
|
|
63
|
+
listModels: provider?.listModels && ((user) => provider.listModels(user)),
|
|
169
64
|
...options.ai
|
|
170
65
|
});
|
|
66
|
+
const limiter = models && createRateLimiter(options.rateLimit ?? defineEditorConfig().ai.rateLimit);
|
|
171
67
|
const context = {
|
|
172
|
-
|
|
173
|
-
...collab && { collab }
|
|
68
|
+
ports,
|
|
69
|
+
...collab && { collab },
|
|
70
|
+
served: {
|
|
71
|
+
ai: models !== void 0,
|
|
72
|
+
collaboration: collab !== void 0
|
|
73
|
+
}
|
|
174
74
|
};
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
nitroApp.router.add(
|
|
184
|
-
nitroApp.router.add(COMMENTS_ROUTE, routeOf(comments, commentsPost), "post");
|
|
185
|
-
}
|
|
186
|
-
if (models) {
|
|
187
|
-
const ai = {
|
|
188
|
-
...context,
|
|
189
|
-
ai: models,
|
|
190
|
-
limiter: createRateLimiter(options.rateLimit ?? {
|
|
191
|
-
max: 30,
|
|
192
|
-
windowMs: 6e4
|
|
193
|
-
})
|
|
194
|
-
};
|
|
195
|
-
for (const [method, path, handler] of aiRoutes) nitroApp.router.add(path, routeOf(ai, handler), method);
|
|
75
|
+
const aiContext = models && limiter && {
|
|
76
|
+
...context,
|
|
77
|
+
ai: models,
|
|
78
|
+
limiter
|
|
79
|
+
};
|
|
80
|
+
const mounted = serverRoutesOf(ports, { ai: aiContext !== void 0 });
|
|
81
|
+
for (const route of options.routes ? options.routes(mounted) : mounted) {
|
|
82
|
+
const handler = route.port === "ai" ? routeOf(aiContext, route.handler) : routeOf(context, route.handler);
|
|
83
|
+
nitroApp.router.add(route.path, handler, route.method);
|
|
196
84
|
}
|
|
197
|
-
if (collab) nitroApp.router.use(`${COLLAB_PATH}/:id`, collabRoute(collab));
|
|
85
|
+
if (collab) nitroApp.router.use(`${COLLAB_PATH}/:id`, collabRoute(collab, ports, authenticateUpgrade));
|
|
86
|
+
const release = adoptEditorServer({
|
|
87
|
+
ports,
|
|
88
|
+
schema,
|
|
89
|
+
collab,
|
|
90
|
+
models,
|
|
91
|
+
limiter
|
|
92
|
+
});
|
|
198
93
|
const server = {
|
|
199
|
-
|
|
94
|
+
ports,
|
|
200
95
|
collab,
|
|
201
96
|
models,
|
|
202
|
-
|
|
97
|
+
async close() {
|
|
203
98
|
await collab?.close();
|
|
99
|
+
release();
|
|
204
100
|
}
|
|
205
101
|
};
|
|
206
102
|
nitroApp.hooks.hook("close", () => server.close());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nitro.js","names":[],"sources":["../../src/adapters/nitro.ts"],"sourcesContent":["import { type AiModels, type AiModelsConfig, type CollabConnection, type CollabServer, type CollabServerOptions, createAiModels, createCollabServer, createRateLimiter, type EditorAdapter, HttpError, type RateLimiterOptions } from '../server'\nimport {\n type AiHandlerContext,\n assetGet,\n assetPost,\n chatPost,\n completePost,\n generatePost,\n type HandlerContext,\n type HandlerRequest,\n type HandlerResponse,\n modelsGet,\n settingsGet,\n settingsPut,\n tagsGet,\n themeDelete,\n themeGet,\n themePost,\n themesGet,\n transcribePost,\n transcriptCleanupPost,\n usersGet,\n} from '../server/handlers'\nimport { createError, defineEventHandler, defineWebSocketHandler, getQuery, getRouterParams, type H3Event, readBody, readFormData, type Router, setResponseHeaders, setResponseStatus } from 'h3'\nimport type { DocumentAdmin } from './shared'\nimport type { CommentStore } from './comments/types'\nimport { AI_API, COLLAB_PATH, COMMENTS_ROUTE, DOCUMENT_ROUTE, EDITOR_API } from './routes'\nimport { commentsGet, type CommentsRouteContext, commentsPost, type DocumentsContext, documentGet, documentPut } from './documents'\n\n// The editor backend on a plain Nitro app (nitropack 2, no Nuxt module): the framework's own routes (settings, users,\n// tags, assets, themes, the optional AI endpoints), the collaboration websocket and this package's document and comments\n// routes, registered in one call from a Nitro plugin. It is the explicit-wiring twin of `@ecsplico/editor/nuxt`, which\n// registers the same routes by scanning files; both end in the same `@ecsplico/editor/server/handlers`.\n\n/** The part of a Nitro app this entry uses; `nitroApp` of a Nitro plugin fits. */\nexport interface NitroHost {\n router: Pick<Router, 'add' | 'use'>\n hooks: { hook(name: 'close', listener: () => void | Promise<void>): unknown }\n}\n\nexport interface EditorServerOptions {\n /** Storage and identity. An adapter that also manages documents (`json`, `drizzle`) lets `PUT /api/editor/documents/:id` create them. */\n adapter: EditorAdapter & Partial<DocumentAdmin>\n /**\n * The collaboration websocket (`/collab/:id`). Extensions, hooks and Hocuspocus configuration of `createCollabServer`;\n * `{}` takes everything from the adapter. `false` mounts no websocket (documents then only load and save over HTTP).\n * Needs `experimental: { websocket: true }` in the Nitro config.\n */\n collab: Omit<CollabServerOptions, 'adapter'> | false\n /**\n * Mounts the AI endpoints (`/api/ai/*`): presets, shared key, transcription, slots of `createAiModels`; `languageModel`\n * and `listModels` default to the adapter's. Omitted: no AI routes.\n */\n ai?: Partial<AiModelsConfig>\n /** Per-user limit of the AI endpoints; default 30 requests per minute. */\n rateLimit?: RateLimiterOptions\n /** Mounts the comments endpoint (`/api/editor/comments/:id`) over this store; omitted: no comments routes. */\n comments?: { store: CommentStore }\n}\n\nexport interface EditorServer {\n adapter: EditorServerOptions['adapter']\n /** The collaboration server, `undefined` with `collab: false`. */\n collab: CollabServer | undefined\n /** The AI models, `undefined` without `ai`. */\n models: AiModels | undefined\n /** Writes pending collaboration stores and disconnects every client. Nitro's `close` hook calls it. */\n close(): Promise<void>\n}\n\ntype Method = 'get' | 'post' | 'put' | 'delete'\ntype Handler<C> = (ctx: C, request: HandlerRequest) => Promise<HandlerResponse>\n\nconst API = EDITOR_API\n\n/** The `HandlerRequest` of a Nitro event. `signal` aborts when the client goes away. */\nfunction requestOf(event: H3Event): HandlerRequest {\n const abort = new AbortController()\n event.node.res.once('close', () => abort.abort())\n return {\n headers: event.headers,\n params: getRouterParams(event, { decode: true }),\n query: Object.fromEntries(Object.entries(getQuery(event)).map(([key, value]) => [key, value === undefined ? undefined : String(value)])),\n readJson: () => readBody(event),\n readForm: () => readFormData(event),\n signal: abort.signal,\n }\n}\n\n/** An event handler that runs `handler` with `ctx` and sends its `HandlerResponse`; an `HttpError` becomes Nitro's error response. */\nfunction routeOf<C>(ctx: C, handler: Handler<C>) {\n return defineEventHandler(async (event) => {\n let response: HandlerResponse\n try {\n response = await handler(ctx, requestOf(event))\n }\n catch (error) {\n if (!(error instanceof HttpError)) throw error\n setResponseHeaders(event, error.headers)\n throw createError({ statusCode: error.statusCode, statusMessage: error.statusMessage, message: error.statusMessage, data: error.data })\n }\n setResponseStatus(event, response.status)\n setResponseHeaders(event, response.headers)\n // `null` ends the response without a body and keeps the status set above.\n return response.body\n })\n}\n\nconst editorRoutes: [Method, string, Handler<HandlerContext>][] = [\n ['get', `${API}/settings`, settingsGet],\n ['put', `${API}/settings`, settingsPut],\n ['get', `${API}/users`, usersGet],\n ['get', `${API}/tags`, tagsGet],\n ['post', `${API}/assets/:id`, assetPost],\n ['get', `${API}/assets/:id/:name`, assetGet],\n ['get', `${API}/themes`, themesGet],\n ['post', `${API}/themes`, themePost],\n ['get', `${API}/themes/:id`, themeGet],\n ['delete', `${API}/themes/:id`, themeDelete],\n]\n\nconst aiRoutes: [Method, string, Handler<AiHandlerContext>][] = [\n ['get', `${AI_API}/models`, modelsGet],\n ['post', `${AI_API}/chat`, chatPost],\n ['post', `${AI_API}/complete`, completePost],\n ['post', `${AI_API}/generate`, generatePost],\n ['post', `${AI_API}/transcribe`, transcribePost],\n ['post', `${AI_API}/transcript-cleanup`, transcriptCleanupPost],\n]\n\ntype CollabPeer = { _hocuspocus?: CollabConnection }\n\nconst collabRoute = (collab: CollabServer) => defineWebSocketHandler({\n open(peer) {\n ;(peer as unknown as CollabPeer)._hocuspocus = collab.handleConnection(peer.websocket as unknown as Parameters<CollabServer['handleConnection']>[0], peer.request as Request)\n },\n message(peer, message) {\n ;(peer as unknown as CollabPeer)._hocuspocus?.handleMessage(message.uint8Array())\n },\n close(peer, details) {\n ;(peer as unknown as CollabPeer)._hocuspocus?.handleClose({ code: details.code ?? 1000, reason: details.reason ?? '' } as CloseEvent)\n },\n error(peer, error) {\n console.error('[collab]', peer.id, error)\n },\n})\n\n/**\n * Wires the editor backend into `nitroApp` (call it from a Nitro plugin):\n *\n * /api/editor/{settings,users,tags,assets/…,themes/…} the editor's own endpoints\n * /api/editor/documents/:id GET/PUT a document's TipTap JSON (what `useEditorDocument` uses)\n * /api/editor/comments/:id GET/POST comments, with `comments`\n * /api/ai/{models,chat,complete,generate,transcribe,transcript-cleanup} with `ai`\n * /collab/:id the collaboration websocket, unless `collab: false`\n *\n * Every route authenticates through `adapter.authenticate`. The collaboration server is closed with Nitro's `close`\n * hook. The paths are the ones `@ecsplico/editor/nuxt` serves, so the editor's client works unchanged.\n */\nexport function installEditorServer(nitroApp: NitroHost, options: EditorServerOptions): EditorServer {\n const { adapter } = options\n const collab = options.collab === false ? undefined : createCollabServer({ adapter, ...options.collab })\n const models = options.ai && createAiModels({\n presets: {},\n languageModel: adapter.languageModel && ((ref, user) => adapter.languageModel!(ref, user)),\n listModels: adapter.listModels && (user => adapter.listModels!(user)),\n ...options.ai,\n })\n\n const context: DocumentsContext = { adapter, ...(collab && { collab }) }\n for (const [method, path, handler] of editorRoutes) nitroApp.router.add(path, routeOf<HandlerContext>(context, handler), method)\n nitroApp.router.add(DOCUMENT_ROUTE, routeOf(context, documentGet), 'get')\n nitroApp.router.add(DOCUMENT_ROUTE, routeOf(context, documentPut), 'put')\n\n if (options.comments) {\n const comments: CommentsRouteContext = { ...context, store: options.comments.store }\n nitroApp.router.add(COMMENTS_ROUTE, routeOf(comments, commentsGet), 'get')\n nitroApp.router.add(COMMENTS_ROUTE, routeOf(comments, commentsPost), 'post')\n }\n if (models) {\n const ai: AiHandlerContext = { ...context, ai: models, limiter: createRateLimiter(options.rateLimit ?? { max: 30, windowMs: 60_000 }) }\n for (const [method, path, handler] of aiRoutes) nitroApp.router.add(path, routeOf(ai, handler), method)\n }\n // No method: the websocket upgrade resolves its handler by path only.\n if (collab) nitroApp.router.use(`${COLLAB_PATH}/:id`, collabRoute(collab))\n\n const server: EditorServer = { adapter, collab, models, close: async () => { await collab?.close() } }\n nitroApp.hooks.hook('close', () => server.close())\n return server\n}\n"],"mappings":";;;;;;;;;;AAyEA,MAAM,MAAM;;AAGZ,SAAS,UAAU,OAAgC;CACjD,MAAM,QAAQ,IAAI,gBAAgB;CAClC,MAAM,KAAK,IAAI,KAAK,eAAe,MAAM,MAAM,CAAC;CAChD,OAAO;EACL,SAAS,MAAM;EACf,QAAQ,gBAAgB,OAAO,EAAE,QAAQ,KAAK,CAAC;EAC/C,OAAO,OAAO,YAAY,OAAO,QAAQ,SAAS,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU,KAAA,IAAY,KAAA,IAAY,OAAO,KAAK,CAAC,CAAC,CAAC;EACvI,gBAAgB,SAAS,KAAK;EAC9B,gBAAgB,aAAa,KAAK;EAClC,QAAQ,MAAM;CAChB;AACF;;AAGA,SAAS,QAAW,KAAQ,SAAqB;CAC/C,OAAO,mBAAmB,OAAO,UAAU;EACzC,IAAI;EACJ,IAAI;GACF,WAAW,MAAM,QAAQ,KAAK,UAAU,KAAK,CAAC;EAChD,SACO,OAAO;GACZ,IAAI,EAAE,iBAAiB,YAAY,MAAM;GACzC,mBAAmB,OAAO,MAAM,OAAO;GACvC,MAAM,YAAY;IAAE,YAAY,MAAM;IAAY,eAAe,MAAM;IAAe,SAAS,MAAM;IAAe,MAAM,MAAM;GAAK,CAAC;EACxI;EACA,kBAAkB,OAAO,SAAS,MAAM;EACxC,mBAAmB,OAAO,SAAS,OAAO;EAE1C,OAAO,SAAS;CAClB,CAAC;AACH;AAEA,MAAM,eAA4D;CAChE;EAAC;EAAO,GAAG,IAAI;EAAY;CAAW;CACtC;EAAC;EAAO,GAAG,IAAI;EAAY;CAAW;CACtC;EAAC;EAAO,GAAG,IAAI;EAAS;CAAQ;CAChC;EAAC;EAAO,GAAG,IAAI;EAAQ;CAAO;CAC9B;EAAC;EAAQ,GAAG,IAAI;EAAc;CAAS;CACvC;EAAC;EAAO,GAAG,IAAI;EAAoB;CAAQ;CAC3C;EAAC;EAAO,GAAG,IAAI;EAAU;CAAS;CAClC;EAAC;EAAQ,GAAG,IAAI;EAAU;CAAS;CACnC;EAAC;EAAO,GAAG,IAAI;EAAc;CAAQ;CACrC;EAAC;EAAU,GAAG,IAAI;EAAc;CAAW;AAC7C;AAEA,MAAM,WAA0D;CAC9D;EAAC;EAAO,GAAG,OAAO;EAAU;CAAS;CACrC;EAAC;EAAQ,GAAG,OAAO;EAAQ;CAAQ;CACnC;EAAC;EAAQ,GAAG,OAAO;EAAY;CAAY;CAC3C;EAAC;EAAQ,GAAG,OAAO;EAAY;CAAY;CAC3C;EAAC;EAAQ,GAAG,OAAO;EAAc;CAAc;CAC/C;EAAC;EAAQ,GAAG,OAAO;EAAsB;CAAqB;AAChE;AAIA,MAAM,eAAe,WAAyB,uBAAuB;CACnE,KAAK,MAAM;EACR,KAAgC,cAAc,OAAO,iBAAiB,KAAK,WAAyE,KAAK,OAAkB;CAC9K;CACA,QAAQ,MAAM,SAAS;EACpB,KAAgC,aAAa,cAAc,QAAQ,WAAW,CAAC;CAClF;CACA,MAAM,MAAM,SAAS;EAClB,KAAgC,aAAa,YAAY;GAAE,MAAM,QAAQ,QAAQ;GAAM,QAAQ,QAAQ,UAAU;EAAG,CAAe;CACtI;CACA,MAAM,MAAM,OAAO;EACjB,QAAQ,MAAM,YAAY,KAAK,IAAI,KAAK;CAC1C;AACF,CAAC;;;;;;;;;;;;;AAcD,SAAgB,oBAAoB,UAAqB,SAA4C;CACnG,MAAM,EAAE,YAAY;CACpB,MAAM,SAAS,QAAQ,WAAW,QAAQ,KAAA,IAAY,mBAAmB;EAAE;EAAS,GAAG,QAAQ;CAAO,CAAC;CACvG,MAAM,SAAS,QAAQ,MAAM,eAAe;EAC1C,SAAS,CAAC;EACV,eAAe,QAAQ,mBAAmB,KAAK,SAAS,QAAQ,cAAe,KAAK,IAAI;EACxF,YAAY,QAAQ,gBAAe,SAAQ,QAAQ,WAAY,IAAI;EACnE,GAAG,QAAQ;CACb,CAAC;CAED,MAAM,UAA4B;EAAE;EAAS,GAAI,UAAU,EAAE,OAAO;CAAG;CACvE,KAAK,MAAM,CAAC,QAAQ,MAAM,YAAY,cAAc,SAAS,OAAO,IAAI,MAAM,QAAwB,SAAS,OAAO,GAAG,MAAM;CAC/H,SAAS,OAAO,IAAI,gBAAgB,QAAQ,SAAS,WAAW,GAAG,KAAK;CACxE,SAAS,OAAO,IAAI,gBAAgB,QAAQ,SAAS,WAAW,GAAG,KAAK;CAExE,IAAI,QAAQ,UAAU;EACpB,MAAM,WAAiC;GAAE,GAAG;GAAS,OAAO,QAAQ,SAAS;EAAM;EACnF,SAAS,OAAO,IAAI,gBAAgB,QAAQ,UAAU,WAAW,GAAG,KAAK;EACzE,SAAS,OAAO,IAAI,gBAAgB,QAAQ,UAAU,YAAY,GAAG,MAAM;CAC7E;CACA,IAAI,QAAQ;EACV,MAAM,KAAuB;GAAE,GAAG;GAAS,IAAI;GAAQ,SAAS,kBAAkB,QAAQ,aAAa;IAAE,KAAK;IAAI,UAAU;GAAO,CAAC;EAAE;EACtI,KAAK,MAAM,CAAC,QAAQ,MAAM,YAAY,UAAU,SAAS,OAAO,IAAI,MAAM,QAAQ,IAAI,OAAO,GAAG,MAAM;CACxG;CAEA,IAAI,QAAQ,SAAS,OAAO,IAAI,GAAG,YAAY,OAAO,YAAY,MAAM,CAAC;CAEzE,MAAM,SAAuB;EAAE;EAAS;EAAQ;EAAQ,OAAO,YAAY;GAAE,MAAM,QAAQ,MAAM;EAAE;CAAE;CACrG,SAAS,MAAM,KAAK,eAAe,OAAO,MAAM,CAAC;CACjD,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"nitro.js","names":[],"sources":["../../src/adapters/nitro.ts"],"sourcesContent":["import type { AnyExtension } from '@tiptap/core'\nimport { type AiModels, type AiModelsConfig, type CollabConnection, type CollabServer, type CollabServerOptions, createAiModels, createCollabServer, createRateLimiter, type EditorPorts, type RateLimiter, type RateLimiterOptions } from '../server'\nimport { defineEditorConfig } from '../config'\nimport { routeOf } from '../server/h3'\nimport type { AiHandlerContext, HandlerContext } from '../server/handlers'\nimport { adoptEditorServer } from '../server/host'\nimport { type RouteDef, serverRoutesOf } from '../server/routes'\nimport { defineWebSocketHandler, type Router } from 'h3'\nimport { COLLAB_PATH } from '../core/api-routes'\n\n// The editor backend on a Nitro app: the routes the ports can serve (`serverRoutesOf`: settings, users, tags, assets,\n// themes, documents, comments, the optional AI endpoints) and the collaboration websocket, registered in one call from a\n// Nitro plugin. One installer serves both hosts: a plain Nitro app (nitropack 2) calls it from its own plugin, the\n// Nuxt module (`@ecsplico/editor/nuxt`) from its server plugin. Both end in the same `@ecsplico/editor/server/handlers`.\n\n/** The part of a Nitro app this entry uses; `nitroApp` of a Nitro plugin fits. */\nexport interface NitroHost {\n router: Pick<Router, 'add' | 'use'>\n hooks: { hook(name: 'close', listener: () => void | Promise<void>): unknown }\n}\n\n/** The route type of the table `EditorServerOptions.routes` filters. */\nexport type { RouteDef }\n\nexport interface EditorServerOptions {\n /** Identity, storage and everything else the backend serves, one port per capability: a route is mounted only when its port is present. A documents port that also manages documents (`json`, `drizzle`) lets `PUT /api/editor/documents/:id` create them; the `comments` port mounts the comments endpoint, `models` the host's language models. */\n ports: EditorPorts\n /**\n * The collaboration websocket (`/collab/:id`). Schema, hooks and Hocuspocus configuration of `createCollabServer`;\n * `{}` takes everything from the ports (the `collabState` port is required). `false` mounts no websocket (documents then only load and save over HTTP).\n * `authenticateUpgrade`: authenticate the upgrade request itself (`Identity.authenticate` with its headers; cookies,\n * not the provider's `token`) and refuse it with HTTP 401, instead of closing an unauthenticated socket with 4401\n * after the upgrade; the user then travels with the connection and is not authenticated a second time.\n * Needs `experimental: { websocket: true }` in the Nitro config.\n */\n collab: (Omit<CollabServerOptions, 'ports'> & { authenticateUpgrade?: boolean }) | false\n /**\n * Mounts the AI endpoints (`/api/ai/*`): presets, shared key, transcription, slots of `createAiModels`; `languageModel`\n * and `listModels` default to those of the `models` port. Omitted: no AI routes.\n */\n ai?: Partial<AiModelsConfig>\n /** Per-user limit of the AI endpoints; default: that of `defineEditorConfig` (30 requests per minute). */\n rateLimit?: RateLimiterOptions\n /** Filters or reorders the routes before they are mounted (a host that serves `/api/editor/assets/*` itself drops them); default: all. Receives what `serverRoutesOf(ports, { ai })` returns, so a route of an absent port, or an AI route without the `ai` option, is not in it. */\n routes?: (routes: readonly RouteDef[]) => readonly RouteDef[]\n /** The collaboration schema (see `CollabServerOptions.schema`); default `advancedSchemaExtensions()`, host nodes: `() => [...advancedSchemaExtensions(), Callout]`. */\n schema?: () => AnyExtension[]\n}\n\nexport interface EditorServer {\n ports: EditorPorts\n /** The collaboration server, `undefined` with `collab: false`. */\n collab: CollabServer | undefined\n /** The AI models, `undefined` without `ai`. */\n models: AiModels | undefined\n /** Writes pending collaboration stores and disconnects every client. Nitro's `close` hook calls it. */\n close(): Promise<void>\n}\n\ntype CollabPeer = { _hocuspocus?: CollabConnection }\n\n// Same crossws wiring as Hocuspocus' own Server; the document name comes from the provider's `name`. By default the user\n// is authenticated in Hocuspocus' `onAuthenticate` (cookie headers of the upgrade request or the provider's `token`), so\n// the upgrade always succeeds and an unauthenticated socket is closed with 4401 afterwards. With `authenticateUpgrade` the\n// upgrade request itself is authenticated (headers only) and refused with HTTP 401.\nconst collabRoute = (collab: CollabServer, ports: EditorPorts, authenticateUpgrade: boolean) => defineWebSocketHandler({\n async upgrade(request) {\n if (!authenticateUpgrade) return\n const user = await ports.identity.authenticate({ headers: request.headers })\n // No body: crossws' node adapter writes the response headers percent-encoded, which would mangle an automatic `content-type`.\n if (!user) return new Response(null, { status: 401, statusText: 'Unauthorized' })\n // crossws creates the context before it calls the hook (its type is optional only for other callers); `open` reads it as `peer.context`.\n request.context!.user = user\n },\n open(peer) {\n const user = peer.context.user as object | undefined\n ;(peer as unknown as CollabPeer)._hocuspocus = collab.handleConnection(peer.websocket as unknown as Parameters<CollabServer['handleConnection']>[0], peer.request as Request, user && { user })\n },\n message(peer, message) {\n ;(peer as unknown as CollabPeer)._hocuspocus?.handleMessage(message.uint8Array())\n },\n close(peer, details) {\n ;(peer as unknown as CollabPeer)._hocuspocus?.handleClose({ code: details.code ?? 1000, reason: details.reason ?? '' } as CloseEvent)\n },\n error(peer, error) {\n console.error('[collab]', peer.id, error)\n },\n})\n\n/**\n * Wires the editor backend into `nitroApp` (call it from a Nitro plugin):\n *\n * /api/editor/{capabilities,settings,users,tags,assets/…,themes/…} the editor's own endpoints, each with its port; `capabilities` lists what is served\n * /api/editor/documents/:id GET/PUT a document's TipTap JSON (what `useEditorDocument` uses)\n * /api/editor/comments/:id GET/POST comments, with `ports.comments`\n * /api/ai/{models,chat,complete,generate,extract,transcript-cleanup} with `ai`\n * /collab/:id the collaboration websocket, unless `collab: false`\n *\n * Every route authenticates through `ports.identity.authenticate`. The collaboration server is closed with Nitro's `close`\n * hook. The installed server is also the process-wide one of `@ecsplico/editor/server` (`useCollabServer`, `useAiModels`,\n * `liveContent`, …) until it closes. The paths are the ones the editor's client (`createHttpBackend`) calls.\n */\nexport function installEditorServer(nitroApp: NitroHost, options: EditorServerOptions): EditorServer {\n const { ports, schema } = options\n const { authenticateUpgrade = false, ...collabOptions }: Exclude<EditorServerOptions['collab'], false> = options.collab || {}\n const collab = options.collab === false ? undefined : createCollabServer({ ports, ...(schema && { schema }), ...collabOptions })\n const provider = ports.models\n const models = options.ai && createAiModels({\n presets: {},\n languageModel: provider?.languageModel && ((ref, user) => provider.languageModel!(ref, user)),\n listModels: provider?.listModels && (user => provider.listModels!(user)),\n ...options.ai,\n })\n const limiter: RateLimiter | undefined = models && createRateLimiter(options.rateLimit ?? defineEditorConfig().ai.rateLimit)\n\n const context: HandlerContext = { ports, ...(collab && { collab }), served: { ai: models !== undefined, collaboration: collab !== undefined } }\n const aiContext: AiHandlerContext | undefined = models && limiter && { ...context, ai: models, limiter }\n const mounted = serverRoutesOf(ports, { ai: aiContext !== undefined })\n for (const route of options.routes ? options.routes(mounted) : mounted) {\n // `serverRoutesOf` returns the AI routes only with `ai`, so `aiContext` is set for them.\n const handler = route.port === 'ai' ? routeOf(aiContext!, route.handler) : routeOf(context, route.handler)\n nitroApp.router.add(route.path, handler, route.method)\n }\n // No method: the websocket upgrade resolves its handler by path only.\n if (collab) nitroApp.router.use(`${COLLAB_PATH}/:id`, collabRoute(collab, ports, authenticateUpgrade))\n\n const release = adoptEditorServer({ ports, schema, collab, models, limiter })\n const server: EditorServer = {\n ports,\n collab,\n models,\n async close() {\n await collab?.close()\n release()\n },\n }\n nitroApp.hooks.hook('close', () => server.close())\n return server\n}\n"],"mappings":";;;;;;;;;;AAiEA,MAAM,eAAe,QAAsB,OAAoB,wBAAiC,uBAAuB;CACrH,MAAM,QAAQ,SAAS;EACrB,IAAI,CAAC,qBAAqB;EAC1B,MAAM,OAAO,MAAM,MAAM,SAAS,aAAa,EAAE,SAAS,QAAQ,QAAQ,CAAC;EAE3E,IAAI,CAAC,MAAM,OAAO,IAAI,SAAS,MAAM;GAAE,QAAQ;GAAK,YAAY;EAAe,CAAC;EAEhF,QAAQ,QAAS,OAAO;CAC1B;CACA,KAAK,MAAM;EACT,MAAM,OAAO,KAAK,QAAQ;EACzB,KAAgC,cAAc,OAAO,iBAAiB,KAAK,WAAyE,KAAK,SAAoB,QAAQ,EAAE,KAAK,CAAC;CAChM;CACA,QAAQ,MAAM,SAAS;EACpB,KAAgC,aAAa,cAAc,QAAQ,WAAW,CAAC;CAClF;CACA,MAAM,MAAM,SAAS;EAClB,KAAgC,aAAa,YAAY;GAAE,MAAM,QAAQ,QAAQ;GAAM,QAAQ,QAAQ,UAAU;EAAG,CAAe;CACtI;CACA,MAAM,MAAM,OAAO;EACjB,QAAQ,MAAM,YAAY,KAAK,IAAI,KAAK;CAC1C;AACF,CAAC;;;;;;;;;;;;;;AAeD,SAAgB,oBAAoB,UAAqB,SAA4C;CACnG,MAAM,EAAE,OAAO,WAAW;CAC1B,MAAM,EAAE,sBAAsB,OAAO,GAAG,kBAAiE,QAAQ,UAAU,CAAC;CAC5H,MAAM,SAAS,QAAQ,WAAW,QAAQ,KAAA,IAAY,mBAAmB;EAAE;EAAO,GAAI,UAAU,EAAE,OAAO;EAAI,GAAG;CAAc,CAAC;CAC/H,MAAM,WAAW,MAAM;CACvB,MAAM,SAAS,QAAQ,MAAM,eAAe;EAC1C,SAAS,CAAC;EACV,eAAe,UAAU,mBAAmB,KAAK,SAAS,SAAS,cAAe,KAAK,IAAI;EAC3F,YAAY,UAAU,gBAAe,SAAQ,SAAS,WAAY,IAAI;EACtE,GAAG,QAAQ;CACb,CAAC;CACD,MAAM,UAAmC,UAAU,kBAAkB,QAAQ,aAAa,mBAAmB,CAAC,CAAC,GAAG,SAAS;CAE3H,MAAM,UAA0B;EAAE;EAAO,GAAI,UAAU,EAAE,OAAO;EAAI,QAAQ;GAAE,IAAI,WAAW,KAAA;GAAW,eAAe,WAAW,KAAA;EAAU;CAAE;CAC9I,MAAM,YAA0C,UAAU,WAAW;EAAE,GAAG;EAAS,IAAI;EAAQ;CAAQ;CACvG,MAAM,UAAU,eAAe,OAAO,EAAE,IAAI,cAAc,KAAA,EAAU,CAAC;CACrE,KAAK,MAAM,SAAS,QAAQ,SAAS,QAAQ,OAAO,OAAO,IAAI,SAAS;EAEtE,MAAM,UAAU,MAAM,SAAS,OAAO,QAAQ,WAAY,MAAM,OAAO,IAAI,QAAQ,SAAS,MAAM,OAAO;EACzG,SAAS,OAAO,IAAI,MAAM,MAAM,SAAS,MAAM,MAAM;CACvD;CAEA,IAAI,QAAQ,SAAS,OAAO,IAAI,GAAG,YAAY,OAAO,YAAY,QAAQ,OAAO,mBAAmB,CAAC;CAErG,MAAM,UAAU,kBAAkB;EAAE;EAAO;EAAQ;EAAQ;EAAQ;CAAQ,CAAC;CAC5E,MAAM,SAAuB;EAC3B;EACA;EACA;EACA,MAAM,QAAQ;GACZ,MAAM,QAAQ,MAAM;GACpB,QAAQ;EACV;CACF;CACA,SAAS,MAAM,KAAK,eAAe,OAAO,MAAM,CAAC;CACjD,OAAO;AACT"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { CollaborationSession } from "../core/feature.js";
|
|
2
|
+
import { CommentsModel } from "../core/backend-types.js";
|
|
3
|
+
import "../core/index.js";
|
|
4
|
+
import { EditorDocumentOptions } from "./document-state.js";
|
|
5
|
+
import { Editor, JSONContent } from "@tiptap/core";
|
|
6
|
+
//#region src/adapters/react.d.ts
|
|
7
|
+
/** The props of the editor surface (`EditorSurface`, `AdvancedEditor`) that `useEditorDocument` fills. */
|
|
8
|
+
export interface EditorDocumentBinding {
|
|
9
|
+
/** The document (standalone mode); `undefined` in collaboration mode and until it has loaded. */
|
|
10
|
+
value: JSONContent | undefined;
|
|
11
|
+
onChange: (content: JSONContent) => void;
|
|
12
|
+
/** Hands the live editor to the comments model. */
|
|
13
|
+
onReady: (editor: Editor) => void;
|
|
14
|
+
collaboration: CollaborationSession | undefined;
|
|
15
|
+
}
|
|
16
|
+
export interface EditorDocument {
|
|
17
|
+
/** The document's TipTap JSON: the surface's `value`. `undefined` until loaded, and always in collaboration mode. */
|
|
18
|
+
modelValue: JSONContent | undefined;
|
|
19
|
+
/** Replaces `modelValue` (the surface's `onChange`). */
|
|
20
|
+
onChange: (content: JSONContent) => void;
|
|
21
|
+
/** `true` once the surface can be mounted: the content has loaded (a missing document starts empty), or the collaboration session exists. Mount with `key` = the id, so a changed id remounts it. */
|
|
22
|
+
ready: boolean;
|
|
23
|
+
/** Edits since the content was loaded or last saved. */
|
|
24
|
+
dirty: boolean;
|
|
25
|
+
/** Stores the current content (`backend.documents.save`); several calls run one after another and an edit made while one is in flight stays dirty. Rejects with the backend's refusal. */
|
|
26
|
+
save: () => Promise<void>;
|
|
27
|
+
/** Loads the content again and drops unsaved edits (in collaboration mode: reconnects). */
|
|
28
|
+
reload: () => Promise<void>;
|
|
29
|
+
/** The last load or save error, `null` while all is well. */
|
|
30
|
+
error: Error | null;
|
|
31
|
+
/** The collaboration session for the surface's `collaboration` prop; `undefined` without the `collaboration` option, and never the session of another document. */
|
|
32
|
+
collaboration: CollaborationSession | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* The comments model of this document, made by `backend.comments` (`undefined` when the backend has none, and until
|
|
35
|
+
* the first effect ran). A new one per id. The feature's `model` factory runs when the editor is created, so read it
|
|
36
|
+
* through a ref the host keeps current: `commentsFeature({ model: () => commentsRef.current! })`.
|
|
37
|
+
*/
|
|
38
|
+
comments: CommentsModel | undefined;
|
|
39
|
+
/** The live editor, once the surface reported it. */
|
|
40
|
+
editor: Editor | undefined;
|
|
41
|
+
/** Spread target for the surface: `<AdvancedEditor key={id} {...bind} />` once `ready`. */
|
|
42
|
+
bind: EditorDocumentBinding;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Loads document `id` through `backend.documents` (a missing document starts empty; the first `save()` creates it),
|
|
46
|
+
* tracks edits, saves, and prepares the collaboration session (`backend.collaboration`) and comments model
|
|
47
|
+
* (`backend.comments`) for the editor surface. The backend is `options.backend`, else the editor context's
|
|
48
|
+
* (`EditorContextProvider`); keep it stable across renders (a new object reloads the document). A changed `id` loads the
|
|
49
|
+
* other document and replaces the session and the comments model. Throws when `collaboration` is set and the backend
|
|
50
|
+
* cannot collaborate, or when it keeps no documents.
|
|
51
|
+
*/
|
|
52
|
+
export declare function useEditorDocument(documentId: string | null | undefined, options?: EditorDocumentOptions): EditorDocument;
|
|
53
|
+
//#endregion
|
|
54
|
+
export type { EditorDocumentOptions };
|
|
55
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { useOptionalEditorContext } from "../react/context.js";
|
|
2
|
+
import { errorOf, fingerprintToSave, isDirty, loadedDocument, openSession, requireCapability } from "./document-state.js";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
//#region src/adapters/react.ts
|
|
5
|
+
const fresh = (id) => ({
|
|
6
|
+
id,
|
|
7
|
+
ready: false,
|
|
8
|
+
modelValue: void 0,
|
|
9
|
+
saved: null,
|
|
10
|
+
error: null,
|
|
11
|
+
session: void 0,
|
|
12
|
+
editor: void 0
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Loads document `id` through `backend.documents` (a missing document starts empty; the first `save()` creates it),
|
|
16
|
+
* tracks edits, saves, and prepares the collaboration session (`backend.collaboration`) and comments model
|
|
17
|
+
* (`backend.comments`) for the editor surface. The backend is `options.backend`, else the editor context's
|
|
18
|
+
* (`EditorContextProvider`); keep it stable across renders (a new object reloads the document). A changed `id` loads the
|
|
19
|
+
* other document and replaces the session and the comments model. Throws when `collaboration` is set and the backend
|
|
20
|
+
* cannot collaborate, or when it keeps no documents.
|
|
21
|
+
*/
|
|
22
|
+
function useEditorDocument(documentId, options = {}) {
|
|
23
|
+
/** `''` = no document open (the host has none yet, e.g. it still waits for the signed-in user): the hook stays idle. */
|
|
24
|
+
const id = documentId ?? "";
|
|
25
|
+
const context = useOptionalEditorContext();
|
|
26
|
+
const backend = options.backend ?? context?.backend;
|
|
27
|
+
if (!backend) throw new Error("@ecsplico/editor: useEditorDocument needs a backend: pass `backend` or wrap the tree in <EditorContextProvider context={createEditorContext()}>");
|
|
28
|
+
const collaborating = Boolean(options.collaboration);
|
|
29
|
+
const documents = collaborating ? void 0 : requireCapability(backend, "documents");
|
|
30
|
+
const collaborationPort = collaborating ? requireCapability(backend, "collaboration") : void 0;
|
|
31
|
+
const [state, setState] = useState(() => fresh(id));
|
|
32
|
+
const [comments, setComments] = useState();
|
|
33
|
+
const [attempt, setAttempt] = useState(0);
|
|
34
|
+
/** What the callbacks read: the open id, and the latest options and values (an edit just reported is here before the next render). */
|
|
35
|
+
const live = useRef({
|
|
36
|
+
id,
|
|
37
|
+
options,
|
|
38
|
+
modelValue: void 0,
|
|
39
|
+
saved: null,
|
|
40
|
+
ready: false,
|
|
41
|
+
missing: false,
|
|
42
|
+
editor: void 0
|
|
43
|
+
});
|
|
44
|
+
live.current.id = id;
|
|
45
|
+
live.current.options = options;
|
|
46
|
+
const generation = useRef(0);
|
|
47
|
+
const tail = useRef(Promise.resolve());
|
|
48
|
+
const current = state.id === id ? state : fresh(id);
|
|
49
|
+
const userOf = useCallback(() => {
|
|
50
|
+
const { user } = live.current.options;
|
|
51
|
+
return (typeof user === "function" ? user() : user) ?? null;
|
|
52
|
+
}, []);
|
|
53
|
+
const commit = useCallback((documentId, change) => {
|
|
54
|
+
if (documentId !== live.current.id) return;
|
|
55
|
+
if ("modelValue" in change) live.current.modelValue = change.modelValue;
|
|
56
|
+
if ("saved" in change) live.current.saved = change.saved ?? null;
|
|
57
|
+
if ("ready" in change) live.current.ready = change.ready ?? false;
|
|
58
|
+
if ("editor" in change) live.current.editor = change.editor;
|
|
59
|
+
setState((previous) => previous.id === documentId ? {
|
|
60
|
+
...previous,
|
|
61
|
+
...change
|
|
62
|
+
} : previous);
|
|
63
|
+
}, []);
|
|
64
|
+
const fetchContent = useCallback(async (documentId, mine) => {
|
|
65
|
+
try {
|
|
66
|
+
const content = await documents.load(documentId);
|
|
67
|
+
if (mine !== generation.current) return;
|
|
68
|
+
const { modelValue, saved, missing } = loadedDocument(content);
|
|
69
|
+
live.current.missing = missing;
|
|
70
|
+
commit(documentId, {
|
|
71
|
+
modelValue,
|
|
72
|
+
saved,
|
|
73
|
+
ready: true
|
|
74
|
+
});
|
|
75
|
+
} catch (cause) {
|
|
76
|
+
if (mine === generation.current) commit(documentId, { error: errorOf(cause) });
|
|
77
|
+
}
|
|
78
|
+
}, [documents, commit]);
|
|
79
|
+
const start = useCallback((documentId) => {
|
|
80
|
+
const mine = ++generation.current;
|
|
81
|
+
Object.assign(live.current, {
|
|
82
|
+
modelValue: void 0,
|
|
83
|
+
saved: null,
|
|
84
|
+
ready: false,
|
|
85
|
+
missing: false,
|
|
86
|
+
editor: void 0
|
|
87
|
+
});
|
|
88
|
+
setState(fresh(documentId));
|
|
89
|
+
return mine;
|
|
90
|
+
}, []);
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
const mine = start(id);
|
|
93
|
+
if (!id) return;
|
|
94
|
+
if (collaborationPort) {
|
|
95
|
+
const { session, close } = openSession(collaborationPort, id, live.current.options.collaboration, userOf());
|
|
96
|
+
commit(id, {
|
|
97
|
+
session,
|
|
98
|
+
ready: true
|
|
99
|
+
});
|
|
100
|
+
return () => {
|
|
101
|
+
generation.current++;
|
|
102
|
+
close();
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
fetchContent(id, mine);
|
|
106
|
+
return () => {
|
|
107
|
+
generation.current++;
|
|
108
|
+
};
|
|
109
|
+
}, [
|
|
110
|
+
id,
|
|
111
|
+
collaborationPort,
|
|
112
|
+
attempt,
|
|
113
|
+
start,
|
|
114
|
+
commit,
|
|
115
|
+
fetchContent,
|
|
116
|
+
userOf
|
|
117
|
+
]);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
if (!id) return;
|
|
120
|
+
const model = backend.comments?.(id, {
|
|
121
|
+
user: userOf,
|
|
122
|
+
canComment: () => {
|
|
123
|
+
const { canComment } = live.current.options;
|
|
124
|
+
return (typeof canComment === "function" ? canComment() : canComment) ?? true;
|
|
125
|
+
},
|
|
126
|
+
getEditor: () => live.current.editor,
|
|
127
|
+
onError: (cause) => commit(id, { error: cause })
|
|
128
|
+
});
|
|
129
|
+
setComments(model);
|
|
130
|
+
return () => {
|
|
131
|
+
model?.dispose();
|
|
132
|
+
setComments(void 0);
|
|
133
|
+
};
|
|
134
|
+
}, [
|
|
135
|
+
backend,
|
|
136
|
+
id,
|
|
137
|
+
userOf,
|
|
138
|
+
commit
|
|
139
|
+
]);
|
|
140
|
+
const save = useCallback(() => {
|
|
141
|
+
if (!documents) return Promise.resolve();
|
|
142
|
+
const run = async () => {
|
|
143
|
+
const documentId = live.current.id;
|
|
144
|
+
const content = live.current.modelValue;
|
|
145
|
+
const saved = fingerprintToSave(content, live.current.ready, live.current.saved, live.current.missing);
|
|
146
|
+
if (content === void 0 || saved === null) return;
|
|
147
|
+
try {
|
|
148
|
+
await documents.save(documentId, content);
|
|
149
|
+
} catch (cause) {
|
|
150
|
+
commit(documentId, { error: errorOf(cause) });
|
|
151
|
+
throw cause;
|
|
152
|
+
}
|
|
153
|
+
if (documentId === live.current.id) live.current.missing = false;
|
|
154
|
+
commit(documentId, {
|
|
155
|
+
saved,
|
|
156
|
+
error: null
|
|
157
|
+
});
|
|
158
|
+
};
|
|
159
|
+
const result = tail.current.then(run, run);
|
|
160
|
+
tail.current = result.catch(() => {});
|
|
161
|
+
return result;
|
|
162
|
+
}, [documents, commit]);
|
|
163
|
+
const reload = useCallback(async () => {
|
|
164
|
+
if (collaborationPort) {
|
|
165
|
+
setAttempt((count) => count + 1);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
await fetchContent(live.current.id, start(live.current.id));
|
|
169
|
+
}, [
|
|
170
|
+
collaborationPort,
|
|
171
|
+
fetchContent,
|
|
172
|
+
start
|
|
173
|
+
]);
|
|
174
|
+
const onChange = useCallback((content) => commit(live.current.id, { modelValue: content }), [commit]);
|
|
175
|
+
const onReady = useCallback((editor) => commit(live.current.id, { editor }), [commit]);
|
|
176
|
+
const dirty = useMemo(() => isDirty(collaborating, current.modelValue, current.saved), [
|
|
177
|
+
collaborating,
|
|
178
|
+
current.modelValue,
|
|
179
|
+
current.saved
|
|
180
|
+
]);
|
|
181
|
+
const bind = useMemo(() => ({
|
|
182
|
+
value: current.modelValue,
|
|
183
|
+
onChange,
|
|
184
|
+
onReady,
|
|
185
|
+
collaboration: current.session
|
|
186
|
+
}), [
|
|
187
|
+
current.modelValue,
|
|
188
|
+
current.session,
|
|
189
|
+
onChange,
|
|
190
|
+
onReady
|
|
191
|
+
]);
|
|
192
|
+
return {
|
|
193
|
+
modelValue: current.modelValue,
|
|
194
|
+
onChange,
|
|
195
|
+
ready: current.ready,
|
|
196
|
+
dirty,
|
|
197
|
+
save,
|
|
198
|
+
reload,
|
|
199
|
+
error: current.error,
|
|
200
|
+
collaboration: current.session,
|
|
201
|
+
comments,
|
|
202
|
+
editor: current.editor,
|
|
203
|
+
bind
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
//#endregion
|
|
207
|
+
export { useEditorDocument };
|
|
208
|
+
|
|
209
|
+
//# sourceMappingURL=react.js.map
|