@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,32 @@
|
|
|
1
|
+
import { hasAllFeatures } from "@open-mercato/shared/lib/auth/featureMatch";
|
|
2
|
+
import { hasTier } from "./permissions.js";
|
|
3
|
+
function hasFeature(userFeatures, feature) {
|
|
4
|
+
return hasAllFeatures([feature], Array.from(userFeatures));
|
|
5
|
+
}
|
|
6
|
+
function hasDocumentsManagerOverride(userFeatures) {
|
|
7
|
+
return hasFeature(userFeatures, "documents.manage");
|
|
8
|
+
}
|
|
9
|
+
function deriveDocumentCapabilities(input) {
|
|
10
|
+
const managerOverride = input.managerOverride === true && hasDocumentsManagerOverride(input.userFeatures);
|
|
11
|
+
const hasRelationship = input.relationshipTier !== null || managerOverride;
|
|
12
|
+
const canCommentByTier = managerOverride || hasTier(input.relationshipTier, "commenter");
|
|
13
|
+
const canEditByTier = managerOverride || hasTier(input.relationshipTier, "editor");
|
|
14
|
+
const canOwnByTier = managerOverride || input.relationshipTier === "owner";
|
|
15
|
+
const archived = input.archived === true;
|
|
16
|
+
return {
|
|
17
|
+
canView: hasRelationship && hasFeature(input.userFeatures, "documents.view"),
|
|
18
|
+
canComment: !archived && canCommentByTier && hasFeature(input.userFeatures, "documents.view"),
|
|
19
|
+
canEdit: !archived && canEditByTier && hasFeature(input.userFeatures, "documents.edit"),
|
|
20
|
+
canShare: !archived && canOwnByTier && hasFeature(input.userFeatures, "documents.share"),
|
|
21
|
+
canDelete: canOwnByTier && hasFeature(input.userFeatures, "documents.delete"),
|
|
22
|
+
canCreate: hasFeature(input.userFeatures, "documents.create"),
|
|
23
|
+
canManageTemplates: hasFeature(input.userFeatures, "documents.templates.manage"),
|
|
24
|
+
canArchive: canOwnByTier && hasFeature(input.userFeatures, "documents.edit"),
|
|
25
|
+
canDuplicate: hasRelationship && hasFeature(input.userFeatures, "documents.create") && hasFeature(input.userFeatures, "documents.edit")
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
deriveDocumentCapabilities,
|
|
30
|
+
hasDocumentsManagerOverride
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=capabilities.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/capabilities.ts"],
|
|
4
|
+
"sourcesContent": ["import { hasAllFeatures } from '@open-mercato/shared/lib/auth/featureMatch'\nimport { hasTier, type DocumentTier } from './permissions'\n\nexport type DocumentCapabilities = {\n canView: boolean\n canComment: boolean\n canEdit: boolean\n canShare: boolean\n canDelete: boolean\n canCreate: boolean\n canManageTemplates: boolean\n canArchive: boolean\n canDuplicate: boolean\n}\n\nexport type DeriveDocumentCapabilitiesInput = {\n relationshipTier: DocumentTier | null\n managerOverride?: boolean\n archived?: boolean\n userFeatures: readonly string[]\n}\n\nfunction hasFeature(userFeatures: readonly string[], feature: string): boolean {\n return hasAllFeatures([feature], Array.from(userFeatures))\n}\n\nexport function hasDocumentsManagerOverride(userFeatures: readonly string[]): boolean {\n return hasFeature(userFeatures, 'documents.manage')\n}\n\nexport function deriveDocumentCapabilities(\n input: DeriveDocumentCapabilitiesInput,\n): DocumentCapabilities {\n const managerOverride = input.managerOverride === true\n && hasDocumentsManagerOverride(input.userFeatures)\n const hasRelationship = input.relationshipTier !== null || managerOverride\n const canCommentByTier = managerOverride\n || hasTier(input.relationshipTier, 'commenter')\n const canEditByTier = managerOverride\n || hasTier(input.relationshipTier, 'editor')\n const canOwnByTier = managerOverride || input.relationshipTier === 'owner'\n const archived = input.archived === true\n\n return {\n canView: hasRelationship && hasFeature(input.userFeatures, 'documents.view'),\n canComment: !archived && canCommentByTier && hasFeature(input.userFeatures, 'documents.view'),\n canEdit: !archived && canEditByTier && hasFeature(input.userFeatures, 'documents.edit'),\n canShare: !archived && canOwnByTier && hasFeature(input.userFeatures, 'documents.share'),\n canDelete: canOwnByTier && hasFeature(input.userFeatures, 'documents.delete'),\n canCreate: hasFeature(input.userFeatures, 'documents.create'),\n canManageTemplates: hasFeature(input.userFeatures, 'documents.templates.manage'),\n canArchive: canOwnByTier && hasFeature(input.userFeatures, 'documents.edit'),\n canDuplicate: hasRelationship\n && hasFeature(input.userFeatures, 'documents.create')\n && hasFeature(input.userFeatures, 'documents.edit'),\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,sBAAsB;AAC/B,SAAS,eAAkC;AAqB3C,SAAS,WAAW,cAAiC,SAA0B;AAC7E,SAAO,eAAe,CAAC,OAAO,GAAG,MAAM,KAAK,YAAY,CAAC;AAC3D;AAEO,SAAS,4BAA4B,cAA0C;AACpF,SAAO,WAAW,cAAc,kBAAkB;AACpD;AAEO,SAAS,2BACd,OACsB;AACtB,QAAM,kBAAkB,MAAM,oBAAoB,QAC7C,4BAA4B,MAAM,YAAY;AACnD,QAAM,kBAAkB,MAAM,qBAAqB,QAAQ;AAC3D,QAAM,mBAAmB,mBACpB,QAAQ,MAAM,kBAAkB,WAAW;AAChD,QAAM,gBAAgB,mBACjB,QAAQ,MAAM,kBAAkB,QAAQ;AAC7C,QAAM,eAAe,mBAAmB,MAAM,qBAAqB;AACnE,QAAM,WAAW,MAAM,aAAa;AAEpC,SAAO;AAAA,IACL,SAAS,mBAAmB,WAAW,MAAM,cAAc,gBAAgB;AAAA,IAC3E,YAAY,CAAC,YAAY,oBAAoB,WAAW,MAAM,cAAc,gBAAgB;AAAA,IAC5F,SAAS,CAAC,YAAY,iBAAiB,WAAW,MAAM,cAAc,gBAAgB;AAAA,IACtF,UAAU,CAAC,YAAY,gBAAgB,WAAW,MAAM,cAAc,iBAAiB;AAAA,IACvF,WAAW,gBAAgB,WAAW,MAAM,cAAc,kBAAkB;AAAA,IAC5E,WAAW,WAAW,MAAM,cAAc,kBAAkB;AAAA,IAC5D,oBAAoB,WAAW,MAAM,cAAc,4BAA4B;AAAA,IAC/E,YAAY,gBAAgB,WAAW,MAAM,cAAc,gBAAgB;AAAA,IAC3E,cAAc,mBACT,WAAW,MAAM,cAAc,kBAAkB,KACjD,WAAW,MAAM,cAAc,gBAAgB;AAAA,EACtD;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const COLLAB_CONTENT_RESET_CLOSE_CODE = 4205;
|
|
2
|
+
const COLLAB_CONTENT_RESET_CLOSE_REASON = "documents:content-reset";
|
|
3
|
+
const COLLAB_CONTENT_RESET_CLOSE_EVENT = {
|
|
4
|
+
code: COLLAB_CONTENT_RESET_CLOSE_CODE,
|
|
5
|
+
reason: COLLAB_CONTENT_RESET_CLOSE_REASON
|
|
6
|
+
};
|
|
7
|
+
function isCollabContentResetCloseEvent(event) {
|
|
8
|
+
if (!event || typeof event !== "object") return false;
|
|
9
|
+
return event.reason === COLLAB_CONTENT_RESET_CLOSE_REASON;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
COLLAB_CONTENT_RESET_CLOSE_CODE,
|
|
13
|
+
COLLAB_CONTENT_RESET_CLOSE_EVENT,
|
|
14
|
+
COLLAB_CONTENT_RESET_CLOSE_REASON,
|
|
15
|
+
isCollabContentResetCloseEvent
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=collabCloseEvents.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/collabCloseEvents.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Hocuspocus closes every socket of a room with `ResetConnection` (4205) both\n * when the room only needs to re-authenticate (share/archive changes) and when\n * its content was replaced server-side (version restore, content reset). The\n * provider reconnects with the SAME local Y.Doc in both cases \u2014 after a\n * content replacement that stale document would sync straight back into the\n * freshly loaded room and silently undo the restore. The sidecar therefore\n * closes content-replaced rooms with this dedicated reason so browsers know to\n * discard their local document before reconnecting.\n *\n * Only the reason is significant. Hocuspocus multiplexes documents over one\n * socket, so a per-document close reaches the browser as a Close *message*\n * that the provider surfaces with code 1000 and the server-supplied reason;\n * the 4205 code is only observed when the socket itself is closed.\n */\nexport const COLLAB_CONTENT_RESET_CLOSE_CODE = 4205\nexport const COLLAB_CONTENT_RESET_CLOSE_REASON = 'documents:content-reset'\nexport const COLLAB_CONTENT_RESET_CLOSE_EVENT = {\n code: COLLAB_CONTENT_RESET_CLOSE_CODE,\n reason: COLLAB_CONTENT_RESET_CLOSE_REASON,\n} as const\n\nexport function isCollabContentResetCloseEvent(event: unknown): boolean {\n if (!event || typeof event !== 'object') return false\n return (event as { reason?: unknown }).reason === COLLAB_CONTENT_RESET_CLOSE_REASON\n}\n"],
|
|
5
|
+
"mappings": "AAeO,MAAM,kCAAkC;AACxC,MAAM,oCAAoC;AAC1C,MAAM,mCAAmC;AAAA,EAC9C,MAAM;AAAA,EACN,QAAQ;AACV;AAEO,SAAS,+BAA+B,OAAyB;AACtE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,SAAQ,MAA+B,WAAW;AACpD;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
function isLoopbackHostname(hostname) {
|
|
2
|
+
return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "::1" || hostname === "::" || hostname === "0.0.0.0" || /^127(?:\.|$)/.test(hostname) || /^::ffff:7f[0-9a-f]{2}:/.test(hostname) || hostname === "::ffff:0:0";
|
|
3
|
+
}
|
|
4
|
+
function resolveDocumentsCollaborationEndpoint(raw = process.env.NEXT_PUBLIC_DOCUMENTS_COLLAB_URL, options = {}) {
|
|
5
|
+
if (!raw || raw !== raw.trim()) return null;
|
|
6
|
+
let endpoint;
|
|
7
|
+
try {
|
|
8
|
+
endpoint = new URL(raw);
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const hostname = endpoint.hostname.replace(/^\[|\]$/g, "").toLowerCase().replace(/\.$/, "");
|
|
13
|
+
if (!["ws:", "wss:"].includes(endpoint.protocol) || !hostname) return null;
|
|
14
|
+
const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
|
|
15
|
+
const allowLoopback = options.allowLoopback ?? (nodeEnv !== "production" || process.env.OM_DOCUMENTS_COLLAB_INTEGRATION === "1");
|
|
16
|
+
if (!allowLoopback && isLoopbackHostname(hostname)) return null;
|
|
17
|
+
return raw;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
resolveDocumentsCollaborationEndpoint
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=collabEndpoint.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/collabEndpoint.ts"],
|
|
4
|
+
"sourcesContent": ["export type CollaborationEndpointOptions = {\n nodeEnv?: string\n allowLoopback?: boolean\n}\n\nfunction isLoopbackHostname(hostname: string): boolean {\n return hostname === 'localhost'\n || hostname.endsWith('.localhost')\n || hostname === '::1'\n || hostname === '::'\n || hostname === '0.0.0.0'\n || /^127(?:\\.|$)/.test(hostname)\n || /^::ffff:7f[0-9a-f]{2}:/.test(hostname)\n || hostname === '::ffff:0:0'\n}\n\nexport function resolveDocumentsCollaborationEndpoint(\n raw = process.env.NEXT_PUBLIC_DOCUMENTS_COLLAB_URL,\n options: CollaborationEndpointOptions = {},\n): string | null {\n if (!raw || raw !== raw.trim()) return null\n\n let endpoint: URL\n try {\n endpoint = new URL(raw)\n } catch {\n return null\n }\n\n const hostname = endpoint.hostname\n .replace(/^\\[|\\]$/g, '')\n .toLowerCase()\n .replace(/\\.$/, '')\n if (!['ws:', 'wss:'].includes(endpoint.protocol) || !hostname) return null\n\n const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV\n const allowLoopback = options.allowLoopback ?? (\n nodeEnv !== 'production' || process.env.OM_DOCUMENTS_COLLAB_INTEGRATION === '1'\n )\n if (!allowLoopback && isLoopbackHostname(hostname)) return null\n\n return raw\n}\n"],
|
|
5
|
+
"mappings": "AAKA,SAAS,mBAAmB,UAA2B;AACrD,SAAO,aAAa,eACf,SAAS,SAAS,YAAY,KAC9B,aAAa,SACb,aAAa,QACb,aAAa,aACb,eAAe,KAAK,QAAQ,KAC5B,yBAAyB,KAAK,QAAQ,KACtC,aAAa;AACpB;AAEO,SAAS,sCACd,MAAM,QAAQ,IAAI,kCAClB,UAAwC,CAAC,GAC1B;AACf,MAAI,CAAC,OAAO,QAAQ,IAAI,KAAK,EAAG,QAAO;AAEvC,MAAI;AACJ,MAAI;AACF,eAAW,IAAI,IAAI,GAAG;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,SAAS,SACvB,QAAQ,YAAY,EAAE,EACtB,YAAY,EACZ,QAAQ,OAAO,EAAE;AACpB,MAAI,CAAC,CAAC,OAAO,MAAM,EAAE,SAAS,SAAS,QAAQ,KAAK,CAAC,SAAU,QAAO;AAEtE,QAAM,UAAU,QAAQ,WAAW,QAAQ,IAAI;AAC/C,QAAM,gBAAgB,QAAQ,kBAC5B,YAAY,gBAAgB,QAAQ,IAAI,oCAAoC;AAE9E,MAAI,CAAC,iBAAiB,mBAAmB,QAAQ,EAAG,QAAO;AAE3D,SAAO;AACT;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { TiptapTransformer } from "@hocuspocus/transformer";
|
|
3
|
+
import { isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
4
|
+
import * as Y from "yjs";
|
|
5
|
+
import { deriveContentTextFromHtml } from "./contentService.js";
|
|
6
|
+
import { COLLAB_FRAGMENT_FIELD, getDocumentEditorExtensions } from "./editorConfig.js";
|
|
7
|
+
import { assertDocumentContentResourceLimits } from "./resourceLimits.js";
|
|
8
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
9
|
+
let tiptapHtmlServer = null;
|
|
10
|
+
function getTiptapHtmlServer() {
|
|
11
|
+
if (!tiptapHtmlServer) {
|
|
12
|
+
tiptapHtmlServer = requireFromHere("@tiptap/html/server");
|
|
13
|
+
}
|
|
14
|
+
return tiptapHtmlServer;
|
|
15
|
+
}
|
|
16
|
+
function hasRenderableContent(node) {
|
|
17
|
+
if (node.type === "text") return Boolean(node.text);
|
|
18
|
+
if (Array.isArray(node.content) && node.content.some(hasRenderableContent)) return true;
|
|
19
|
+
return Boolean(node.type && node.type !== "doc" && node.type !== "paragraph" && node.type !== "text");
|
|
20
|
+
}
|
|
21
|
+
function yDocToContent(ydoc) {
|
|
22
|
+
try {
|
|
23
|
+
if (ydoc.getXmlFragment(COLLAB_FRAGMENT_FIELD).length === 0) {
|
|
24
|
+
return { html: "", text: "" };
|
|
25
|
+
}
|
|
26
|
+
const json = TiptapTransformer.fromYdoc(ydoc, COLLAB_FRAGMENT_FIELD);
|
|
27
|
+
if (!json || !hasRenderableContent(json)) {
|
|
28
|
+
return { html: "", text: "" };
|
|
29
|
+
}
|
|
30
|
+
const { generateHTML } = getTiptapHtmlServer();
|
|
31
|
+
const html = generateHTML(json, getDocumentEditorExtensions());
|
|
32
|
+
const text = deriveContentTextFromHtml(html);
|
|
33
|
+
assertDocumentContentResourceLimits({ contentHtml: html, contentText: text });
|
|
34
|
+
return { html, text };
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (isCrudHttpError(error) && error.status === 413) throw error;
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function htmlToYDoc(html) {
|
|
41
|
+
assertDocumentContentResourceLimits({ contentHtml: html });
|
|
42
|
+
if (!html.trim()) return new Y.Doc();
|
|
43
|
+
const extensions = getDocumentEditorExtensions();
|
|
44
|
+
const { generateJSON } = getTiptapHtmlServer();
|
|
45
|
+
const json = generateJSON(html, extensions);
|
|
46
|
+
return TiptapTransformer.toYdoc(json, COLLAB_FRAGMENT_FIELD, extensions);
|
|
47
|
+
}
|
|
48
|
+
function materializeDocumentHtml(html) {
|
|
49
|
+
try {
|
|
50
|
+
const ydoc = htmlToYDoc(html);
|
|
51
|
+
const content = yDocToContent(ydoc);
|
|
52
|
+
if (!content) return null;
|
|
53
|
+
const result = {
|
|
54
|
+
yjsState: Buffer.from(Y.encodeStateAsUpdate(ydoc)),
|
|
55
|
+
html: content.html,
|
|
56
|
+
text: content.text
|
|
57
|
+
};
|
|
58
|
+
assertDocumentContentResourceLimits({
|
|
59
|
+
yjsState: result.yjsState,
|
|
60
|
+
contentHtml: result.html,
|
|
61
|
+
contentText: result.text
|
|
62
|
+
});
|
|
63
|
+
return result;
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (isCrudHttpError(error) && error.status === 413) throw error;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function materializeDocumentContentReplacement(existingState, html) {
|
|
70
|
+
try {
|
|
71
|
+
assertDocumentContentResourceLimits({ yjsState: existingState, contentHtml: html });
|
|
72
|
+
const replacement = htmlToYDoc(html);
|
|
73
|
+
const ydoc = new Y.Doc();
|
|
74
|
+
if (existingState && existingState.length > 0) {
|
|
75
|
+
Y.applyUpdate(ydoc, new Uint8Array(existingState));
|
|
76
|
+
}
|
|
77
|
+
const target = ydoc.getXmlFragment(COLLAB_FRAGMENT_FIELD);
|
|
78
|
+
const replacementNodes = replacement.getXmlFragment(COLLAB_FRAGMENT_FIELD).toArray().filter((node) => node instanceof Y.XmlElement || node instanceof Y.XmlText).map((node) => node.clone());
|
|
79
|
+
ydoc.transact(() => {
|
|
80
|
+
if (target.length > 0) target.delete(0, target.length);
|
|
81
|
+
if (replacementNodes.length > 0) target.insert(0, replacementNodes);
|
|
82
|
+
});
|
|
83
|
+
const content = yDocToContent(ydoc);
|
|
84
|
+
if (!content) return null;
|
|
85
|
+
const result = {
|
|
86
|
+
yjsState: Buffer.from(Y.encodeStateAsUpdate(ydoc)),
|
|
87
|
+
html: content.html,
|
|
88
|
+
text: content.text
|
|
89
|
+
};
|
|
90
|
+
assertDocumentContentResourceLimits({
|
|
91
|
+
yjsState: result.yjsState,
|
|
92
|
+
contentHtml: result.html,
|
|
93
|
+
contentText: result.text
|
|
94
|
+
});
|
|
95
|
+
return result;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (isCrudHttpError(error) && error.status === 413) throw error;
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
htmlToYDoc,
|
|
103
|
+
materializeDocumentContentReplacement,
|
|
104
|
+
materializeDocumentHtml,
|
|
105
|
+
yDocToContent
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=collabMaterializer.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/collabMaterializer.ts"],
|
|
4
|
+
"sourcesContent": ["import { createRequire } from 'node:module'\nimport type { JSONContent } from '@tiptap/core'\nimport { TiptapTransformer } from '@hocuspocus/transformer'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport * as Y from 'yjs'\nimport { deriveContentTextFromHtml } from './contentService'\nimport { COLLAB_FRAGMENT_FIELD, getDocumentEditorExtensions } from './editorConfig'\nimport { assertDocumentContentResourceLimits } from './resourceLimits'\n\ntype TiptapHtmlServer = typeof import('@tiptap/html/server')\n\nconst requireFromHere = createRequire(import.meta.url)\nlet tiptapHtmlServer: TiptapHtmlServer | null = null\n\nfunction getTiptapHtmlServer(): TiptapHtmlServer {\n if (!tiptapHtmlServer) {\n tiptapHtmlServer = requireFromHere('@tiptap/html/server') as TiptapHtmlServer\n }\n return tiptapHtmlServer\n}\n\nfunction hasRenderableContent(node: JSONContent): boolean {\n if (node.type === 'text') return Boolean(node.text)\n if (Array.isArray(node.content) && node.content.some(hasRenderableContent)) return true\n return Boolean(node.type && node.type !== 'doc' && node.type !== 'paragraph' && node.type !== 'text')\n}\n\nexport function yDocToContent(ydoc: Y.Doc): { html: string; text: string } | null {\n try {\n if (ydoc.getXmlFragment(COLLAB_FRAGMENT_FIELD).length === 0) {\n return { html: '', text: '' }\n }\n\n const json = TiptapTransformer.fromYdoc(ydoc, COLLAB_FRAGMENT_FIELD) as JSONContent | null\n if (!json || !hasRenderableContent(json)) {\n return { html: '', text: '' }\n }\n\n const { generateHTML } = getTiptapHtmlServer()\n const html = generateHTML(json, getDocumentEditorExtensions())\n const text = deriveContentTextFromHtml(html)\n assertDocumentContentResourceLimits({ contentHtml: html, contentText: text })\n return { html, text }\n } catch (error) {\n if (isCrudHttpError(error) && error.status === 413) throw error\n return null\n }\n}\n\nexport function htmlToYDoc(html: string): Y.Doc {\n assertDocumentContentResourceLimits({ contentHtml: html })\n if (!html.trim()) return new Y.Doc()\n\n const extensions = getDocumentEditorExtensions()\n const { generateJSON } = getTiptapHtmlServer()\n const json = generateJSON(html, extensions) as JSONContent\n return TiptapTransformer.toYdoc(json, COLLAB_FRAGMENT_FIELD, extensions)\n}\n\nexport type MaterializedDocumentHtml = {\n yjsState: Buffer\n html: string\n text: string\n}\n\n/**\n * Convert authored HTML through the same editor/Yjs pipeline used by persisted\n * document content. Callers that preview content before writing it must use the\n * returned HTML too, otherwise the preview can differ from the canonical markup\n * users receive after the document is created.\n */\nexport function materializeDocumentHtml(html: string): MaterializedDocumentHtml | null {\n try {\n const ydoc = htmlToYDoc(html)\n const content = yDocToContent(ydoc)\n if (!content) return null\n const result = {\n yjsState: Buffer.from(Y.encodeStateAsUpdate(ydoc)),\n html: content.html,\n text: content.text,\n }\n assertDocumentContentResourceLimits({\n yjsState: result.yjsState,\n contentHtml: result.html,\n contentText: result.text,\n })\n return result\n } catch (error) {\n if (isCrudHttpError(error) && error.status === 413) throw error\n return null\n }\n}\n\n/**\n * Replace REST-authored content as a Yjs update derived from the current CRDT\n * epoch. Keeping the old structs as deleted tombstones means a retained client\n * can merge the replacement without resurrecting or duplicating stale text.\n */\nexport function materializeDocumentContentReplacement(\n existingState: Buffer | Uint8Array | null | undefined,\n html: string,\n): MaterializedDocumentHtml | null {\n try {\n assertDocumentContentResourceLimits({ yjsState: existingState, contentHtml: html })\n const replacement = htmlToYDoc(html)\n const ydoc = new Y.Doc()\n if (existingState && existingState.length > 0) {\n Y.applyUpdate(ydoc, new Uint8Array(existingState))\n }\n\n const target = ydoc.getXmlFragment(COLLAB_FRAGMENT_FIELD)\n const replacementNodes = replacement\n .getXmlFragment(COLLAB_FRAGMENT_FIELD)\n .toArray()\n .filter((node): node is Y.XmlElement | Y.XmlText => (\n node instanceof Y.XmlElement || node instanceof Y.XmlText\n ))\n .map((node) => node.clone())\n ydoc.transact(() => {\n if (target.length > 0) target.delete(0, target.length)\n if (replacementNodes.length > 0) target.insert(0, replacementNodes)\n })\n const content = yDocToContent(ydoc)\n if (!content) return null\n const result = {\n yjsState: Buffer.from(Y.encodeStateAsUpdate(ydoc)),\n html: content.html,\n text: content.text,\n }\n assertDocumentContentResourceLimits({\n yjsState: result.yjsState,\n contentHtml: result.html,\n contentText: result.text,\n })\n return result\n } catch (error) {\n if (isCrudHttpError(error) && error.status === 413) throw error\n return null\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,qBAAqB;AAE9B,SAAS,yBAAyB;AAClC,SAAS,uBAAuB;AAChC,YAAY,OAAO;AACnB,SAAS,iCAAiC;AAC1C,SAAS,uBAAuB,mCAAmC;AACnE,SAAS,2CAA2C;AAIpD,MAAM,kBAAkB,cAAc,YAAY,GAAG;AACrD,IAAI,mBAA4C;AAEhD,SAAS,sBAAwC;AAC/C,MAAI,CAAC,kBAAkB;AACrB,uBAAmB,gBAAgB,qBAAqB;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,MAA4B;AACxD,MAAI,KAAK,SAAS,OAAQ,QAAO,QAAQ,KAAK,IAAI;AAClD,MAAI,MAAM,QAAQ,KAAK,OAAO,KAAK,KAAK,QAAQ,KAAK,oBAAoB,EAAG,QAAO;AACnF,SAAO,QAAQ,KAAK,QAAQ,KAAK,SAAS,SAAS,KAAK,SAAS,eAAe,KAAK,SAAS,MAAM;AACtG;AAEO,SAAS,cAAc,MAAoD;AAChF,MAAI;AACF,QAAI,KAAK,eAAe,qBAAqB,EAAE,WAAW,GAAG;AAC3D,aAAO,EAAE,MAAM,IAAI,MAAM,GAAG;AAAA,IAC9B;AAEA,UAAM,OAAO,kBAAkB,SAAS,MAAM,qBAAqB;AACnE,QAAI,CAAC,QAAQ,CAAC,qBAAqB,IAAI,GAAG;AACxC,aAAO,EAAE,MAAM,IAAI,MAAM,GAAG;AAAA,IAC9B;AAEA,UAAM,EAAE,aAAa,IAAI,oBAAoB;AAC7C,UAAM,OAAO,aAAa,MAAM,4BAA4B,CAAC;AAC7D,UAAM,OAAO,0BAA0B,IAAI;AAC3C,wCAAoC,EAAE,aAAa,MAAM,aAAa,KAAK,CAAC;AAC5E,WAAO,EAAE,MAAM,KAAK;AAAA,EACtB,SAAS,OAAO;AACd,QAAI,gBAAgB,KAAK,KAAK,MAAM,WAAW,IAAK,OAAM;AAC1D,WAAO;AAAA,EACT;AACF;AAEO,SAAS,WAAW,MAAqB;AAC9C,sCAAoC,EAAE,aAAa,KAAK,CAAC;AACzD,MAAI,CAAC,KAAK,KAAK,EAAG,QAAO,IAAI,EAAE,IAAI;AAEnC,QAAM,aAAa,4BAA4B;AAC/C,QAAM,EAAE,aAAa,IAAI,oBAAoB;AAC7C,QAAM,OAAO,aAAa,MAAM,UAAU;AAC1C,SAAO,kBAAkB,OAAO,MAAM,uBAAuB,UAAU;AACzE;AAcO,SAAS,wBAAwB,MAA+C;AACrF,MAAI;AACF,UAAM,OAAO,WAAW,IAAI;AAC5B,UAAM,UAAU,cAAc,IAAI;AAClC,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,SAAS;AAAA,MACb,UAAU,OAAO,KAAK,EAAE,oBAAoB,IAAI,CAAC;AAAA,MACjD,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,IAChB;AACA,wCAAoC;AAAA,MAClC,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,IACtB,CAAC;AACD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,gBAAgB,KAAK,KAAK,MAAM,WAAW,IAAK,OAAM;AAC1D,WAAO;AAAA,EACT;AACF;AAOO,SAAS,sCACd,eACA,MACiC;AACjC,MAAI;AACF,wCAAoC,EAAE,UAAU,eAAe,aAAa,KAAK,CAAC;AAClF,UAAM,cAAc,WAAW,IAAI;AACnC,UAAM,OAAO,IAAI,EAAE,IAAI;AACvB,QAAI,iBAAiB,cAAc,SAAS,GAAG;AAC7C,QAAE,YAAY,MAAM,IAAI,WAAW,aAAa,CAAC;AAAA,IACnD;AAEA,UAAM,SAAS,KAAK,eAAe,qBAAqB;AACxD,UAAM,mBAAmB,YACtB,eAAe,qBAAqB,EACpC,QAAQ,EACR,OAAO,CAAC,SACP,gBAAgB,EAAE,cAAc,gBAAgB,EAAE,OACnD,EACA,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC;AAC7B,SAAK,SAAS,MAAM;AAClB,UAAI,OAAO,SAAS,EAAG,QAAO,OAAO,GAAG,OAAO,MAAM;AACrD,UAAI,iBAAiB,SAAS,EAAG,QAAO,OAAO,GAAG,gBAAgB;AAAA,IACpE,CAAC;AACD,UAAM,UAAU,cAAc,IAAI;AAClC,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,SAAS;AAAA,MACb,UAAU,OAAO,KAAK,EAAE,oBAAoB,IAAI,CAAC;AAAA,MACjD,MAAM,QAAQ;AAAA,MACd,MAAM,QAAQ;AAAA,IAChB;AACA,wCAAoC;AAAA,MAClC,UAAU,OAAO;AAAA,MACjB,aAAa,OAAO;AAAA,MACpB,aAAa,OAAO;AAAA,IACtB,CAAC;AACD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,gBAAgB,KAAK,KAAK,MAAM,WAAW,IAAK,OAAM;AAC1D,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { signJwt, verifyJwt } from "@open-mercato/shared/lib/auth/jwt";
|
|
2
|
+
const COLLAB_TOKEN_AUDIENCE = "documents-collab";
|
|
3
|
+
const COLLAB_TOKEN_V2_AUDIENCE = "documents-collab-v2";
|
|
4
|
+
const COLLAB_TOKEN_TTL_SECONDS = 60;
|
|
5
|
+
const COLLAB_TOKEN_CLOCK_SKEW_SECONDS = 5;
|
|
6
|
+
const COLLAB_TOKEN_V2_MIN_SECRET_BYTES = 32;
|
|
7
|
+
function isNonEmptyString(value) {
|
|
8
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
9
|
+
}
|
|
10
|
+
function isDocumentTier(value) {
|
|
11
|
+
return value === "owner" || value === "editor" || value === "commenter" || value === "viewer";
|
|
12
|
+
}
|
|
13
|
+
function readV2Secret() {
|
|
14
|
+
const secret = process.env.DOCUMENTS_COLLAB_JWT_SECRET_V2?.trim();
|
|
15
|
+
if (!secret || new TextEncoder().encode(secret).byteLength < COLLAB_TOKEN_V2_MIN_SECRET_BYTES) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const explicitV1Secret = process.env.DOCUMENTS_COLLAB_JWT_SECRET?.trim();
|
|
19
|
+
return explicitV1Secret === secret ? null : secret;
|
|
20
|
+
}
|
|
21
|
+
function isCollabTokenV2Ready() {
|
|
22
|
+
return readV2Secret() !== null;
|
|
23
|
+
}
|
|
24
|
+
function requireV2Secret() {
|
|
25
|
+
const secret = readV2Secret();
|
|
26
|
+
if (!secret) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`[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`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return secret;
|
|
32
|
+
}
|
|
33
|
+
function readCommonClaims(claims) {
|
|
34
|
+
const { userId, tenantId, organizationId, documentId, tier } = claims;
|
|
35
|
+
if (!isNonEmptyString(userId) || !isNonEmptyString(tenantId) || !isNonEmptyString(organizationId) || !isNonEmptyString(documentId) || !isDocumentTier(tier)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
return { userId, tenantId, organizationId, documentId, tier };
|
|
39
|
+
}
|
|
40
|
+
function mintCollabToken(claims) {
|
|
41
|
+
return signJwt(
|
|
42
|
+
{ ...claims, sub: claims.userId },
|
|
43
|
+
{
|
|
44
|
+
audience: COLLAB_TOKEN_AUDIENCE,
|
|
45
|
+
secret: process.env.DOCUMENTS_COLLAB_JWT_SECRET,
|
|
46
|
+
expiresInSec: COLLAB_TOKEN_TTL_SECONDS
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
function resolveLegacyCollabTokenVerifier(env = process.env) {
|
|
51
|
+
const secret = env.DOCUMENTS_COLLAB_JWT_SECRET?.trim();
|
|
52
|
+
if (!secret || new TextEncoder().encode(secret).byteLength < COLLAB_TOKEN_V2_MIN_SECRET_BYTES) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return verifyCollabToken;
|
|
56
|
+
}
|
|
57
|
+
function verifyCollabToken(token) {
|
|
58
|
+
let payload;
|
|
59
|
+
try {
|
|
60
|
+
payload = verifyJwt(token, {
|
|
61
|
+
audience: COLLAB_TOKEN_AUDIENCE,
|
|
62
|
+
secret: process.env.DOCUMENTS_COLLAB_JWT_SECRET
|
|
63
|
+
});
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (!payload || typeof payload !== "object") return null;
|
|
68
|
+
return readCommonClaims(payload);
|
|
69
|
+
}
|
|
70
|
+
function mintCollabTokenV2(claims) {
|
|
71
|
+
return signJwt(
|
|
72
|
+
{ ...claims, sub: claims.userId },
|
|
73
|
+
{
|
|
74
|
+
audience: COLLAB_TOKEN_V2_AUDIENCE,
|
|
75
|
+
secret: requireV2Secret(),
|
|
76
|
+
expiresInSec: COLLAB_TOKEN_TTL_SECONDS
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
function verifyCollabTokenV2(token) {
|
|
81
|
+
const secret = readV2Secret();
|
|
82
|
+
if (!secret) return null;
|
|
83
|
+
let payload;
|
|
84
|
+
try {
|
|
85
|
+
payload = verifyJwt(token, {
|
|
86
|
+
audience: COLLAB_TOKEN_V2_AUDIENCE,
|
|
87
|
+
secret
|
|
88
|
+
});
|
|
89
|
+
} catch {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
if (!payload || typeof payload !== "object") return null;
|
|
93
|
+
const claims = payload;
|
|
94
|
+
const common = readCommonClaims(claims);
|
|
95
|
+
const { exp, iat, readOnly, tokenVersion } = claims;
|
|
96
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
97
|
+
if (!common || tokenVersion !== 2 || typeof readOnly !== "boolean" || typeof exp !== "number" || !Number.isInteger(exp) || typeof iat !== "number" || !Number.isInteger(iat) || exp <= now || exp <= iat || exp - iat > COLLAB_TOKEN_TTL_SECONDS || iat > now + COLLAB_TOKEN_CLOCK_SKEW_SECONDS || exp > now + COLLAB_TOKEN_TTL_SECONDS + COLLAB_TOKEN_CLOCK_SKEW_SECONDS) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
...common,
|
|
102
|
+
tokenVersion,
|
|
103
|
+
readOnly,
|
|
104
|
+
exp
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
COLLAB_TOKEN_AUDIENCE,
|
|
109
|
+
COLLAB_TOKEN_CLOCK_SKEW_SECONDS,
|
|
110
|
+
COLLAB_TOKEN_TTL_SECONDS,
|
|
111
|
+
COLLAB_TOKEN_V2_AUDIENCE,
|
|
112
|
+
COLLAB_TOKEN_V2_MIN_SECRET_BYTES,
|
|
113
|
+
isCollabTokenV2Ready,
|
|
114
|
+
mintCollabToken,
|
|
115
|
+
mintCollabTokenV2,
|
|
116
|
+
resolveLegacyCollabTokenVerifier,
|
|
117
|
+
verifyCollabToken,
|
|
118
|
+
verifyCollabTokenV2
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=collabToken.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/collabToken.ts"],
|
|
4
|
+
"sourcesContent": ["import { signJwt, verifyJwt } from '@open-mercato/shared/lib/auth/jwt'\nimport type { DocumentTier } from '../lib/permissions'\n\nexport const COLLAB_TOKEN_AUDIENCE = 'documents-collab'\nexport const COLLAB_TOKEN_V2_AUDIENCE = 'documents-collab-v2'\nexport const COLLAB_TOKEN_TTL_SECONDS = 60\nexport const COLLAB_TOKEN_CLOCK_SKEW_SECONDS = 5\nexport const COLLAB_TOKEN_V2_MIN_SECRET_BYTES = 32\n\nexport type CollabTokenClaims = {\n userId: string\n tenantId: string\n organizationId: string\n documentId: string\n tier: DocumentTier\n}\n\nexport type CollabTokenV2MintInput = CollabTokenClaims & {\n tokenVersion: 2\n readOnly: boolean\n}\n\nexport type VerifiedCollabTokenV2Claims = CollabTokenV2MintInput & {\n exp: number\n}\n\nfunction isNonEmptyString(value: unknown): value is string {\n return typeof value === 'string' && value.trim().length > 0\n}\n\nfunction isDocumentTier(value: unknown): value is DocumentTier {\n return value === 'owner' || value === 'editor' || value === 'commenter' || value === 'viewer'\n}\n\nfunction readV2Secret(): string | null {\n const secret = process.env.DOCUMENTS_COLLAB_JWT_SECRET_V2?.trim()\n if (!secret || new TextEncoder().encode(secret).byteLength < COLLAB_TOKEN_V2_MIN_SECRET_BYTES) {\n return null\n }\n const explicitV1Secret = process.env.DOCUMENTS_COLLAB_JWT_SECRET?.trim()\n return explicitV1Secret === secret ? null : secret\n}\n\nexport function isCollabTokenV2Ready(): boolean {\n return readV2Secret() !== null\n}\n\nfunction requireV2Secret(): string {\n const secret = readV2Secret()\n if (!secret) {\n throw new Error(\n `[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`,\n )\n }\n return secret\n}\n\nfunction readCommonClaims(claims: Record<string, unknown>): CollabTokenClaims | null {\n const { userId, tenantId, organizationId, documentId, tier } = claims\n if (\n !isNonEmptyString(userId)\n || !isNonEmptyString(tenantId)\n || !isNonEmptyString(organizationId)\n || !isNonEmptyString(documentId)\n || !isDocumentTier(tier)\n ) {\n return null\n }\n\n return { userId, tenantId, organizationId, documentId, tier }\n}\n\nexport function mintCollabToken(claims: CollabTokenClaims): string {\n return signJwt(\n { ...claims, sub: claims.userId },\n {\n audience: COLLAB_TOKEN_AUDIENCE,\n secret: process.env.DOCUMENTS_COLLAB_JWT_SECRET,\n expiresInSec: COLLAB_TOKEN_TTL_SECONDS,\n },\n )\n}\n\n/**\n * Legacy v1 acceptance is a rollout bridge only. Nothing mints v1 tokens\n * anymore, so the sidecar accepts them solely while a dedicated\n * DOCUMENTS_COLLAB_JWT_SECRET is explicitly configured and at least as strong\n * as the v2 minimum. Default deployments (derived JWT_SECRET fallback) accept\n * v2 tokens exclusively.\n */\nexport function resolveLegacyCollabTokenVerifier(\n env: Record<string, string | undefined> = process.env,\n): ((token: string) => CollabTokenClaims | null) | null {\n const secret = env.DOCUMENTS_COLLAB_JWT_SECRET?.trim()\n if (!secret || new TextEncoder().encode(secret).byteLength < COLLAB_TOKEN_V2_MIN_SECRET_BYTES) {\n return null\n }\n return verifyCollabToken\n}\n\nexport function verifyCollabToken(token: string): CollabTokenClaims | null {\n let payload: unknown\n try {\n payload = verifyJwt(token, {\n audience: COLLAB_TOKEN_AUDIENCE,\n secret: process.env.DOCUMENTS_COLLAB_JWT_SECRET,\n })\n } catch {\n return null\n }\n\n if (!payload || typeof payload !== 'object') return null\n\n return readCommonClaims(payload as Record<string, unknown>)\n}\n\nexport function mintCollabTokenV2(claims: CollabTokenV2MintInput): string {\n return signJwt(\n { ...claims, sub: claims.userId },\n {\n audience: COLLAB_TOKEN_V2_AUDIENCE,\n secret: requireV2Secret(),\n expiresInSec: COLLAB_TOKEN_TTL_SECONDS,\n },\n )\n}\n\nexport function verifyCollabTokenV2(token: string): VerifiedCollabTokenV2Claims | null {\n const secret = readV2Secret()\n if (!secret) return null\n\n let payload: unknown\n try {\n payload = verifyJwt(token, {\n audience: COLLAB_TOKEN_V2_AUDIENCE,\n secret,\n })\n } catch {\n return null\n }\n if (!payload || typeof payload !== 'object') return null\n\n const claims = payload as Record<string, unknown>\n const common = readCommonClaims(claims)\n const { exp, iat, readOnly, tokenVersion } = claims\n const now = Math.floor(Date.now() / 1000)\n if (\n !common\n || tokenVersion !== 2\n || typeof readOnly !== 'boolean'\n || typeof exp !== 'number'\n || !Number.isInteger(exp)\n || typeof iat !== 'number'\n || !Number.isInteger(iat)\n || exp <= now\n || exp <= iat\n || exp - iat > COLLAB_TOKEN_TTL_SECONDS\n || iat > now + COLLAB_TOKEN_CLOCK_SKEW_SECONDS\n || exp > now + COLLAB_TOKEN_TTL_SECONDS + COLLAB_TOKEN_CLOCK_SKEW_SECONDS\n ) {\n return null\n }\n\n return {\n ...common,\n tokenVersion,\n readOnly,\n exp,\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { sanitizeDocumentsDisplayLabel } from "./displayLabels.js";
|
|
2
|
+
const COLLABORATION_COLOR_FALLBACK = "#64748b";
|
|
3
|
+
const COLLABORATION_COLOR_PATTERN = /^#[0-9a-f]{6}$/i;
|
|
4
|
+
const UNSAFE_AWARENESS_NAME_PATTERN = /[\u0000-\u001f\u007f-\u009f\u061c\u200b-\u200f\u202a-\u202e\u2060-\u2069\ufeff]/u;
|
|
5
|
+
const MAX_AWARENESS_NAME_LENGTH = 120;
|
|
6
|
+
function isEncryptedAwarenessName(value) {
|
|
7
|
+
const parts = value.split(":");
|
|
8
|
+
return parts.length === 4 && parts[3] === "v1";
|
|
9
|
+
}
|
|
10
|
+
function hashString(value) {
|
|
11
|
+
let hash = 2166136261;
|
|
12
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
13
|
+
hash ^= value.charCodeAt(index);
|
|
14
|
+
hash = Math.imul(hash, 16777619);
|
|
15
|
+
}
|
|
16
|
+
return hash >>> 0;
|
|
17
|
+
}
|
|
18
|
+
function channelToHex(value) {
|
|
19
|
+
return Math.round(value).toString(16).padStart(2, "0");
|
|
20
|
+
}
|
|
21
|
+
function hslToHex(hue, saturationPercent, lightnessPercent) {
|
|
22
|
+
const saturation = saturationPercent / 100;
|
|
23
|
+
const lightness = lightnessPercent / 100;
|
|
24
|
+
const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;
|
|
25
|
+
const intermediate = chroma * (1 - Math.abs(hue / 60 % 2 - 1));
|
|
26
|
+
const match = lightness - chroma / 2;
|
|
27
|
+
const [red, green, blue] = hue < 60 ? [chroma, intermediate, 0] : hue < 120 ? [intermediate, chroma, 0] : hue < 180 ? [0, chroma, intermediate] : hue < 240 ? [0, intermediate, chroma] : hue < 300 ? [intermediate, 0, chroma] : [chroma, 0, intermediate];
|
|
28
|
+
return `#${channelToHex((red + match) * 255)}${channelToHex((green + match) * 255)}${channelToHex((blue + match) * 255)}`;
|
|
29
|
+
}
|
|
30
|
+
function normalizeCollaborationColor(value) {
|
|
31
|
+
if (typeof value !== "string" || !COLLABORATION_COLOR_PATTERN.test(value)) {
|
|
32
|
+
return COLLABORATION_COLOR_FALLBACK;
|
|
33
|
+
}
|
|
34
|
+
return value.toLowerCase();
|
|
35
|
+
}
|
|
36
|
+
function resolveCollaborationUserColor(userId) {
|
|
37
|
+
return hslToHex(hashString(userId) % 360, 64, 42);
|
|
38
|
+
}
|
|
39
|
+
function sanitizeCollaborationAwarenessName(value) {
|
|
40
|
+
const label = sanitizeDocumentsDisplayLabel(value);
|
|
41
|
+
if (!label || label.length > MAX_AWARENESS_NAME_LENGTH || UNSAFE_AWARENESS_NAME_PATTERN.test(label) || isEncryptedAwarenessName(label)) {
|
|
42
|
+
return "";
|
|
43
|
+
}
|
|
44
|
+
return label;
|
|
45
|
+
}
|
|
46
|
+
function firstSafeCollaborationAwarenessName(...values) {
|
|
47
|
+
for (const value of values) {
|
|
48
|
+
const label = sanitizeCollaborationAwarenessName(value);
|
|
49
|
+
if (label) return label;
|
|
50
|
+
}
|
|
51
|
+
return "";
|
|
52
|
+
}
|
|
53
|
+
function createCanonicalCollaborationAwarenessUser(userId, name) {
|
|
54
|
+
return {
|
|
55
|
+
id: userId,
|
|
56
|
+
name: sanitizeCollaborationAwarenessName(name),
|
|
57
|
+
color: resolveCollaborationUserColor(userId)
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export {
|
|
61
|
+
COLLABORATION_COLOR_FALLBACK,
|
|
62
|
+
createCanonicalCollaborationAwarenessUser,
|
|
63
|
+
firstSafeCollaborationAwarenessName,
|
|
64
|
+
normalizeCollaborationColor,
|
|
65
|
+
resolveCollaborationUserColor,
|
|
66
|
+
sanitizeCollaborationAwarenessName
|
|
67
|
+
};
|
|
68
|
+
//# sourceMappingURL=collaborationAwareness.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/collaborationAwareness.ts"],
|
|
4
|
+
"sourcesContent": ["import { sanitizeDocumentsDisplayLabel } from './displayLabels'\n\nexport const COLLABORATION_COLOR_FALLBACK = '#64748b'\n\nconst COLLABORATION_COLOR_PATTERN = /^#[0-9a-f]{6}$/i\nconst UNSAFE_AWARENESS_NAME_PATTERN =\n /[\\u0000-\\u001f\\u007f-\\u009f\\u061c\\u200b-\\u200f\\u202a-\\u202e\\u2060-\\u2069\\ufeff]/u\nconst MAX_AWARENESS_NAME_LENGTH = 120\n\nfunction isEncryptedAwarenessName(value: string): boolean {\n const parts = value.split(':')\n return parts.length === 4 && parts[3] === 'v1'\n}\n\nfunction hashString(value: string): number {\n let hash = 2166136261\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index)\n hash = Math.imul(hash, 16777619)\n }\n return hash >>> 0\n}\n\nfunction channelToHex(value: number): string {\n return Math.round(value).toString(16).padStart(2, '0')\n}\n\nfunction hslToHex(hue: number, saturationPercent: number, lightnessPercent: number): string {\n const saturation = saturationPercent / 100\n const lightness = lightnessPercent / 100\n const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation\n const intermediate = chroma * (1 - Math.abs(((hue / 60) % 2) - 1))\n const match = lightness - chroma / 2\n const [red, green, blue] =\n hue < 60 ? [chroma, intermediate, 0]\n : hue < 120 ? [intermediate, chroma, 0]\n : hue < 180 ? [0, chroma, intermediate]\n : hue < 240 ? [0, intermediate, chroma]\n : hue < 300 ? [intermediate, 0, chroma]\n : [chroma, 0, intermediate]\n return `#${channelToHex((red + match) * 255)}${channelToHex((green + match) * 255)}${channelToHex((blue + match) * 255)}`\n}\n\n/**\n * Awareness colors are interpolated into inline styles by TipTap. Accept only\n * the single canonical representation emitted by the server, never general\n * CSS color syntax.\n */\nexport function normalizeCollaborationColor(value: unknown): string {\n if (typeof value !== 'string' || !COLLABORATION_COLOR_PATTERN.test(value)) {\n return COLLABORATION_COLOR_FALLBACK\n }\n return value.toLowerCase()\n}\n\nexport function resolveCollaborationUserColor(userId: string): string {\n return hslToHex(hashString(userId) % 360, 64, 42)\n}\n\n/**\n * Presence names come from an authenticated profile, but still cross the Yjs\n * awareness boundary. Reject control, directionality, zero-width and UUID\n * content and encryption envelopes so a collaborator cannot visually\n * impersonate another identity or leak internal data through a caret label.\n */\nexport function sanitizeCollaborationAwarenessName(value: unknown): string {\n const label = sanitizeDocumentsDisplayLabel(value)\n if (\n !label\n || label.length > MAX_AWARENESS_NAME_LENGTH\n || UNSAFE_AWARENESS_NAME_PATTERN.test(label)\n || isEncryptedAwarenessName(label)\n ) {\n return ''\n }\n return label\n}\n\nexport function firstSafeCollaborationAwarenessName(...values: unknown[]): string {\n for (const value of values) {\n const label = sanitizeCollaborationAwarenessName(value)\n if (label) return label\n }\n return ''\n}\n\nexport type CanonicalCollaborationAwarenessUser = {\n id: string\n name: string\n color: string\n}\n\nexport function createCanonicalCollaborationAwarenessUser(\n userId: string,\n name: unknown,\n): CanonicalCollaborationAwarenessUser {\n return {\n id: userId,\n name: sanitizeCollaborationAwarenessName(name),\n color: resolveCollaborationUserColor(userId),\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,qCAAqC;AAEvC,MAAM,+BAA+B;AAE5C,MAAM,8BAA8B;AACpC,MAAM,gCACJ;AACF,MAAM,4BAA4B;AAElC,SAAS,yBAAyB,OAAwB;AACxD,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,SAAO,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM;AAC5C;AAEA,SAAS,WAAW,OAAuB;AACzC,MAAI,OAAO;AACX,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,SAAS,GAAG;AACpD,YAAQ,MAAM,WAAW,KAAK;AAC9B,WAAO,KAAK,KAAK,MAAM,QAAQ;AAAA,EACjC;AACA,SAAO,SAAS;AAClB;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,KAAK,MAAM,KAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AACvD;AAEA,SAAS,SAAS,KAAa,mBAA2B,kBAAkC;AAC1F,QAAM,aAAa,oBAAoB;AACvC,QAAM,YAAY,mBAAmB;AACrC,QAAM,UAAU,IAAI,KAAK,IAAI,IAAI,YAAY,CAAC,KAAK;AACnD,QAAM,eAAe,UAAU,IAAI,KAAK,IAAM,MAAM,KAAM,IAAK,CAAC;AAChE,QAAM,QAAQ,YAAY,SAAS;AACnC,QAAM,CAAC,KAAK,OAAO,IAAI,IACrB,MAAM,KAAK,CAAC,QAAQ,cAAc,CAAC,IAC/B,MAAM,MAAM,CAAC,cAAc,QAAQ,CAAC,IAClC,MAAM,MAAM,CAAC,GAAG,QAAQ,YAAY,IAClC,MAAM,MAAM,CAAC,GAAG,cAAc,MAAM,IAClC,MAAM,MAAM,CAAC,cAAc,GAAG,MAAM,IAClC,CAAC,QAAQ,GAAG,YAAY;AACtC,SAAO,IAAI,cAAc,MAAM,SAAS,GAAG,CAAC,GAAG,cAAc,QAAQ,SAAS,GAAG,CAAC,GAAG,cAAc,OAAO,SAAS,GAAG,CAAC;AACzH;AAOO,SAAS,4BAA4B,OAAwB;AAClE,MAAI,OAAO,UAAU,YAAY,CAAC,4BAA4B,KAAK,KAAK,GAAG;AACzE,WAAO;AAAA,EACT;AACA,SAAO,MAAM,YAAY;AAC3B;AAEO,SAAS,8BAA8B,QAAwB;AACpE,SAAO,SAAS,WAAW,MAAM,IAAI,KAAK,IAAI,EAAE;AAClD;AAQO,SAAS,mCAAmC,OAAwB;AACzE,QAAM,QAAQ,8BAA8B,KAAK;AACjD,MACE,CAAC,SACE,MAAM,SAAS,6BACf,8BAA8B,KAAK,KAAK,KACxC,yBAAyB,KAAK,GACjC;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,uCAAuC,QAA2B;AAChF,aAAW,SAAS,QAAQ;AAC1B,UAAM,QAAQ,mCAAmC,KAAK;AACtD,QAAI,MAAO,QAAO;AAAA,EACpB;AACA,SAAO;AACT;AAQO,SAAS,0CACd,QACA,MACqC;AACrC,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,MAAM,mCAAmC,IAAI;AAAA,IAC7C,OAAO,8BAA8B,MAAM;AAAA,EAC7C;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
documentCommentAnchorWriteSchema
|
|
3
|
+
} from "../data/validators.js";
|
|
4
|
+
function normalizeDocumentCommentAnchor(value) {
|
|
5
|
+
const parsed = documentCommentAnchorWriteSchema.safeParse(value);
|
|
6
|
+
return parsed.success ? parsed.data : { kind: "legacy-unknown" };
|
|
7
|
+
}
|
|
8
|
+
function isChangedDocumentCommentAnchor(value) {
|
|
9
|
+
return "kind" in value && value.kind === "legacy-unknown";
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
isChangedDocumentCommentAnchor,
|
|
13
|
+
normalizeDocumentCommentAnchor
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=commentAnchors.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/commentAnchors.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n documentCommentAnchorWriteSchema,\n type DocumentCommentAnchor,\n} from '../data/validators'\n\nexport type NormalizedDocumentCommentAnchor =\n | DocumentCommentAnchor\n | { kind: 'legacy-unknown' }\n\nexport function normalizeDocumentCommentAnchor(value: unknown): NormalizedDocumentCommentAnchor {\n const parsed = documentCommentAnchorWriteSchema.safeParse(value)\n return parsed.success ? parsed.data : { kind: 'legacy-unknown' }\n}\n\nexport function isChangedDocumentCommentAnchor(\n value: NormalizedDocumentCommentAnchor,\n): value is { kind: 'legacy-unknown' } {\n return 'kind' in value && value.kind === 'legacy-unknown'\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,OAEK;AAMA,SAAS,+BAA+B,OAAiD;AAC9F,QAAM,SAAS,iCAAiC,UAAU,KAAK;AAC/D,SAAO,OAAO,UAAU,OAAO,OAAO,EAAE,MAAM,iBAAiB;AACjE;AAEO,SAAS,+BACd,OACqC;AACrC,SAAO,UAAU,SAAS,MAAM,SAAS;AAC3C;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
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
|
+
};
|
|
14
|
+
const DOCUMENTS_MAX_FOLDER_DEPTH = 64;
|
|
15
|
+
const DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION = 2e3;
|
|
16
|
+
const DOCUMENTS_MAX_LISTED_FOLDERS = 5e3;
|
|
17
|
+
const DOCUMENTS_MAX_LISTED_SHARES = 500;
|
|
18
|
+
export {
|
|
19
|
+
DOCUMENTS_ENTITY_IDS,
|
|
20
|
+
DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION,
|
|
21
|
+
DOCUMENTS_MAX_FOLDER_DEPTH,
|
|
22
|
+
DOCUMENTS_MAX_LISTED_FOLDERS,
|
|
23
|
+
DOCUMENTS_MAX_LISTED_SHARES
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/documents/lib/constants.ts"],
|
|
4
|
+
"sourcesContent": ["export const DOCUMENTS_ENTITY_IDS = {\n document: 'documents:document',\n documentContent: 'documents:document_content',\n documentFolder: 'documents:document_folder',\n documentShare: 'documents:document_share',\n documentComment: 'documents:document_comment',\n documentFavorite: 'documents:document_favorite',\n documentWatcher: 'documents:document_watcher',\n documentVersion: 'documents:document_version',\n documentAttachment: 'documents:document_attachment',\n documentTemplate: 'documents:document_template',\n documentEntityLink: 'documents:document_entity_link',\n} as const\n\n/** Maximum number of folder nodes from a root through its deepest descendant. */\nexport const DOCUMENTS_MAX_FOLDER_DEPTH = 64\n\n/**\n * Maximum active folders one organization may hold. A navigable folder tree\n * stays in the tens or low hundreds, so this only stops runaway automated\n * creation while bounding the manager-override listing that decrypts every\n * folder in scope.\n */\nexport const DOCUMENTS_MAX_FOLDERS_PER_ORGANIZATION = 2_000\n\n/**\n * Upper bound for one manager-override folder listing. Kept far above the\n * creation cap so an organization that predates that cap still lists a\n * coherent tree it can prune, instead of losing folder navigation entirely.\n */\nexport const DOCUMENTS_MAX_LISTED_FOLDERS = 5_000\n\n/**\n * Upper bound for one document's share listing. Explicit sharing stays in the\n * tens, and the mention path can only add one share per distinct mentioned\n * user, so this sits at the comment cap and keeps the listing (plus its\n * principal-label fan-out) bounded the way the comment and version lists are.\n */\nexport const DOCUMENTS_MAX_LISTED_SHARES = 500\n"],
|
|
5
|
+
"mappings": "AAAO,MAAM,uBAAuB;AAAA,EAClC,UAAU;AAAA,EACV,iBAAiB;AAAA,EACjB,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,kBAAkB;AAAA,EAClB,oBAAoB;AACtB;AAGO,MAAM,6BAA6B;AAQnC,MAAM,yCAAyC;AAO/C,MAAM,+BAA+B;AAQrC,MAAM,8BAA8B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|