@open-mercato/documents 0.6.8-develop.7016.1.4ed7b1e49d
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 +88 -0
- package/build.mjs +23 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +7 -0
- package/dist/modules/documents/acl.js +15 -0
- package/dist/modules/documents/acl.js.map +7 -0
- package/dist/modules/documents/api/[id]/archive/route.js +116 -0
- package/dist/modules/documents/api/[id]/archive/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/attachments/[attachmentId]/route.js +155 -0
- package/dist/modules/documents/api/[id]/attachments/[attachmentId]/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/attachments/route.js +153 -0
- package/dist/modules/documents/api/[id]/attachments/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/collab-token/route.js +180 -0
- package/dist/modules/documents/api/[id]/collab-token/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/comments/access-check/route.js +86 -0
- package/dist/modules/documents/api/[id]/comments/access-check/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/comments/route.js +387 -0
- package/dist/modules/documents/api/[id]/comments/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/content/route.js +143 -0
- package/dist/modules/documents/api/[id]/content/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/duplicate/route.js +200 -0
- package/dist/modules/documents/api/[id]/duplicate/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/export/route.js +421 -0
- package/dist/modules/documents/api/[id]/export/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/favorite/route.js +96 -0
- package/dist/modules/documents/api/[id]/favorite/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/links/[linkId]/route.js +85 -0
- package/dist/modules/documents/api/[id]/links/[linkId]/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/links/route.js +257 -0
- package/dist/modules/documents/api/[id]/links/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/principals/route.js +299 -0
- package/dist/modules/documents/api/[id]/principals/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/route.js +246 -0
- package/dist/modules/documents/api/[id]/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/shares/route.js +335 -0
- package/dist/modules/documents/api/[id]/shares/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/unarchive/route.js +39 -0
- package/dist/modules/documents/api/[id]/unarchive/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/versions/[versionId]/restore/route.js +133 -0
- package/dist/modules/documents/api/[id]/versions/[versionId]/restore/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/versions/[versionId]/route.js +93 -0
- package/dist/modules/documents/api/[id]/versions/[versionId]/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/versions/route.js +193 -0
- package/dist/modules/documents/api/[id]/versions/route.js.map +7 -0
- package/dist/modules/documents/api/[id]/watch/route.js +97 -0
- package/dist/modules/documents/api/[id]/watch/route.js.map +7 -0
- package/dist/modules/documents/api/_commands.js +34 -0
- package/dist/modules/documents/api/_commands.js.map +7 -0
- package/dist/modules/documents/api/_shared.js +490 -0
- package/dist/modules/documents/api/_shared.js.map +7 -0
- package/dist/modules/documents/api/folders/route.js +256 -0
- package/dist/modules/documents/api/folders/route.js.map +7 -0
- package/dist/modules/documents/api/instantiate/route.js +108 -0
- package/dist/modules/documents/api/instantiate/route.js.map +7 -0
- package/dist/modules/documents/api/route.js +322 -0
- package/dist/modules/documents/api/route.js.map +7 -0
- package/dist/modules/documents/api/templates/[templateId]/preview/route.js +94 -0
- package/dist/modules/documents/api/templates/[templateId]/preview/route.js.map +7 -0
- package/dist/modules/documents/api/templates/[templateId]/route.js +82 -0
- package/dist/modules/documents/api/templates/[templateId]/route.js.map +7 -0
- package/dist/modules/documents/api/templates/route.js +344 -0
- package/dist/modules/documents/api/templates/route.js.map +7 -0
- package/dist/modules/documents/backend/documents/DocumentsPageClient.js +160 -0
- package/dist/modules/documents/backend/documents/DocumentsPageClient.js.map +7 -0
- package/dist/modules/documents/backend/documents/DocumentsTable.js +143 -0
- package/dist/modules/documents/backend/documents/DocumentsTable.js.map +7 -0
- package/dist/modules/documents/backend/documents/FolderDialog.js +55 -0
- package/dist/modules/documents/backend/documents/FolderDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/FolderTree.js +40 -0
- package/dist/modules/documents/backend/documents/FolderTree.js.map +7 -0
- package/dist/modules/documents/backend/documents/MoveDocumentDialog.js +64 -0
- package/dist/modules/documents/backend/documents/MoveDocumentDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/CommentAnchorNavigation.js +77 -0
- package/dist/modules/documents/backend/documents/[id]/CommentAnchorNavigation.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/CommentComposer.js +126 -0
- package/dist/modules/documents/backend/documents/[id]/CommentComposer.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/CommentThreadList.js +88 -0
- package/dist/modules/documents/backend/documents/[id]/CommentThreadList.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/CommentsRail.js +123 -0
- package/dist/modules/documents/backend/documents/[id]/CommentsRail.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentCanvas.js +91 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentCanvas.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentEditorErrorBoundary.js +27 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentEditorErrorBoundary.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentEditorIsland.js +50 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentEditorIsland.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentEditorSurface.js +168 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentEditorSurface.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentNavigator.js +129 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentNavigator.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentPageClient.js +429 -0
- package/dist/modules/documents/backend/documents/[id]/DocumentPageClient.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/EditorColorTools.js +68 -0
- package/dist/modules/documents/backend/documents/[id]/EditorColorTools.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/EditorStatusPresence.js +69 -0
- package/dist/modules/documents/backend/documents/[id]/EditorStatusPresence.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/EditorToolbar.js +151 -0
- package/dist/modules/documents/backend/documents/[id]/EditorToolbar.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/ExportMenu.js +121 -0
- package/dist/modules/documents/backend/documents/[id]/ExportMenu.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/MentionPicker.js +114 -0
- package/dist/modules/documents/backend/documents/[id]/MentionPicker.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/OutlinePane.js +70 -0
- package/dist/modules/documents/backend/documents/[id]/OutlinePane.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/RecordFieldsDialog.js +157 -0
- package/dist/modules/documents/backend/documents/[id]/RecordFieldsDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/RelatedRecordsPanel.js +266 -0
- package/dist/modules/documents/backend/documents/[id]/RelatedRecordsPanel.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/VersionHistoryPanel.js +227 -0
- package/dist/modules/documents/backend/documents/[id]/VersionHistoryPanel.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/VersionPreviewDialog.js +157 -0
- package/dist/modules/documents/backend/documents/[id]/VersionPreviewDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/commentTypes.js +150 -0
- package/dist/modules/documents/backend/documents/[id]/commentTypes.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/componentCapabilities.js +13 -0
- package/dist/modules/documents/backend/documents/[id]/componentCapabilities.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/documentPagination.js +295 -0
- package/dist/modules/documents/backend/documents/[id]/documentPagination.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/editorPresenceStyles.js +81 -0
- package/dist/modules/documents/backend/documents/[id]/editorPresenceStyles.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/editorTypes.js +52 -0
- package/dist/modules/documents/backend/documents/[id]/editorTypes.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/page.js +10 -0
- package/dist/modules/documents/backend/documents/[id]/page.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/page.meta.js +16 -0
- package/dist/modules/documents/backend/documents/[id]/page.meta.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/relatedRecordModel.js +38 -0
- package/dist/modules/documents/backend/documents/[id]/relatedRecordModel.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/restoreVersion.js +33 -0
- package/dist/modules/documents/backend/documents/[id]/restoreVersion.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentCollaboration.js +392 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentCollaboration.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentComments.js +253 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentComments.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentEditor.js +149 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentEditor.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentTitle.js +82 -0
- package/dist/modules/documents/backend/documents/[id]/useDocumentTitle.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useEditorInsertions.js +144 -0
- package/dist/modules/documents/backend/documents/[id]/useEditorInsertions.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useFallbackContentPersistence.js +237 -0
- package/dist/modules/documents/backend/documents/[id]/useFallbackContentPersistence.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/useMentionPicker.js +216 -0
- package/dist/modules/documents/backend/documents/[id]/useMentionPicker.js.map +7 -0
- package/dist/modules/documents/backend/documents/[id]/versionHistoryModel.js +25 -0
- package/dist/modules/documents/backend/documents/[id]/versionHistoryModel.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/EntityPicker.js +156 -0
- package/dist/modules/documents/backend/documents/components/EntityPicker.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/EntityPickerResults.js +46 -0
- package/dist/modules/documents/backend/documents/components/EntityPickerResults.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/NewFromTemplateDialog.js +127 -0
- package/dist/modules/documents/backend/documents/components/NewFromTemplateDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/PrincipalPicker.js +84 -0
- package/dist/modules/documents/backend/documents/components/PrincipalPicker.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/ShareDialog.js +77 -0
- package/dist/modules/documents/backend/documents/components/ShareDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/ShareDialogAddForm.js +93 -0
- package/dist/modules/documents/backend/documents/components/ShareDialogAddForm.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/ShareDialogList.js +82 -0
- package/dist/modules/documents/backend/documents/components/ShareDialogList.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/TemplateBodyEditor.js +96 -0
- package/dist/modules/documents/backend/documents/components/TemplateBodyEditor.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/TemplateEditorDialog.js +169 -0
- package/dist/modules/documents/backend/documents/components/TemplateEditorDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/TemplatePreview.js +38 -0
- package/dist/modules/documents/backend/documents/components/TemplatePreview.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/TemplateSlotFields.js +69 -0
- package/dist/modules/documents/backend/documents/components/TemplateSlotFields.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/TemplateSlotsEditor.js +71 -0
- package/dist/modules/documents/backend/documents/components/TemplateSlotsEditor.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/principalPickerModel.js +63 -0
- package/dist/modules/documents/backend/documents/components/principalPickerModel.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/shareDialogModel.js +68 -0
- package/dist/modules/documents/backend/documents/components/shareDialogModel.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/templateUi.js +89 -0
- package/dist/modules/documents/backend/documents/components/templateUi.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/useAvailableEntityRegistry.js +30 -0
- package/dist/modules/documents/backend/documents/components/useAvailableEntityRegistry.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/useEntitySearch.js +191 -0
- package/dist/modules/documents/backend/documents/components/useEntitySearch.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/usePrincipalPicker.js +221 -0
- package/dist/modules/documents/backend/documents/components/usePrincipalPicker.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/useShareDialog.js +236 -0
- package/dist/modules/documents/backend/documents/components/useShareDialog.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/useTemplateDetail.js +49 -0
- package/dist/modules/documents/backend/documents/components/useTemplateDetail.js.map +7 -0
- package/dist/modules/documents/backend/documents/components/useTemplateInstantiation.js +234 -0
- package/dist/modules/documents/backend/documents/components/useTemplateInstantiation.js.map +7 -0
- package/dist/modules/documents/backend/documents/documentUi.js +106 -0
- package/dist/modules/documents/backend/documents/documentUi.js.map +7 -0
- package/dist/modules/documents/backend/documents/documentsListTypes.js +132 -0
- package/dist/modules/documents/backend/documents/documentsListTypes.js.map +7 -0
- package/dist/modules/documents/backend/documents/page.js +9 -0
- package/dist/modules/documents/backend/documents/page.js.map +7 -0
- package/dist/modules/documents/backend/documents/page.meta.js +26 -0
- package/dist/modules/documents/backend/documents/page.meta.js.map +7 -0
- package/dist/modules/documents/backend/documents/templates/TemplatesPageClient.js +91 -0
- package/dist/modules/documents/backend/documents/templates/TemplatesPageClient.js.map +7 -0
- package/dist/modules/documents/backend/documents/templates/TemplatesTable.js +58 -0
- package/dist/modules/documents/backend/documents/templates/TemplatesTable.js.map +7 -0
- package/dist/modules/documents/backend/documents/templates/page.js +9 -0
- package/dist/modules/documents/backend/documents/templates/page.js.map +7 -0
- package/dist/modules/documents/backend/documents/templates/page.meta.js +34 -0
- package/dist/modules/documents/backend/documents/templates/page.meta.js.map +7 -0
- package/dist/modules/documents/backend/documents/templates/useTemplatesPage.js +139 -0
- package/dist/modules/documents/backend/documents/templates/useTemplatesPage.js.map +7 -0
- package/dist/modules/documents/backend/documents/useDocumentsList.js +314 -0
- package/dist/modules/documents/backend/documents/useDocumentsList.js.map +7 -0
- package/dist/modules/documents/ce.js +8 -0
- package/dist/modules/documents/ce.js.map +7 -0
- package/dist/modules/documents/commands/aggregate.js +99 -0
- package/dist/modules/documents/commands/aggregate.js.map +7 -0
- package/dist/modules/documents/commands/attachments.js +252 -0
- package/dist/modules/documents/commands/attachments.js.map +7 -0
- package/dist/modules/documents/commands/comments.js +782 -0
- package/dist/modules/documents/commands/comments.js.map +7 -0
- package/dist/modules/documents/commands/content.js +238 -0
- package/dist/modules/documents/commands/content.js.map +7 -0
- package/dist/modules/documents/commands/document-crud.js +505 -0
- package/dist/modules/documents/commands/document-crud.js.map +7 -0
- package/dist/modules/documents/commands/documents.js +473 -0
- package/dist/modules/documents/commands/documents.js.map +7 -0
- package/dist/modules/documents/commands/duplicate.js +640 -0
- package/dist/modules/documents/commands/duplicate.js.map +7 -0
- package/dist/modules/documents/commands/favorites.js +150 -0
- package/dist/modules/documents/commands/favorites.js.map +7 -0
- package/dist/modules/documents/commands/folders.js +420 -0
- package/dist/modules/documents/commands/folders.js.map +7 -0
- package/dist/modules/documents/commands/index.js +64 -0
- package/dist/modules/documents/commands/index.js.map +7 -0
- package/dist/modules/documents/commands/interceptors.js +300 -0
- package/dist/modules/documents/commands/interceptors.js.map +7 -0
- package/dist/modules/documents/commands/lifecycle.js +249 -0
- package/dist/modules/documents/commands/lifecycle.js.map +7 -0
- package/dist/modules/documents/commands/links.js +410 -0
- package/dist/modules/documents/commands/links.js.map +7 -0
- package/dist/modules/documents/commands/mutation-helpers.js +42 -0
- package/dist/modules/documents/commands/mutation-helpers.js.map +7 -0
- package/dist/modules/documents/commands/projection-types.js +1 -0
- package/dist/modules/documents/commands/projection-types.js.map +7 -0
- package/dist/modules/documents/commands/shared.js +143 -0
- package/dist/modules/documents/commands/shared.js.map +7 -0
- package/dist/modules/documents/commands/shares.js +527 -0
- package/dist/modules/documents/commands/shares.js.map +7 -0
- package/dist/modules/documents/commands/side-effects.js +103 -0
- package/dist/modules/documents/commands/side-effects.js.map +7 -0
- package/dist/modules/documents/commands/templates.js +461 -0
- package/dist/modules/documents/commands/templates.js.map +7 -0
- package/dist/modules/documents/commands/versions.js +432 -0
- package/dist/modules/documents/commands/versions.js.map +7 -0
- package/dist/modules/documents/commands/watchers.js +164 -0
- package/dist/modules/documents/commands/watchers.js.map +7 -0
- package/dist/modules/documents/data/entities.js +653 -0
- package/dist/modules/documents/data/entities.js.map +7 -0
- package/dist/modules/documents/data/extensions.js +44 -0
- package/dist/modules/documents/data/extensions.js.map +7 -0
- package/dist/modules/documents/data/validators.js +219 -0
- package/dist/modules/documents/data/validators.js.map +7 -0
- package/dist/modules/documents/di.js +35 -0
- package/dist/modules/documents/di.js.map +7 -0
- package/dist/modules/documents/encryption.js +12 -0
- package/dist/modules/documents/encryption.js.map +7 -0
- package/dist/modules/documents/events.js +27 -0
- package/dist/modules/documents/events.js.map +7 -0
- package/dist/modules/documents/index.js +19 -0
- package/dist/modules/documents/index.js.map +7 -0
- package/dist/modules/documents/lib/attachmentServicePort.js +30 -0
- package/dist/modules/documents/lib/attachmentServicePort.js.map +7 -0
- package/dist/modules/documents/lib/capabilities.js +32 -0
- package/dist/modules/documents/lib/capabilities.js.map +7 -0
- package/dist/modules/documents/lib/collabCloseEvents.js +17 -0
- package/dist/modules/documents/lib/collabCloseEvents.js.map +7 -0
- package/dist/modules/documents/lib/collabEndpoint.js +22 -0
- package/dist/modules/documents/lib/collabEndpoint.js.map +7 -0
- package/dist/modules/documents/lib/collabMaterializer.js +107 -0
- package/dist/modules/documents/lib/collabMaterializer.js.map +7 -0
- package/dist/modules/documents/lib/collabToken.js +120 -0
- package/dist/modules/documents/lib/collabToken.js.map +7 -0
- package/dist/modules/documents/lib/collaborationAwareness.js +68 -0
- package/dist/modules/documents/lib/collaborationAwareness.js.map +7 -0
- package/dist/modules/documents/lib/commentAnchors.js +15 -0
- package/dist/modules/documents/lib/commentAnchors.js.map +7 -0
- package/dist/modules/documents/lib/constants.js +25 -0
- package/dist/modules/documents/lib/constants.js.map +7 -0
- package/dist/modules/documents/lib/contentService.js +248 -0
- package/dist/modules/documents/lib/contentService.js.map +7 -0
- package/dist/modules/documents/lib/displayLabels.js +23 -0
- package/dist/modules/documents/lib/displayLabels.js.map +7 -0
- package/dist/modules/documents/lib/docxRenderer.js +601 -0
- package/dist/modules/documents/lib/docxRenderer.js.map +7 -0
- package/dist/modules/documents/lib/duplicateContent.js +22 -0
- package/dist/modules/documents/lib/duplicateContent.js.map +7 -0
- package/dist/modules/documents/lib/editorConfig.js +287 -0
- package/dist/modules/documents/lib/editorConfig.js.map +7 -0
- package/dist/modules/documents/lib/entityLinks.js +148 -0
- package/dist/modules/documents/lib/entityLinks.js.map +7 -0
- package/dist/modules/documents/lib/entityRegistry.js +258 -0
- package/dist/modules/documents/lib/entityRegistry.js.map +7 -0
- package/dist/modules/documents/lib/entityRegistry.server.js +189 -0
- package/dist/modules/documents/lib/entityRegistry.server.js.map +7 -0
- package/dist/modules/documents/lib/entityRegistryAvailability.server.js +9 -0
- package/dist/modules/documents/lib/entityRegistryAvailability.server.js.map +7 -0
- package/dist/modules/documents/lib/entitySuggestion.js +50 -0
- package/dist/modules/documents/lib/entitySuggestion.js.map +7 -0
- package/dist/modules/documents/lib/favorites.js +22 -0
- package/dist/modules/documents/lib/favorites.js.map +7 -0
- package/dist/modules/documents/lib/folderHierarchySerialization.js +19 -0
- package/dist/modules/documents/lib/folderHierarchySerialization.js.map +7 -0
- package/dist/modules/documents/lib/historyLimits.js +100 -0
- package/dist/modules/documents/lib/historyLimits.js.map +7 -0
- package/dist/modules/documents/lib/historyPolicy.js +14 -0
- package/dist/modules/documents/lib/historyPolicy.js.map +7 -0
- package/dist/modules/documents/lib/organizationAccess.js +17 -0
- package/dist/modules/documents/lib/organizationAccess.js.map +7 -0
- package/dist/modules/documents/lib/pdfHtml.js +62 -0
- package/dist/modules/documents/lib/pdfHtml.js.map +7 -0
- package/dist/modules/documents/lib/pdfRenderer.js +284 -0
- package/dist/modules/documents/lib/pdfRenderer.js.map +7 -0
- package/dist/modules/documents/lib/permissions.js +222 -0
- package/dist/modules/documents/lib/permissions.js.map +7 -0
- package/dist/modules/documents/lib/platformServices.js +35 -0
- package/dist/modules/documents/lib/platformServices.js.map +7 -0
- package/dist/modules/documents/lib/recordFieldInsertion.js +58 -0
- package/dist/modules/documents/lib/recordFieldInsertion.js.map +7 -0
- package/dist/modules/documents/lib/requestBody.js +80 -0
- package/dist/modules/documents/lib/requestBody.js.map +7 -0
- package/dist/modules/documents/lib/resourceLimits.js +62 -0
- package/dist/modules/documents/lib/resourceLimits.js.map +7 -0
- package/dist/modules/documents/lib/shareCounts.js +25 -0
- package/dist/modules/documents/lib/shareCounts.js.map +7 -0
- package/dist/modules/documents/lib/templateFill.js +84 -0
- package/dist/modules/documents/lib/templateFill.js.map +7 -0
- package/dist/modules/documents/lib/templateInstantiation.js +147 -0
- package/dist/modules/documents/lib/templateInstantiation.js.map +7 -0
- package/dist/modules/documents/lib/templatePreviewDigest.js +82 -0
- package/dist/modules/documents/lib/templatePreviewDigest.js.map +7 -0
- package/dist/modules/documents/lib/templateSeeds.js +201 -0
- package/dist/modules/documents/lib/templateSeeds.js.map +7 -0
- package/dist/modules/documents/lib/userLabels.js +37 -0
- package/dist/modules/documents/lib/userLabels.js.map +7 -0
- package/dist/modules/documents/lib/versionContent.js +131 -0
- package/dist/modules/documents/lib/versionContent.js.map +7 -0
- package/dist/modules/documents/lib/versionLabels.js +12 -0
- package/dist/modules/documents/lib/versionLabels.js.map +7 -0
- package/dist/modules/documents/lib/versioning.js +14 -0
- package/dist/modules/documents/lib/versioning.js.map +7 -0
- package/dist/modules/documents/lib/visibility.js +422 -0
- package/dist/modules/documents/lib/visibility.js.map +7 -0
- package/dist/modules/documents/lib/watchers.js +106 -0
- package/dist/modules/documents/lib/watchers.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260708163836_documents.js +44 -0
- package/dist/modules/documents/migrations/Migration20260708163836_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260709164720_documents.js +17 -0
- package/dist/modules/documents/migrations/Migration20260709164720_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260710002318_documents.js +32 -0
- package/dist/modules/documents/migrations/Migration20260710002318_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260710071003_documents.js +13 -0
- package/dist/modules/documents/migrations/Migration20260710071003_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260712120000_documents.js +13 -0
- package/dist/modules/documents/migrations/Migration20260712120000_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260712183000_documents.js +14 -0
- package/dist/modules/documents/migrations/Migration20260712183000_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260713092156_documents.js +29 -0
- package/dist/modules/documents/migrations/Migration20260713092156_documents.js.map +7 -0
- package/dist/modules/documents/migrations/Migration20260717000000_documents.js +37 -0
- package/dist/modules/documents/migrations/Migration20260717000000_documents.js.map +7 -0
- package/dist/modules/documents/notifications.js +47 -0
- package/dist/modules/documents/notifications.js.map +7 -0
- package/dist/modules/documents/search.js +101 -0
- package/dist/modules/documents/search.js.map +7 -0
- package/dist/modules/documents/setup.js +19 -0
- package/dist/modules/documents/setup.js.map +7 -0
- package/dist/modules/documents/widgets/injection/related-documents/LinkDocumentDialog.js +214 -0
- package/dist/modules/documents/widgets/injection/related-documents/LinkDocumentDialog.js.map +7 -0
- package/dist/modules/documents/widgets/injection/related-documents/context.js +84 -0
- package/dist/modules/documents/widgets/injection/related-documents/context.js.map +7 -0
- package/dist/modules/documents/widgets/injection/related-documents/useRelatedDocuments.js +98 -0
- package/dist/modules/documents/widgets/injection/related-documents/useRelatedDocuments.js.map +7 -0
- package/dist/modules/documents/widgets/injection/related-documents/widget.client.js +83 -0
- package/dist/modules/documents/widgets/injection/related-documents/widget.client.js.map +7 -0
- package/dist/modules/documents/widgets/injection/related-documents/widget.js +19 -0
- package/dist/modules/documents/widgets/injection/related-documents/widget.js.map +7 -0
- package/dist/modules/documents/widgets/injection-table.js +21 -0
- package/dist/modules/documents/widgets/injection-table.js.map +7 -0
- package/dist/server/documents-collab-server.js +2260 -0
- package/dist/server/documents-collab-server.js.map +7 -0
- package/generated/entities/document/index.ts +12 -0
- package/generated/entities/document_attachment/index.ts +9 -0
- package/generated/entities/document_comment/index.ts +14 -0
- package/generated/entities/document_content/index.ts +11 -0
- package/generated/entities/document_entity_link/index.ts +19 -0
- package/generated/entities/document_favorite/index.ts +7 -0
- package/generated/entities/document_folder/index.ts +9 -0
- package/generated/entities/document_share/index.ts +11 -0
- package/generated/entities/document_template/index.ts +13 -0
- package/generated/entities/document_version/index.ts +9 -0
- package/generated/entities/document_watcher/index.ts +7 -0
- package/generated/entities.ids.generated.ts +21 -0
- package/generated/entity-fields-registry.ts +151 -0
- package/jest.config.cjs +34 -0
- package/package.json +149 -0
- package/server/documents-collab-server.ts +3416 -0
- package/src/index.ts +1 -0
- package/src/modules/documents/acl.ts +11 -0
- package/src/modules/documents/api/[id]/archive/route.ts +132 -0
- package/src/modules/documents/api/[id]/attachments/[attachmentId]/route.ts +166 -0
- package/src/modules/documents/api/[id]/attachments/route.ts +173 -0
- package/src/modules/documents/api/[id]/collab-token/route.ts +203 -0
- package/src/modules/documents/api/[id]/comments/access-check/route.ts +96 -0
- package/src/modules/documents/api/[id]/comments/route.ts +442 -0
- package/src/modules/documents/api/[id]/content/route.ts +156 -0
- package/src/modules/documents/api/[id]/duplicate/route.ts +231 -0
- package/src/modules/documents/api/[id]/export/route.ts +535 -0
- package/src/modules/documents/api/[id]/favorite/route.ts +110 -0
- package/src/modules/documents/api/[id]/links/[linkId]/route.ts +92 -0
- package/src/modules/documents/api/[id]/links/route.ts +301 -0
- package/src/modules/documents/api/[id]/principals/route.ts +375 -0
- package/src/modules/documents/api/[id]/route.ts +267 -0
- package/src/modules/documents/api/[id]/shares/route.ts +372 -0
- package/src/modules/documents/api/[id]/unarchive/route.ts +42 -0
- package/src/modules/documents/api/[id]/versions/[versionId]/restore/route.ts +152 -0
- package/src/modules/documents/api/[id]/versions/[versionId]/route.ts +100 -0
- package/src/modules/documents/api/[id]/versions/route.ts +207 -0
- package/src/modules/documents/api/[id]/watch/route.ts +111 -0
- package/src/modules/documents/api/_commands.ts +53 -0
- package/src/modules/documents/api/_shared.ts +676 -0
- package/src/modules/documents/api/folders/route.ts +287 -0
- package/src/modules/documents/api/instantiate/route.ts +114 -0
- package/src/modules/documents/api/route.ts +362 -0
- package/src/modules/documents/api/templates/[templateId]/preview/route.ts +97 -0
- package/src/modules/documents/api/templates/[templateId]/route.ts +92 -0
- package/src/modules/documents/api/templates/route.ts +370 -0
- package/src/modules/documents/backend/documents/DocumentsPageClient.tsx +150 -0
- package/src/modules/documents/backend/documents/DocumentsTable.tsx +168 -0
- package/src/modules/documents/backend/documents/FolderDialog.tsx +62 -0
- package/src/modules/documents/backend/documents/FolderTree.tsx +72 -0
- package/src/modules/documents/backend/documents/MoveDocumentDialog.tsx +70 -0
- package/src/modules/documents/backend/documents/[id]/CommentAnchorNavigation.ts +88 -0
- package/src/modules/documents/backend/documents/[id]/CommentComposer.tsx +136 -0
- package/src/modules/documents/backend/documents/[id]/CommentThreadList.tsx +131 -0
- package/src/modules/documents/backend/documents/[id]/CommentsRail.tsx +138 -0
- package/src/modules/documents/backend/documents/[id]/DocumentCanvas.tsx +111 -0
- package/src/modules/documents/backend/documents/[id]/DocumentEditorErrorBoundary.tsx +39 -0
- package/src/modules/documents/backend/documents/[id]/DocumentEditorIsland.tsx +50 -0
- package/src/modules/documents/backend/documents/[id]/DocumentEditorSurface.tsx +162 -0
- package/src/modules/documents/backend/documents/[id]/DocumentNavigator.tsx +129 -0
- package/src/modules/documents/backend/documents/[id]/DocumentPageClient.tsx +463 -0
- package/src/modules/documents/backend/documents/[id]/EditorColorTools.tsx +71 -0
- package/src/modules/documents/backend/documents/[id]/EditorStatusPresence.tsx +78 -0
- package/src/modules/documents/backend/documents/[id]/EditorToolbar.tsx +108 -0
- package/src/modules/documents/backend/documents/[id]/ExportMenu.tsx +144 -0
- package/src/modules/documents/backend/documents/[id]/MentionPicker.tsx +137 -0
- package/src/modules/documents/backend/documents/[id]/OutlinePane.tsx +98 -0
- package/src/modules/documents/backend/documents/[id]/RecordFieldsDialog.tsx +185 -0
- package/src/modules/documents/backend/documents/[id]/RelatedRecordsPanel.tsx +320 -0
- package/src/modules/documents/backend/documents/[id]/VersionHistoryPanel.tsx +244 -0
- package/src/modules/documents/backend/documents/[id]/VersionPreviewDialog.tsx +197 -0
- package/src/modules/documents/backend/documents/[id]/commentTypes.ts +192 -0
- package/src/modules/documents/backend/documents/[id]/componentCapabilities.ts +17 -0
- package/src/modules/documents/backend/documents/[id]/documentPagination.ts +352 -0
- package/src/modules/documents/backend/documents/[id]/editorPresenceStyles.ts +77 -0
- package/src/modules/documents/backend/documents/[id]/editorTypes.ts +84 -0
- package/src/modules/documents/backend/documents/[id]/page.meta.ts +12 -0
- package/src/modules/documents/backend/documents/[id]/page.tsx +6 -0
- package/src/modules/documents/backend/documents/[id]/relatedRecordModel.ts +49 -0
- package/src/modules/documents/backend/documents/[id]/restoreVersion.ts +49 -0
- package/src/modules/documents/backend/documents/[id]/useDocumentCollaboration.ts +458 -0
- package/src/modules/documents/backend/documents/[id]/useDocumentComments.ts +286 -0
- package/src/modules/documents/backend/documents/[id]/useDocumentEditor.ts +157 -0
- package/src/modules/documents/backend/documents/[id]/useDocumentTitle.ts +77 -0
- package/src/modules/documents/backend/documents/[id]/useEditorInsertions.ts +147 -0
- package/src/modules/documents/backend/documents/[id]/useFallbackContentPersistence.ts +277 -0
- package/src/modules/documents/backend/documents/[id]/useMentionPicker.ts +259 -0
- package/src/modules/documents/backend/documents/[id]/versionHistoryModel.ts +29 -0
- package/src/modules/documents/backend/documents/components/EntityPicker.tsx +171 -0
- package/src/modules/documents/backend/documents/components/EntityPickerResults.tsx +64 -0
- package/src/modules/documents/backend/documents/components/NewFromTemplateDialog.tsx +136 -0
- package/src/modules/documents/backend/documents/components/PrincipalPicker.tsx +90 -0
- package/src/modules/documents/backend/documents/components/ShareDialog.tsx +88 -0
- package/src/modules/documents/backend/documents/components/ShareDialogAddForm.tsx +113 -0
- package/src/modules/documents/backend/documents/components/ShareDialogList.tsx +117 -0
- package/src/modules/documents/backend/documents/components/TemplateBodyEditor.tsx +96 -0
- package/src/modules/documents/backend/documents/components/TemplateEditorDialog.tsx +171 -0
- package/src/modules/documents/backend/documents/components/TemplatePreview.tsx +43 -0
- package/src/modules/documents/backend/documents/components/TemplateSlotFields.tsx +72 -0
- package/src/modules/documents/backend/documents/components/TemplateSlotsEditor.tsx +72 -0
- package/src/modules/documents/backend/documents/components/principalPickerModel.ts +86 -0
- package/src/modules/documents/backend/documents/components/shareDialogModel.ts +94 -0
- package/src/modules/documents/backend/documents/components/templateUi.ts +128 -0
- package/src/modules/documents/backend/documents/components/useAvailableEntityRegistry.ts +43 -0
- package/src/modules/documents/backend/documents/components/useEntitySearch.ts +197 -0
- package/src/modules/documents/backend/documents/components/usePrincipalPicker.ts +165 -0
- package/src/modules/documents/backend/documents/components/useShareDialog.ts +267 -0
- package/src/modules/documents/backend/documents/components/useTemplateDetail.ts +54 -0
- package/src/modules/documents/backend/documents/components/useTemplateInstantiation.ts +252 -0
- package/src/modules/documents/backend/documents/documentUi.ts +134 -0
- package/src/modules/documents/backend/documents/documentsListTypes.ts +163 -0
- package/src/modules/documents/backend/documents/page.meta.ts +24 -0
- package/src/modules/documents/backend/documents/page.tsx +5 -0
- package/src/modules/documents/backend/documents/templates/TemplatesPageClient.tsx +93 -0
- package/src/modules/documents/backend/documents/templates/TemplatesTable.tsx +71 -0
- package/src/modules/documents/backend/documents/templates/page.meta.ts +32 -0
- package/src/modules/documents/backend/documents/templates/page.tsx +5 -0
- package/src/modules/documents/backend/documents/templates/useTemplatesPage.tsx +148 -0
- package/src/modules/documents/backend/documents/useDocumentsList.tsx +305 -0
- package/src/modules/documents/ce.ts +6 -0
- package/src/modules/documents/commands/aggregate.ts +128 -0
- package/src/modules/documents/commands/attachments.ts +309 -0
- package/src/modules/documents/commands/comments.ts +966 -0
- package/src/modules/documents/commands/content.ts +294 -0
- package/src/modules/documents/commands/document-crud.ts +609 -0
- package/src/modules/documents/commands/documents.ts +581 -0
- package/src/modules/documents/commands/duplicate.ts +772 -0
- package/src/modules/documents/commands/favorites.ts +171 -0
- package/src/modules/documents/commands/folders.ts +506 -0
- package/src/modules/documents/commands/index.ts +33 -0
- package/src/modules/documents/commands/interceptors.ts +402 -0
- package/src/modules/documents/commands/lifecycle.ts +333 -0
- package/src/modules/documents/commands/links.ts +486 -0
- package/src/modules/documents/commands/mutation-helpers.ts +48 -0
- package/src/modules/documents/commands/projection-types.ts +77 -0
- package/src/modules/documents/commands/shared.ts +219 -0
- package/src/modules/documents/commands/shares.ts +612 -0
- package/src/modules/documents/commands/side-effects.ts +130 -0
- package/src/modules/documents/commands/templates.ts +522 -0
- package/src/modules/documents/commands/versions.ts +537 -0
- package/src/modules/documents/commands/watchers.ts +181 -0
- package/src/modules/documents/data/entities.ts +631 -0
- package/src/modules/documents/data/extensions.ts +42 -0
- package/src/modules/documents/data/validators.ts +248 -0
- package/src/modules/documents/di.ts +33 -0
- package/src/modules/documents/encryption.ts +14 -0
- package/src/modules/documents/events.ts +23 -0
- package/src/modules/documents/i18n/.hardcoded-allowlist.json +9 -0
- package/src/modules/documents/i18n/de.json +522 -0
- package/src/modules/documents/i18n/en.json +522 -0
- package/src/modules/documents/i18n/es.json +522 -0
- package/src/modules/documents/i18n/ko.json +522 -0
- package/src/modules/documents/i18n/pl.json +522 -0
- package/src/modules/documents/index.ts +17 -0
- package/src/modules/documents/lib/attachmentServicePort.ts +94 -0
- package/src/modules/documents/lib/capabilities.ts +57 -0
- package/src/modules/documents/lib/collabCloseEvents.ts +26 -0
- package/src/modules/documents/lib/collabEndpoint.ts +43 -0
- package/src/modules/documents/lib/collabMaterializer.ts +140 -0
- package/src/modules/documents/lib/collabToken.ts +170 -0
- package/src/modules/documents/lib/collaborationAwareness.ts +102 -0
- package/src/modules/documents/lib/commentAnchors.ts +19 -0
- package/src/modules/documents/lib/constants.ts +39 -0
- package/src/modules/documents/lib/contentService.ts +340 -0
- package/src/modules/documents/lib/displayLabels.ts +31 -0
- package/src/modules/documents/lib/docxRenderer.ts +685 -0
- package/src/modules/documents/lib/duplicateContent.ts +32 -0
- package/src/modules/documents/lib/editorConfig.ts +371 -0
- package/src/modules/documents/lib/entityLinks.ts +250 -0
- package/src/modules/documents/lib/entityRegistry.server.ts +267 -0
- package/src/modules/documents/lib/entityRegistry.ts +345 -0
- package/src/modules/documents/lib/entityRegistryAvailability.server.ts +19 -0
- package/src/modules/documents/lib/entitySuggestion.ts +61 -0
- package/src/modules/documents/lib/favorites.ts +35 -0
- package/src/modules/documents/lib/folderHierarchySerialization.ts +34 -0
- package/src/modules/documents/lib/historyLimits.ts +154 -0
- package/src/modules/documents/lib/historyPolicy.ts +7 -0
- package/src/modules/documents/lib/organizationAccess.ts +44 -0
- package/src/modules/documents/lib/pdfHtml.ts +65 -0
- package/src/modules/documents/lib/pdfRenderer.ts +367 -0
- package/src/modules/documents/lib/permissions.ts +299 -0
- package/src/modules/documents/lib/platformServices.ts +70 -0
- package/src/modules/documents/lib/recordFieldInsertion.ts +72 -0
- package/src/modules/documents/lib/requestBody.ts +97 -0
- package/src/modules/documents/lib/resourceLimits.ts +94 -0
- package/src/modules/documents/lib/shareCounts.ts +44 -0
- package/src/modules/documents/lib/templateFill.ts +138 -0
- package/src/modules/documents/lib/templateInstantiation.ts +206 -0
- package/src/modules/documents/lib/templatePreviewDigest.ts +122 -0
- package/src/modules/documents/lib/templateSeeds.ts +248 -0
- package/src/modules/documents/lib/userLabels.ts +58 -0
- package/src/modules/documents/lib/versionContent.ts +163 -0
- package/src/modules/documents/lib/versionLabels.ts +9 -0
- package/src/modules/documents/lib/versioning.ts +29 -0
- package/src/modules/documents/lib/visibility.ts +610 -0
- package/src/modules/documents/lib/watchers.ts +129 -0
- package/src/modules/documents/migrations/.snapshot-open-mercato.json +2892 -0
- package/src/modules/documents/migrations/Migration20260708163836_documents.ts +50 -0
- package/src/modules/documents/migrations/Migration20260709164720_documents.ts +19 -0
- package/src/modules/documents/migrations/Migration20260710002318_documents.ts +35 -0
- package/src/modules/documents/migrations/Migration20260710071003_documents.ts +13 -0
- package/src/modules/documents/migrations/Migration20260712120000_documents.ts +13 -0
- package/src/modules/documents/migrations/Migration20260712183000_documents.ts +12 -0
- package/src/modules/documents/migrations/Migration20260713092156_documents.ts +43 -0
- package/src/modules/documents/migrations/Migration20260717000000_documents.ts +40 -0
- package/src/modules/documents/notifications.ts +45 -0
- package/src/modules/documents/search.ts +118 -0
- package/src/modules/documents/setup.ts +19 -0
- package/src/modules/documents/widgets/injection/related-documents/LinkDocumentDialog.tsx +224 -0
- package/src/modules/documents/widgets/injection/related-documents/context.ts +101 -0
- package/src/modules/documents/widgets/injection/related-documents/useRelatedDocuments.ts +112 -0
- package/src/modules/documents/widgets/injection/related-documents/widget.client.tsx +76 -0
- package/src/modules/documents/widgets/injection/related-documents/widget.ts +19 -0
- package/src/modules/documents/widgets/injection-table.ts +20 -0
- package/tsconfig.json +9 -0
- package/watch.mjs +6 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { hasAllFeatures } from '@open-mercato/shared/lib/auth/featureMatch'
|
|
2
|
+
import { hasTier, type DocumentTier } from './permissions'
|
|
3
|
+
|
|
4
|
+
export type DocumentCapabilities = {
|
|
5
|
+
canView: boolean
|
|
6
|
+
canComment: boolean
|
|
7
|
+
canEdit: boolean
|
|
8
|
+
canShare: boolean
|
|
9
|
+
canDelete: boolean
|
|
10
|
+
canCreate: boolean
|
|
11
|
+
canManageTemplates: boolean
|
|
12
|
+
canArchive: boolean
|
|
13
|
+
canDuplicate: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type DeriveDocumentCapabilitiesInput = {
|
|
17
|
+
relationshipTier: DocumentTier | null
|
|
18
|
+
managerOverride?: boolean
|
|
19
|
+
archived?: boolean
|
|
20
|
+
userFeatures: readonly string[]
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function hasFeature(userFeatures: readonly string[], feature: string): boolean {
|
|
24
|
+
return hasAllFeatures([feature], Array.from(userFeatures))
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function hasDocumentsManagerOverride(userFeatures: readonly string[]): boolean {
|
|
28
|
+
return hasFeature(userFeatures, 'documents.manage')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function deriveDocumentCapabilities(
|
|
32
|
+
input: DeriveDocumentCapabilitiesInput,
|
|
33
|
+
): DocumentCapabilities {
|
|
34
|
+
const managerOverride = input.managerOverride === true
|
|
35
|
+
&& hasDocumentsManagerOverride(input.userFeatures)
|
|
36
|
+
const hasRelationship = input.relationshipTier !== null || managerOverride
|
|
37
|
+
const canCommentByTier = managerOverride
|
|
38
|
+
|| hasTier(input.relationshipTier, 'commenter')
|
|
39
|
+
const canEditByTier = managerOverride
|
|
40
|
+
|| hasTier(input.relationshipTier, 'editor')
|
|
41
|
+
const canOwnByTier = managerOverride || input.relationshipTier === 'owner'
|
|
42
|
+
const archived = input.archived === true
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
canView: hasRelationship && hasFeature(input.userFeatures, 'documents.view'),
|
|
46
|
+
canComment: !archived && canCommentByTier && hasFeature(input.userFeatures, 'documents.view'),
|
|
47
|
+
canEdit: !archived && canEditByTier && hasFeature(input.userFeatures, 'documents.edit'),
|
|
48
|
+
canShare: !archived && canOwnByTier && hasFeature(input.userFeatures, 'documents.share'),
|
|
49
|
+
canDelete: canOwnByTier && hasFeature(input.userFeatures, 'documents.delete'),
|
|
50
|
+
canCreate: hasFeature(input.userFeatures, 'documents.create'),
|
|
51
|
+
canManageTemplates: hasFeature(input.userFeatures, 'documents.templates.manage'),
|
|
52
|
+
canArchive: canOwnByTier && hasFeature(input.userFeatures, 'documents.edit'),
|
|
53
|
+
canDuplicate: hasRelationship
|
|
54
|
+
&& hasFeature(input.userFeatures, 'documents.create')
|
|
55
|
+
&& hasFeature(input.userFeatures, 'documents.edit'),
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hocuspocus closes every socket of a room with `ResetConnection` (4205) both
|
|
3
|
+
* when the room only needs to re-authenticate (share/archive changes) and when
|
|
4
|
+
* its content was replaced server-side (version restore, content reset). The
|
|
5
|
+
* provider reconnects with the SAME local Y.Doc in both cases — after a
|
|
6
|
+
* content replacement that stale document would sync straight back into the
|
|
7
|
+
* freshly loaded room and silently undo the restore. The sidecar therefore
|
|
8
|
+
* closes content-replaced rooms with this dedicated reason so browsers know to
|
|
9
|
+
* discard their local document before reconnecting.
|
|
10
|
+
*
|
|
11
|
+
* Only the reason is significant. Hocuspocus multiplexes documents over one
|
|
12
|
+
* socket, so a per-document close reaches the browser as a Close *message*
|
|
13
|
+
* that the provider surfaces with code 1000 and the server-supplied reason;
|
|
14
|
+
* the 4205 code is only observed when the socket itself is closed.
|
|
15
|
+
*/
|
|
16
|
+
export const COLLAB_CONTENT_RESET_CLOSE_CODE = 4205
|
|
17
|
+
export const COLLAB_CONTENT_RESET_CLOSE_REASON = 'documents:content-reset'
|
|
18
|
+
export const COLLAB_CONTENT_RESET_CLOSE_EVENT = {
|
|
19
|
+
code: COLLAB_CONTENT_RESET_CLOSE_CODE,
|
|
20
|
+
reason: COLLAB_CONTENT_RESET_CLOSE_REASON,
|
|
21
|
+
} as const
|
|
22
|
+
|
|
23
|
+
export function isCollabContentResetCloseEvent(event: unknown): boolean {
|
|
24
|
+
if (!event || typeof event !== 'object') return false
|
|
25
|
+
return (event as { reason?: unknown }).reason === COLLAB_CONTENT_RESET_CLOSE_REASON
|
|
26
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type CollaborationEndpointOptions = {
|
|
2
|
+
nodeEnv?: string
|
|
3
|
+
allowLoopback?: boolean
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function isLoopbackHostname(hostname: string): boolean {
|
|
7
|
+
return hostname === 'localhost'
|
|
8
|
+
|| hostname.endsWith('.localhost')
|
|
9
|
+
|| hostname === '::1'
|
|
10
|
+
|| hostname === '::'
|
|
11
|
+
|| hostname === '0.0.0.0'
|
|
12
|
+
|| /^127(?:\.|$)/.test(hostname)
|
|
13
|
+
|| /^::ffff:7f[0-9a-f]{2}:/.test(hostname)
|
|
14
|
+
|| hostname === '::ffff:0:0'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function resolveDocumentsCollaborationEndpoint(
|
|
18
|
+
raw = process.env.NEXT_PUBLIC_DOCUMENTS_COLLAB_URL,
|
|
19
|
+
options: CollaborationEndpointOptions = {},
|
|
20
|
+
): string | null {
|
|
21
|
+
if (!raw || raw !== raw.trim()) return null
|
|
22
|
+
|
|
23
|
+
let endpoint: URL
|
|
24
|
+
try {
|
|
25
|
+
endpoint = new URL(raw)
|
|
26
|
+
} catch {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const hostname = endpoint.hostname
|
|
31
|
+
.replace(/^\[|\]$/g, '')
|
|
32
|
+
.toLowerCase()
|
|
33
|
+
.replace(/\.$/, '')
|
|
34
|
+
if (!['ws:', 'wss:'].includes(endpoint.protocol) || !hostname) return null
|
|
35
|
+
|
|
36
|
+
const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV
|
|
37
|
+
const allowLoopback = options.allowLoopback ?? (
|
|
38
|
+
nodeEnv !== 'production' || process.env.OM_DOCUMENTS_COLLAB_INTEGRATION === '1'
|
|
39
|
+
)
|
|
40
|
+
if (!allowLoopback && isLoopbackHostname(hostname)) return null
|
|
41
|
+
|
|
42
|
+
return raw
|
|
43
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
import type { JSONContent } from '@tiptap/core'
|
|
3
|
+
import { TiptapTransformer } from '@hocuspocus/transformer'
|
|
4
|
+
import { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
+
import * as Y from 'yjs'
|
|
6
|
+
import { deriveContentTextFromHtml } from './contentService'
|
|
7
|
+
import { COLLAB_FRAGMENT_FIELD, getDocumentEditorExtensions } from './editorConfig'
|
|
8
|
+
import { assertDocumentContentResourceLimits } from './resourceLimits'
|
|
9
|
+
|
|
10
|
+
type TiptapHtmlServer = typeof import('@tiptap/html/server')
|
|
11
|
+
|
|
12
|
+
const requireFromHere = createRequire(import.meta.url)
|
|
13
|
+
let tiptapHtmlServer: TiptapHtmlServer | null = null
|
|
14
|
+
|
|
15
|
+
function getTiptapHtmlServer(): TiptapHtmlServer {
|
|
16
|
+
if (!tiptapHtmlServer) {
|
|
17
|
+
tiptapHtmlServer = requireFromHere('@tiptap/html/server') as TiptapHtmlServer
|
|
18
|
+
}
|
|
19
|
+
return tiptapHtmlServer
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function hasRenderableContent(node: JSONContent): boolean {
|
|
23
|
+
if (node.type === 'text') return Boolean(node.text)
|
|
24
|
+
if (Array.isArray(node.content) && node.content.some(hasRenderableContent)) return true
|
|
25
|
+
return Boolean(node.type && node.type !== 'doc' && node.type !== 'paragraph' && node.type !== 'text')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function yDocToContent(ydoc: Y.Doc): { html: string; text: string } | null {
|
|
29
|
+
try {
|
|
30
|
+
if (ydoc.getXmlFragment(COLLAB_FRAGMENT_FIELD).length === 0) {
|
|
31
|
+
return { html: '', text: '' }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const json = TiptapTransformer.fromYdoc(ydoc, COLLAB_FRAGMENT_FIELD) as JSONContent | null
|
|
35
|
+
if (!json || !hasRenderableContent(json)) {
|
|
36
|
+
return { html: '', text: '' }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { generateHTML } = getTiptapHtmlServer()
|
|
40
|
+
const html = generateHTML(json, getDocumentEditorExtensions())
|
|
41
|
+
const text = deriveContentTextFromHtml(html)
|
|
42
|
+
assertDocumentContentResourceLimits({ contentHtml: html, contentText: text })
|
|
43
|
+
return { html, text }
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (isCrudHttpError(error) && error.status === 413) throw error
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function htmlToYDoc(html: string): Y.Doc {
|
|
51
|
+
assertDocumentContentResourceLimits({ contentHtml: html })
|
|
52
|
+
if (!html.trim()) return new Y.Doc()
|
|
53
|
+
|
|
54
|
+
const extensions = getDocumentEditorExtensions()
|
|
55
|
+
const { generateJSON } = getTiptapHtmlServer()
|
|
56
|
+
const json = generateJSON(html, extensions) as JSONContent
|
|
57
|
+
return TiptapTransformer.toYdoc(json, COLLAB_FRAGMENT_FIELD, extensions)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type MaterializedDocumentHtml = {
|
|
61
|
+
yjsState: Buffer
|
|
62
|
+
html: string
|
|
63
|
+
text: string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Convert authored HTML through the same editor/Yjs pipeline used by persisted
|
|
68
|
+
* document content. Callers that preview content before writing it must use the
|
|
69
|
+
* returned HTML too, otherwise the preview can differ from the canonical markup
|
|
70
|
+
* users receive after the document is created.
|
|
71
|
+
*/
|
|
72
|
+
export function materializeDocumentHtml(html: string): MaterializedDocumentHtml | null {
|
|
73
|
+
try {
|
|
74
|
+
const ydoc = htmlToYDoc(html)
|
|
75
|
+
const content = yDocToContent(ydoc)
|
|
76
|
+
if (!content) return null
|
|
77
|
+
const result = {
|
|
78
|
+
yjsState: Buffer.from(Y.encodeStateAsUpdate(ydoc)),
|
|
79
|
+
html: content.html,
|
|
80
|
+
text: content.text,
|
|
81
|
+
}
|
|
82
|
+
assertDocumentContentResourceLimits({
|
|
83
|
+
yjsState: result.yjsState,
|
|
84
|
+
contentHtml: result.html,
|
|
85
|
+
contentText: result.text,
|
|
86
|
+
})
|
|
87
|
+
return result
|
|
88
|
+
} catch (error) {
|
|
89
|
+
if (isCrudHttpError(error) && error.status === 413) throw error
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Replace REST-authored content as a Yjs update derived from the current CRDT
|
|
96
|
+
* epoch. Keeping the old structs as deleted tombstones means a retained client
|
|
97
|
+
* can merge the replacement without resurrecting or duplicating stale text.
|
|
98
|
+
*/
|
|
99
|
+
export function materializeDocumentContentReplacement(
|
|
100
|
+
existingState: Buffer | Uint8Array | null | undefined,
|
|
101
|
+
html: string,
|
|
102
|
+
): MaterializedDocumentHtml | null {
|
|
103
|
+
try {
|
|
104
|
+
assertDocumentContentResourceLimits({ yjsState: existingState, contentHtml: html })
|
|
105
|
+
const replacement = htmlToYDoc(html)
|
|
106
|
+
const ydoc = new Y.Doc()
|
|
107
|
+
if (existingState && existingState.length > 0) {
|
|
108
|
+
Y.applyUpdate(ydoc, new Uint8Array(existingState))
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const target = ydoc.getXmlFragment(COLLAB_FRAGMENT_FIELD)
|
|
112
|
+
const replacementNodes = replacement
|
|
113
|
+
.getXmlFragment(COLLAB_FRAGMENT_FIELD)
|
|
114
|
+
.toArray()
|
|
115
|
+
.filter((node): node is Y.XmlElement | Y.XmlText => (
|
|
116
|
+
node instanceof Y.XmlElement || node instanceof Y.XmlText
|
|
117
|
+
))
|
|
118
|
+
.map((node) => node.clone())
|
|
119
|
+
ydoc.transact(() => {
|
|
120
|
+
if (target.length > 0) target.delete(0, target.length)
|
|
121
|
+
if (replacementNodes.length > 0) target.insert(0, replacementNodes)
|
|
122
|
+
})
|
|
123
|
+
const content = yDocToContent(ydoc)
|
|
124
|
+
if (!content) return null
|
|
125
|
+
const result = {
|
|
126
|
+
yjsState: Buffer.from(Y.encodeStateAsUpdate(ydoc)),
|
|
127
|
+
html: content.html,
|
|
128
|
+
text: content.text,
|
|
129
|
+
}
|
|
130
|
+
assertDocumentContentResourceLimits({
|
|
131
|
+
yjsState: result.yjsState,
|
|
132
|
+
contentHtml: result.html,
|
|
133
|
+
contentText: result.text,
|
|
134
|
+
})
|
|
135
|
+
return result
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (isCrudHttpError(error) && error.status === 413) throw error
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { signJwt, verifyJwt } from '@open-mercato/shared/lib/auth/jwt'
|
|
2
|
+
import type { DocumentTier } from '../lib/permissions'
|
|
3
|
+
|
|
4
|
+
export const COLLAB_TOKEN_AUDIENCE = 'documents-collab'
|
|
5
|
+
export const COLLAB_TOKEN_V2_AUDIENCE = 'documents-collab-v2'
|
|
6
|
+
export const COLLAB_TOKEN_TTL_SECONDS = 60
|
|
7
|
+
export const COLLAB_TOKEN_CLOCK_SKEW_SECONDS = 5
|
|
8
|
+
export const COLLAB_TOKEN_V2_MIN_SECRET_BYTES = 32
|
|
9
|
+
|
|
10
|
+
export type CollabTokenClaims = {
|
|
11
|
+
userId: string
|
|
12
|
+
tenantId: string
|
|
13
|
+
organizationId: string
|
|
14
|
+
documentId: string
|
|
15
|
+
tier: DocumentTier
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type CollabTokenV2MintInput = CollabTokenClaims & {
|
|
19
|
+
tokenVersion: 2
|
|
20
|
+
readOnly: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type VerifiedCollabTokenV2Claims = CollabTokenV2MintInput & {
|
|
24
|
+
exp: number
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isNonEmptyString(value: unknown): value is string {
|
|
28
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function isDocumentTier(value: unknown): value is DocumentTier {
|
|
32
|
+
return value === 'owner' || value === 'editor' || value === 'commenter' || value === 'viewer'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readV2Secret(): string | null {
|
|
36
|
+
const secret = process.env.DOCUMENTS_COLLAB_JWT_SECRET_V2?.trim()
|
|
37
|
+
if (!secret || new TextEncoder().encode(secret).byteLength < COLLAB_TOKEN_V2_MIN_SECRET_BYTES) {
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
const explicitV1Secret = process.env.DOCUMENTS_COLLAB_JWT_SECRET?.trim()
|
|
41
|
+
return explicitV1Secret === secret ? null : secret
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isCollabTokenV2Ready(): boolean {
|
|
45
|
+
return readV2Secret() !== null
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function requireV2Secret(): string {
|
|
49
|
+
const secret = readV2Secret()
|
|
50
|
+
if (!secret) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`[internal] DOCUMENTS_COLLAB_JWT_SECRET_V2 must contain at least ${COLLAB_TOKEN_V2_MIN_SECRET_BYTES} UTF-8 bytes and differ from DOCUMENTS_COLLAB_JWT_SECRET`,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
return secret
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readCommonClaims(claims: Record<string, unknown>): CollabTokenClaims | null {
|
|
59
|
+
const { userId, tenantId, organizationId, documentId, tier } = claims
|
|
60
|
+
if (
|
|
61
|
+
!isNonEmptyString(userId)
|
|
62
|
+
|| !isNonEmptyString(tenantId)
|
|
63
|
+
|| !isNonEmptyString(organizationId)
|
|
64
|
+
|| !isNonEmptyString(documentId)
|
|
65
|
+
|| !isDocumentTier(tier)
|
|
66
|
+
) {
|
|
67
|
+
return null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { userId, tenantId, organizationId, documentId, tier }
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function mintCollabToken(claims: CollabTokenClaims): string {
|
|
74
|
+
return signJwt(
|
|
75
|
+
{ ...claims, sub: claims.userId },
|
|
76
|
+
{
|
|
77
|
+
audience: COLLAB_TOKEN_AUDIENCE,
|
|
78
|
+
secret: process.env.DOCUMENTS_COLLAB_JWT_SECRET,
|
|
79
|
+
expiresInSec: COLLAB_TOKEN_TTL_SECONDS,
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Legacy v1 acceptance is a rollout bridge only. Nothing mints v1 tokens
|
|
86
|
+
* anymore, so the sidecar accepts them solely while a dedicated
|
|
87
|
+
* DOCUMENTS_COLLAB_JWT_SECRET is explicitly configured and at least as strong
|
|
88
|
+
* as the v2 minimum. Default deployments (derived JWT_SECRET fallback) accept
|
|
89
|
+
* v2 tokens exclusively.
|
|
90
|
+
*/
|
|
91
|
+
export function resolveLegacyCollabTokenVerifier(
|
|
92
|
+
env: Record<string, string | undefined> = process.env,
|
|
93
|
+
): ((token: string) => CollabTokenClaims | null) | null {
|
|
94
|
+
const secret = env.DOCUMENTS_COLLAB_JWT_SECRET?.trim()
|
|
95
|
+
if (!secret || new TextEncoder().encode(secret).byteLength < COLLAB_TOKEN_V2_MIN_SECRET_BYTES) {
|
|
96
|
+
return null
|
|
97
|
+
}
|
|
98
|
+
return verifyCollabToken
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function verifyCollabToken(token: string): CollabTokenClaims | null {
|
|
102
|
+
let payload: unknown
|
|
103
|
+
try {
|
|
104
|
+
payload = verifyJwt(token, {
|
|
105
|
+
audience: COLLAB_TOKEN_AUDIENCE,
|
|
106
|
+
secret: process.env.DOCUMENTS_COLLAB_JWT_SECRET,
|
|
107
|
+
})
|
|
108
|
+
} catch {
|
|
109
|
+
return null
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!payload || typeof payload !== 'object') return null
|
|
113
|
+
|
|
114
|
+
return readCommonClaims(payload as Record<string, unknown>)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function mintCollabTokenV2(claims: CollabTokenV2MintInput): string {
|
|
118
|
+
return signJwt(
|
|
119
|
+
{ ...claims, sub: claims.userId },
|
|
120
|
+
{
|
|
121
|
+
audience: COLLAB_TOKEN_V2_AUDIENCE,
|
|
122
|
+
secret: requireV2Secret(),
|
|
123
|
+
expiresInSec: COLLAB_TOKEN_TTL_SECONDS,
|
|
124
|
+
},
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function verifyCollabTokenV2(token: string): VerifiedCollabTokenV2Claims | null {
|
|
129
|
+
const secret = readV2Secret()
|
|
130
|
+
if (!secret) return null
|
|
131
|
+
|
|
132
|
+
let payload: unknown
|
|
133
|
+
try {
|
|
134
|
+
payload = verifyJwt(token, {
|
|
135
|
+
audience: COLLAB_TOKEN_V2_AUDIENCE,
|
|
136
|
+
secret,
|
|
137
|
+
})
|
|
138
|
+
} catch {
|
|
139
|
+
return null
|
|
140
|
+
}
|
|
141
|
+
if (!payload || typeof payload !== 'object') return null
|
|
142
|
+
|
|
143
|
+
const claims = payload as Record<string, unknown>
|
|
144
|
+
const common = readCommonClaims(claims)
|
|
145
|
+
const { exp, iat, readOnly, tokenVersion } = claims
|
|
146
|
+
const now = Math.floor(Date.now() / 1000)
|
|
147
|
+
if (
|
|
148
|
+
!common
|
|
149
|
+
|| tokenVersion !== 2
|
|
150
|
+
|| typeof readOnly !== 'boolean'
|
|
151
|
+
|| typeof exp !== 'number'
|
|
152
|
+
|| !Number.isInteger(exp)
|
|
153
|
+
|| typeof iat !== 'number'
|
|
154
|
+
|| !Number.isInteger(iat)
|
|
155
|
+
|| exp <= now
|
|
156
|
+
|| exp <= iat
|
|
157
|
+
|| exp - iat > COLLAB_TOKEN_TTL_SECONDS
|
|
158
|
+
|| iat > now + COLLAB_TOKEN_CLOCK_SKEW_SECONDS
|
|
159
|
+
|| exp > now + COLLAB_TOKEN_TTL_SECONDS + COLLAB_TOKEN_CLOCK_SKEW_SECONDS
|
|
160
|
+
) {
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
...common,
|
|
166
|
+
tokenVersion,
|
|
167
|
+
readOnly,
|
|
168
|
+
exp,
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { sanitizeDocumentsDisplayLabel } from './displayLabels'
|
|
2
|
+
|
|
3
|
+
export const COLLABORATION_COLOR_FALLBACK = '#64748b'
|
|
4
|
+
|
|
5
|
+
const COLLABORATION_COLOR_PATTERN = /^#[0-9a-f]{6}$/i
|
|
6
|
+
const UNSAFE_AWARENESS_NAME_PATTERN =
|
|
7
|
+
/[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u202a-\u202e\u2060-\u2069\ufeff]/u
|
|
8
|
+
const MAX_AWARENESS_NAME_LENGTH = 120
|
|
9
|
+
|
|
10
|
+
function isEncryptedAwarenessName(value: string): boolean {
|
|
11
|
+
const parts = value.split(':')
|
|
12
|
+
return parts.length === 4 && parts[3] === 'v1'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function hashString(value: string): number {
|
|
16
|
+
let hash = 2166136261
|
|
17
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
18
|
+
hash ^= value.charCodeAt(index)
|
|
19
|
+
hash = Math.imul(hash, 16777619)
|
|
20
|
+
}
|
|
21
|
+
return hash >>> 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function channelToHex(value: number): string {
|
|
25
|
+
return Math.round(value).toString(16).padStart(2, '0')
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function hslToHex(hue: number, saturationPercent: number, lightnessPercent: number): string {
|
|
29
|
+
const saturation = saturationPercent / 100
|
|
30
|
+
const lightness = lightnessPercent / 100
|
|
31
|
+
const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation
|
|
32
|
+
const intermediate = chroma * (1 - Math.abs(((hue / 60) % 2) - 1))
|
|
33
|
+
const match = lightness - chroma / 2
|
|
34
|
+
const [red, green, blue] =
|
|
35
|
+
hue < 60 ? [chroma, intermediate, 0]
|
|
36
|
+
: hue < 120 ? [intermediate, chroma, 0]
|
|
37
|
+
: hue < 180 ? [0, chroma, intermediate]
|
|
38
|
+
: hue < 240 ? [0, intermediate, chroma]
|
|
39
|
+
: hue < 300 ? [intermediate, 0, chroma]
|
|
40
|
+
: [chroma, 0, intermediate]
|
|
41
|
+
return `#${channelToHex((red + match) * 255)}${channelToHex((green + match) * 255)}${channelToHex((blue + match) * 255)}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Awareness colors are interpolated into inline styles by TipTap. Accept only
|
|
46
|
+
* the single canonical representation emitted by the server, never general
|
|
47
|
+
* CSS color syntax.
|
|
48
|
+
*/
|
|
49
|
+
export function normalizeCollaborationColor(value: unknown): string {
|
|
50
|
+
if (typeof value !== 'string' || !COLLABORATION_COLOR_PATTERN.test(value)) {
|
|
51
|
+
return COLLABORATION_COLOR_FALLBACK
|
|
52
|
+
}
|
|
53
|
+
return value.toLowerCase()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function resolveCollaborationUserColor(userId: string): string {
|
|
57
|
+
return hslToHex(hashString(userId) % 360, 64, 42)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Presence names come from an authenticated profile, but still cross the Yjs
|
|
62
|
+
* awareness boundary. Reject control, directionality, zero-width and UUID
|
|
63
|
+
* content and encryption envelopes so a collaborator cannot visually
|
|
64
|
+
* impersonate another identity or leak internal data through a caret label.
|
|
65
|
+
*/
|
|
66
|
+
export function sanitizeCollaborationAwarenessName(value: unknown): string {
|
|
67
|
+
const label = sanitizeDocumentsDisplayLabel(value)
|
|
68
|
+
if (
|
|
69
|
+
!label
|
|
70
|
+
|| label.length > MAX_AWARENESS_NAME_LENGTH
|
|
71
|
+
|| UNSAFE_AWARENESS_NAME_PATTERN.test(label)
|
|
72
|
+
|| isEncryptedAwarenessName(label)
|
|
73
|
+
) {
|
|
74
|
+
return ''
|
|
75
|
+
}
|
|
76
|
+
return label
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function firstSafeCollaborationAwarenessName(...values: unknown[]): string {
|
|
80
|
+
for (const value of values) {
|
|
81
|
+
const label = sanitizeCollaborationAwarenessName(value)
|
|
82
|
+
if (label) return label
|
|
83
|
+
}
|
|
84
|
+
return ''
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type CanonicalCollaborationAwarenessUser = {
|
|
88
|
+
id: string
|
|
89
|
+
name: string
|
|
90
|
+
color: string
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function createCanonicalCollaborationAwarenessUser(
|
|
94
|
+
userId: string,
|
|
95
|
+
name: unknown,
|
|
96
|
+
): CanonicalCollaborationAwarenessUser {
|
|
97
|
+
return {
|
|
98
|
+
id: userId,
|
|
99
|
+
name: sanitizeCollaborationAwarenessName(name),
|
|
100
|
+
color: resolveCollaborationUserColor(userId),
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
documentCommentAnchorWriteSchema,
|
|
3
|
+
type DocumentCommentAnchor,
|
|
4
|
+
} from '../data/validators'
|
|
5
|
+
|
|
6
|
+
export type NormalizedDocumentCommentAnchor =
|
|
7
|
+
| DocumentCommentAnchor
|
|
8
|
+
| { kind: 'legacy-unknown' }
|
|
9
|
+
|
|
10
|
+
export function normalizeDocumentCommentAnchor(value: unknown): NormalizedDocumentCommentAnchor {
|
|
11
|
+
const parsed = documentCommentAnchorWriteSchema.safeParse(value)
|
|
12
|
+
return parsed.success ? parsed.data : { kind: 'legacy-unknown' }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isChangedDocumentCommentAnchor(
|
|
16
|
+
value: NormalizedDocumentCommentAnchor,
|
|
17
|
+
): value is { kind: 'legacy-unknown' } {
|
|
18
|
+
return 'kind' in value && value.kind === 'legacy-unknown'
|
|
19
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const DOCUMENTS_ENTITY_IDS = {
|
|
2
|
+
document: 'documents:document',
|
|
3
|
+
documentContent: 'documents:document_content',
|
|
4
|
+
documentFolder: 'documents:document_folder',
|
|
5
|
+
documentShare: 'documents:document_share',
|
|
6
|
+
documentComment: 'documents:document_comment',
|
|
7
|
+
documentFavorite: 'documents:document_favorite',
|
|
8
|
+
documentWatcher: 'documents:document_watcher',
|
|
9
|
+
documentVersion: 'documents:document_version',
|
|
10
|
+
documentAttachment: 'documents:document_attachment',
|
|
11
|
+
documentTemplate: 'documents:document_template',
|
|
12
|
+
documentEntityLink: 'documents:document_entity_link',
|
|
13
|
+
} as const
|
|
14
|
+
|
|
15
|
+
/** Maximum number of folder nodes from a root through its deepest descendant. */
|
|
16
|
+
export const DOCUMENTS_MAX_FOLDER_DEPTH = 64
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Maximum active folders one organization may hold. A navigable folder tree
|
|
20
|
+
* stays in the tens or low hundreds, so this only stops runaway automated
|
|
21
|
+
* creation while bounding the manager-override listing that decrypts every
|
|
22
|
+
* folder in scope.
|
|
23
|
+
*/
|
|
24
|
+
export const DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION = 2_000
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Upper bound for one manager-override folder listing. Kept far above the
|
|
28
|
+
* creation cap so an organization that predates that cap still lists a
|
|
29
|
+
* coherent tree it can prune, instead of losing folder navigation entirely.
|
|
30
|
+
*/
|
|
31
|
+
export const DOCUMENTS_MAX_LISTED_FOLDERS = 5_000
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Upper bound for one document's share listing. Explicit sharing stays in the
|
|
35
|
+
* tens, and the mention path can only add one share per distinct mentioned
|
|
36
|
+
* user, so this sits at the comment cap and keeps the listing (plus its
|
|
37
|
+
* principal-label fan-out) bounded the way the comment and version lists are.
|
|
38
|
+
*/
|
|
39
|
+
export const DOCUMENTS_MAX_LISTED_SHARES = 500
|