@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,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/documents/api/%5Bid%5D/export/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { existsSync } from 'node:fs'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { sanitizeRichTextHtml } from '@open-mercato/shared/lib/html/sanitizeRichText'\nimport { assertTier } from '../../../lib/permissions'\nimport { loadDocumentContent } from '../../../lib/contentService'\nimport {\n isDocxRenderFailedError,\n isDocxRenderOutputTooLargeError,\n isDocxRenderOverloadedError,\n isDocxRenderTimeoutError,\n renderDocxWithCapacity,\n} from '../../../lib/docxRenderer'\nimport {\n isPdfRenderOutputTooLargeError,\n isPdfRenderOverloadedError,\n isPdfRenderTimeoutError,\n renderPdfWithChromium,\n} from '../../../lib/pdfRenderer'\nimport { buildDocumentPdfHtml } from '../../../lib/pdfHtml'\nimport {\n assertDocumentContentResourceLimits,\n DOCUMENTS_MAX_CONTENT_HTML_BYTES,\n maxBase64EncodedLength,\n} from '../../../lib/resourceLimits'\nimport { DOCUMENTS_JSON_BODY_LIMITS } from '../../../lib/requestBody'\nimport {\n handleDocumentsRouteError,\n loadScopedDocument,\n readBody,\n resolveDocumentsContext,\n routeErrorSchema,\n withDocumentsContextErrors,\n} from '../../_shared'\n\ntype RouteContext = {\n params: Promise<{ id: string }> | { id: string }\n}\n\ntype ExportFormat = 'docx' | 'pdf'\n\nexport type PdfRequestDescriptor = {\n url: string\n resourceType: string\n isNavigationRequest: boolean\n}\n\nconst exportQuerySchema = z.object({\n format: z.enum(['docx', 'pdf']).optional(),\n})\nconst docxSnapshotSchema = z.object({\n contentHtml: z.string().max(DOCUMENTS_MAX_CONTENT_HTML_BYTES),\n pageBreakMarker: z.string().regex(/^OM_DOCX_PAGE_BREAK_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i),\n})\n\nconst fileResponseSchema = z.string().describe('Binary .docx or PDF file attachment')\n\nconst COMMON_CHROMIUM_PATHS = [\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/Applications/Chromium.app/Contents/MacOS/Chromium',\n '/usr/bin/google-chrome',\n '/usr/bin/chromium',\n '/usr/bin/chromium-browser',\n]\n\nexport const DOCX_MAX_EMBEDDED_IMAGE_BYTES = 1024 * 1024\nexport const PDF_MAX_EMBEDDED_IMAGE_BYTES = 1024 * 1024\nexport const MAX_EMBEDDED_RASTER_DIMENSION = 4096\nexport const MAX_EMBEDDED_RASTER_PIXELS = 16 * 1024 * 1024\nconst DATA_IMAGE_PATTERN = /^data:image\\/(png|jpeg);base64,([a-z0-9+/]+={0,2})$/i\nconst IMAGE_TAG_PATTERN = /<img\\b[^>]*>/gi\nconst ENTITY_REF_SPAN_PATTERN = /<span\\b(?=[^>]*\\bdata-entity-ref(?:\\s|=|>))[^>]*>([\\s\\S]*?)<\\/span>/gi\nconst HIGHLIGHT_OPEN_PATTERN = /<mark\\b([^>]*)>/gi\nconst HIGHLIGHT_CLOSE_PATTERN = /<\\/mark>/gi\nconst LEADING_TABLE_HEADER_ROW_PATTERN = /(<table\\b[^>]*>)(\\s*)<tbody>(\\s*)(<tr>(?:(?:\\s*)<th\\b[^>]*>[\\s\\S]*?<\\/th>)+\\s*<\\/tr>)([\\s\\S]*?)<\\/tbody>/gi\nconst IMAGE_SOURCE_PATTERN = /\\bsrc\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s\"'=<>`]+))/gi\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['documents.view'] },\n POST: { requireAuth: true, requireFeatures: ['documents.view'] },\n}\n\nasync function resolveId(context: RouteContext): Promise<string> {\n const params = await context.params\n return params.id\n}\n\nfunction resolveExportFormat(value: string | null): ExportFormat | null {\n if (value === null || value === 'docx') return 'docx'\n if (value === 'pdf') return 'pdf'\n return null\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n}\n\nfunction buildSafeFilename(title: string): string {\n return title.replace(/[^a-z0-9\\-_. ]/gi, '_').slice(0, 120) || 'document'\n}\n\ntype ImageSource = {\n index: number\n length: number\n value: string\n}\n\nfunction readSingleImageSource(tag: string): ImageSource | null {\n const matches = Array.from(tag.matchAll(IMAGE_SOURCE_PATTERN))\n if (matches.length !== 1 || matches[0].index === undefined) return null\n return {\n index: matches[0].index,\n length: matches[0][0].length,\n value: matches[0][1] ?? matches[0][2] ?? matches[0][3] ?? '',\n }\n}\n\nfunction replaceImageSource(tag: string, source: ImageSource, value: string): string {\n return `${tag.slice(0, source.index)}src=\"${escapeHtml(value)}\"${tag.slice(source.index + source.length)}`\n}\n\nfunction hasSafeRasterDimensions(width: number, height: number): boolean {\n return Number.isSafeInteger(width)\n && Number.isSafeInteger(height)\n && width > 0\n && height > 0\n && width <= MAX_EMBEDDED_RASTER_DIMENSION\n && height <= MAX_EMBEDDED_RASTER_DIMENSION\n && width * height <= MAX_EMBEDDED_RASTER_PIXELS\n}\n\nfunction pngCrc32(bytes: Buffer): number {\n let crc = 0xffffffff\n for (const byte of bytes) {\n crc ^= byte\n for (let bit = 0; bit < 8; bit += 1) {\n crc = (crc >>> 1) ^ ((crc & 1) ? 0xedb88320 : 0)\n }\n }\n return (crc ^ 0xffffffff) >>> 0\n}\n\nfunction readPngDimensions(bytes: Buffer): { width: number; height: number } | null {\n const signature = '89504e470d0a1a0a'\n if (bytes.length < 45 || bytes.subarray(0, 8).toString('hex') !== signature) return null\n\n let offset = 8\n let dimensions: { width: number; height: number } | null = null\n let sawImageData = false\n while (offset + 12 <= bytes.length) {\n const length = bytes.readUInt32BE(offset)\n const chunkEnd = offset + 12 + length\n if (chunkEnd > bytes.length) return null\n const type = bytes.subarray(offset + 4, offset + 8)\n const data = bytes.subarray(offset + 8, offset + 8 + length)\n const expectedCrc = bytes.readUInt32BE(offset + 8 + length)\n if (pngCrc32(bytes.subarray(offset + 4, offset + 8 + length)) !== expectedCrc) return null\n const chunkType = type.toString('ascii')\n if (offset === 8) {\n if (chunkType !== 'IHDR' || length !== 13) return null\n const width = data.readUInt32BE(0)\n const height = data.readUInt32BE(4)\n const bitDepth = data[8]\n const colorType = data[9]\n const validBitDepth = (\n (colorType === 0 && [1, 2, 4, 8, 16].includes(bitDepth!))\n || (colorType === 2 && [8, 16].includes(bitDepth!))\n || (colorType === 3 && [1, 2, 4, 8].includes(bitDepth!))\n || (colorType === 4 && [8, 16].includes(bitDepth!))\n || (colorType === 6 && [8, 16].includes(bitDepth!))\n )\n if (\n !validBitDepth\n || data[10] !== 0\n || data[11] !== 0\n || (data[12] !== 0 && data[12] !== 1)\n || !hasSafeRasterDimensions(width, height)\n ) return null\n dimensions = { width, height }\n } else if (chunkType === 'IHDR') {\n return null\n }\n if (chunkType === 'IDAT') sawImageData = true\n if (chunkType === 'IEND') {\n return length === 0 && chunkEnd === bytes.length && sawImageData\n ? dimensions\n : null\n }\n offset = chunkEnd\n }\n return null\n}\n\nconst JPEG_START_OF_FRAME_MARKERS = new Set([\n 0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7,\n 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf,\n])\n\nfunction readJpegDimensions(bytes: Buffer): { width: number; height: number } | null {\n if (\n bytes.length < 12\n || bytes[0] !== 0xff\n || bytes[1] !== 0xd8\n || bytes.at(-2) !== 0xff\n || bytes.at(-1) !== 0xd9\n ) return null\n\n let offset = 2\n while (offset + 4 <= bytes.length - 2) {\n if (bytes[offset] !== 0xff) return null\n while (bytes[offset] === 0xff) offset += 1\n const marker = bytes[offset]\n offset += 1\n if (marker === undefined || marker === 0xda || marker === 0xd9) return null\n if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue\n if (offset + 2 > bytes.length - 2) return null\n const segmentLength = bytes.readUInt16BE(offset)\n if (segmentLength < 2 || offset + segmentLength > bytes.length - 2) return null\n if (JPEG_START_OF_FRAME_MARKERS.has(marker)) {\n if (segmentLength < 7) return null\n const height = bytes.readUInt16BE(offset + 3)\n const width = bytes.readUInt16BE(offset + 5)\n return hasSafeRasterDimensions(width, height) ? { width, height } : null\n }\n offset += segmentLength\n }\n return null\n}\n\nfunction readSafeEmbeddedImageBytes(source: string, maxDecodedBytes: number): number | null {\n const match = DATA_IMAGE_PATTERN.exec(source)\n if (!match) return null\n const mimeType = match[1].toLowerCase()\n const payload = match[2]\n if (\n !payload\n || payload.length > maxBase64EncodedLength(maxDecodedBytes)\n || payload.length % 4 !== 0\n ) return null\n const bytes = Buffer.from(payload, 'base64')\n if (\n bytes.length === 0\n || bytes.length > maxDecodedBytes\n || bytes.toString('base64') !== payload\n ) return null\n const dimensions = mimeType === 'png'\n ? readPngDimensions(bytes)\n : readJpegDimensions(bytes)\n if (!dimensions) return null\n return bytes.length\n}\n\n/**\n * Keep only bounded embedded PNG/JPEG payloads for the in-process OpenXML\n * renderer. Replace those small raster images with sanitizer-safe placeholders,\n * sanitize the full rich text, then restore the in-memory payloads. Every URL,\n * relative path, blob source, malformed data URI, SVG, duplicate src attribute,\n * and aggregate payload beyond the bound is removed before conversion, so no\n * exporter ever dereferences a remote image.\n */\nfunction sanitizeEmbeddedRasterExportContent(\n contentHtml: string,\n maxEmbeddedBytes: number,\n placeholderNamespace: 'docx' | 'pdf',\n): string {\n assertDocumentContentResourceLimits(\n { contentHtml },\n { error: 'documents.export.inputTooLarge' },\n )\n const embeddedImages = new Map<string, string>()\n let embeddedBytes = 0\n const placeholderHtml = contentHtml.replace(IMAGE_TAG_PATTERN, (tag) => {\n const source = readSingleImageSource(tag)\n if (!source) return ''\n const remainingBytes = maxEmbeddedBytes - embeddedBytes\n const imageBytes = readSafeEmbeddedImageBytes(source.value, remainingBytes)\n if (imageBytes === null || embeddedBytes + imageBytes > maxEmbeddedBytes) return ''\n embeddedBytes += imageBytes\n const placeholder = `https://${placeholderNamespace}.invalid/__embedded-image-${embeddedImages.size}`\n embeddedImages.set(placeholder, source.value)\n return replaceImageSource(tag, source, placeholder)\n })\n\n return sanitizeRichTextHtml(placeholderHtml).replace(IMAGE_TAG_PATTERN, (tag) => {\n const source = readSingleImageSource(tag)\n if (!source) return ''\n const embeddedSource = embeddedImages.get(source.value)\n return embeddedSource ? replaceImageSource(tag, source, embeddedSource) : ''\n })\n}\n\nexport function sanitizeDocxExportContent(contentHtml: string): string {\n return sanitizeEmbeddedRasterExportContent(\n contentHtml,\n DOCX_MAX_EMBEDDED_IMAGE_BYTES,\n 'docx',\n )\n}\n\n/**\n * Sanitize stored rich text and bound the decoded aggregate raster payload\n * before authored HTML reaches Chromium. Request interception remains a\n * defense-in-depth boundary, not the primary content validator.\n */\nexport function sanitizePdfExportContent(contentHtml: string): string {\n const semanticHtml = contentHtml\n .replace(ENTITY_REF_SPAN_PATTERN, '<strong><code><span>$1</span></code></strong>')\n .replace(HIGHLIGHT_OPEN_PATTERN, (_tag, attributes: string) => (\n /\\bstyle\\s*=/i.test(attributes)\n ? `<span${attributes}>`\n : `<span style=\"background-color:#fef08a\"${attributes}>`\n ))\n .replace(HIGHLIGHT_CLOSE_PATTERN, '</span>')\n const sanitized = sanitizeEmbeddedRasterExportContent(\n semanticHtml,\n PDF_MAX_EMBEDDED_IMAGE_BYTES,\n 'pdf',\n )\n return sanitized.replace(\n LEADING_TABLE_HEADER_ROW_PATTERN,\n '$1$2<thead>$4</thead><tbody>$3$5</tbody>',\n )\n}\n\nfunction buildExportHtml(title: string, contentHtml: string): string {\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta http-equiv=\"Content-Security-Policy\" content=\"default-src 'none'; img-src data:; style-src 'unsafe-inline'; script-src 'none'; frame-src 'none'; connect-src 'none'; base-uri 'none'; form-action 'none'\"><title>${escapeHtml(title)}</title></head><body>${contentHtml}</body></html>`\n}\n\nexport function applyDocxPageBreakMarkers(contentHtml: string, marker: string): string {\n const markerParagraph = `<p>${marker}</p>`\n const breakCount = contentHtml.split(markerParagraph).length - 1\n if (breakCount > 100) {\n throw new CrudHttpError(413, { error: 'documents.export.inputTooLarge' })\n }\n return contentHtml.replaceAll(\n markerParagraph,\n '<div class=\"page-break\" style=\"page-break-after: always\"></div>',\n )\n}\n\nfunction resolveChromiumExecutablePath(): string | null {\n const configured =\n process.env.DOCUMENTS_PDF_CHROMIUM_PATH?.trim() ||\n process.env.PUPPETEER_EXECUTABLE_PATH?.trim()\n if (configured) return configured\n return COMMON_CHROMIUM_PATHS.find((path) => existsSync(path)) ?? null\n}\n\nfunction toArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n const arrayBuffer = new ArrayBuffer(bytes.byteLength)\n new Uint8Array(arrayBuffer).set(bytes)\n return arrayBuffer\n}\n\n/**\n * PDF rendering is an inert conversion boundary, not a browser session. Never\n * allow a top-level/frame navigation or network fetch from authored content.\n * The only request class retained is a raster image embedded entirely in the\n * HTML itself; current editor configuration normally strips those too.\n */\nexport function isAllowedPdfAssetRequest(request: PdfRequestDescriptor): boolean {\n if (request.isNavigationRequest || request.resourceType !== 'image') return false\n const embeddedBytes = readSafeEmbeddedImageBytes(request.url, PDF_MAX_EMBEDDED_IMAGE_BYTES)\n return embeddedBytes !== null && embeddedBytes <= PDF_MAX_EMBEDDED_IMAGE_BYTES\n}\n\nasync function handleExport(\n request: Request,\n context: RouteContext,\n options?: {\n loadSnapshot?: () => Promise<z.infer<typeof docxSnapshotSchema>>\n operation?: string\n },\n): Promise<Response> {\n try {\n const format = resolveExportFormat(new URL(request.url).searchParams.get('format'))\n if (!format) {\n throw new CrudHttpError(400, { error: 'documents.export.unsupportedFormat' })\n }\n\n const id = await resolveId(context)\n const ctx = await resolveDocumentsContext(request, ['documents.view'])\n await assertTier(ctx.em, id, ctx.auth, 'viewer')\n const doc = await loadScopedDocument(ctx, id)\n // The snapshot body is buffered and validated only after the caller has\n // proven document access, so an unauthenticated request cannot make the\n // server process multi-megabyte payloads.\n const snapshot = options?.loadSnapshot ? await options.loadSnapshot() : undefined\n const content = await loadDocumentContent(ctx.em, id, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n })\n const contentHtml = format === 'docx' && snapshot ? snapshot.contentHtml : content?.contentHtml ?? ''\n assertDocumentContentResourceLimits(\n { contentHtml, contentText: content?.contentText },\n { error: 'documents.export.inputTooLarge' },\n )\n const safeName = buildSafeFilename(doc.title)\n\n if (format === 'docx') {\n const sanitized = sanitizeDocxExportContent(contentHtml)\n const paginated = snapshot\n ? applyDocxPageBreakMarkers(sanitized, snapshot.pageBreakMarker)\n : sanitized\n const docxHtml = buildExportHtml(doc.title, paginated)\n let bufferBytes: Uint8Array\n try {\n bufferBytes = await renderDocxWithCapacity(docxHtml)\n } catch (error) {\n if (isDocxRenderOverloadedError(error)) {\n throw new CrudHttpError(503, { error: 'documents.export.overloaded' })\n }\n if (isDocxRenderTimeoutError(error)) {\n throw new CrudHttpError(503, { error: 'documents.export.renderTimeout' })\n }\n if (isDocxRenderOutputTooLargeError(error)) {\n throw new CrudHttpError(413, { error: 'documents.export.outputTooLarge' })\n }\n if (isDocxRenderFailedError(error)) {\n throw new CrudHttpError(503, { error: 'documents.export.runtimeUnavailable' })\n }\n throw error\n }\n return new Response(toArrayBuffer(bufferBytes), {\n headers: {\n 'content-type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\n 'content-disposition': `attachment; filename=\"${safeName}.docx\"`,\n 'cache-control': 'private, no-store',\n },\n })\n }\n\n const executablePath = resolveChromiumExecutablePath()\n if (!executablePath) {\n throw new CrudHttpError(503, { error: 'documents.export.runtimeUnavailable' })\n }\n\n const pdfHtml = buildDocumentPdfHtml(doc.title, sanitizePdfExportContent(contentHtml))\n let pdf: Uint8Array\n try {\n pdf = await renderPdfWithChromium({\n html: pdfHtml,\n executablePath,\n isAllowedRequest: (interceptedRequest) => isAllowedPdfAssetRequest({\n url: interceptedRequest.url(),\n resourceType: interceptedRequest.resourceType(),\n isNavigationRequest: interceptedRequest.isNavigationRequest(),\n }),\n })\n } catch (error) {\n if (isPdfRenderOverloadedError(error)) {\n throw new CrudHttpError(503, { error: 'documents.export.overloaded' })\n }\n if (isPdfRenderTimeoutError(error)) {\n throw new CrudHttpError(503, { error: 'documents.export.renderTimeout' })\n }\n if (isPdfRenderOutputTooLargeError(error)) {\n throw new CrudHttpError(413, { error: 'documents.export.outputTooLarge' })\n }\n throw new CrudHttpError(503, { error: 'documents.export.runtimeUnavailable' })\n }\n return new Response(toArrayBuffer(pdf), {\n headers: {\n 'content-type': 'application/pdf',\n 'content-disposition': `attachment; filename=\"${safeName}.pdf\"`,\n 'cache-control': 'private, no-store',\n },\n })\n } catch (error) {\n return handleDocumentsRouteError(error, options?.operation ?? 'documents.export.get')\n }\n}\n\nexport async function GET(request: Request, context: RouteContext): Promise<Response> {\n return handleExport(request, context)\n}\n\nexport async function POST(request: Request, context: RouteContext): Promise<Response> {\n return handleExport(request, context, {\n loadSnapshot: async () => docxSnapshotSchema.parse(await readBody(\n request,\n DOCUMENTS_JSON_BODY_LIMITS.exportSnapshot,\n )),\n operation: 'documents.export.post',\n })\n}\n\nexport const openApi: OpenApiRouteDoc = withDocumentsContextErrors({\n tag: 'Documents',\n summary: 'Document export',\n pathParams: z.object({ id: z.string().uuid() }),\n methods: {\n GET: {\n summary: 'Export document',\n description: 'Returns a binary .docx or PDF file attachment for a document.',\n query: exportQuerySchema,\n responses: [\n { status: 200, description: 'Document export file', schema: fileResponseSchema, mediaType: 'application/octet-stream' },\n ],\n errors: [\n { status: 400, description: 'Unsupported format', schema: routeErrorSchema },\n { status: 401, description: 'Unauthorized', schema: routeErrorSchema },\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n { status: 404, description: 'Not found', schema: routeErrorSchema },\n { status: 413, description: 'Document or generated export exceeds the safe resource bound', schema: routeErrorSchema },\n { status: 503, description: 'Export runtime is unavailable, overloaded, or timed out', schema: routeErrorSchema },\n ],\n },\n POST: {\n summary: 'Export a paginated DOCX document',\n description: 'Returns a DOCX attachment using the editor pagination snapshot supplied by the client.',\n query: exportQuerySchema,\n requestBody: { contentType: 'application/json', schema: docxSnapshotSchema },\n responses: [\n { status: 200, description: 'Paginated DOCX export file', schema: fileResponseSchema, mediaType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' },\n ],\n errors: [\n { status: 400, description: 'Invalid pagination snapshot or unsupported format', schema: routeErrorSchema },\n { status: 401, description: 'Unauthorized', schema: routeErrorSchema },\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n { status: 404, description: 'Not found', schema: routeErrorSchema },\n { status: 413, description: 'Document or generated export exceeds the safe resource bound', schema: routeErrorSchema },\n { status: 503, description: 'Export runtime is unavailable, overloaded, or timed out', schema: routeErrorSchema },\n ],\n },\n },\n})\n\nexport default { GET, POST }\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { NextResponse } from "next/server";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { DOCUMENTS_ENTITY_IDS } from "../../../lib/constants.js";
|
|
5
|
+
import {
|
|
6
|
+
buildDocumentsCommandRuntimeContext,
|
|
7
|
+
resolveDocumentsCommandBus
|
|
8
|
+
} from "../../_commands.js";
|
|
9
|
+
import {
|
|
10
|
+
handleDocumentsRouteError,
|
|
11
|
+
resolveActorUserId,
|
|
12
|
+
resolveDocumentsContext,
|
|
13
|
+
routeErrorSchema,
|
|
14
|
+
runMutationGuardAfterSuccess,
|
|
15
|
+
validateMutationGuard,
|
|
16
|
+
withDocumentsContextErrors
|
|
17
|
+
} from "../../_shared.js";
|
|
18
|
+
const toggleResponseSchema = z.object({
|
|
19
|
+
id: z.string().uuid(),
|
|
20
|
+
active: z.boolean()
|
|
21
|
+
});
|
|
22
|
+
const metadata = {
|
|
23
|
+
POST: { requireAuth: true, requireFeatures: ["documents.view"] },
|
|
24
|
+
DELETE: { requireAuth: true, requireFeatures: ["documents.view"] }
|
|
25
|
+
};
|
|
26
|
+
async function runFavoriteToggle(request, context, commandId, operation, errorScope) {
|
|
27
|
+
try {
|
|
28
|
+
const { id: documentId } = await context.params;
|
|
29
|
+
const ctx = await resolveDocumentsContext(request, ["documents.view"]);
|
|
30
|
+
const guardResult = await validateMutationGuard(ctx, {
|
|
31
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentFavorite,
|
|
32
|
+
resourceId: documentId,
|
|
33
|
+
operation,
|
|
34
|
+
mutationPayload: { documentId }
|
|
35
|
+
});
|
|
36
|
+
const input = {
|
|
37
|
+
tenantId: ctx.tenantId,
|
|
38
|
+
organizationId: ctx.organizationId,
|
|
39
|
+
documentId,
|
|
40
|
+
favoriteId: randomUUID(),
|
|
41
|
+
actorUserId: resolveActorUserId(ctx.auth)
|
|
42
|
+
};
|
|
43
|
+
const commandBus = resolveDocumentsCommandBus(ctx);
|
|
44
|
+
const { result } = await commandBus.execute(
|
|
45
|
+
commandId,
|
|
46
|
+
{ input, ctx: buildDocumentsCommandRuntimeContext(ctx) }
|
|
47
|
+
);
|
|
48
|
+
await runMutationGuardAfterSuccess(ctx, guardResult, {
|
|
49
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentFavorite,
|
|
50
|
+
resourceId: documentId,
|
|
51
|
+
operation
|
|
52
|
+
});
|
|
53
|
+
return NextResponse.json({ id: result.id, active: result.active });
|
|
54
|
+
} catch (error) {
|
|
55
|
+
return handleDocumentsRouteError(error, errorScope);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function POST(request, context) {
|
|
59
|
+
return runFavoriteToggle(request, context, "documents.favorite.create", "create", "documents.favorite.create");
|
|
60
|
+
}
|
|
61
|
+
async function DELETE(request, context) {
|
|
62
|
+
return runFavoriteToggle(request, context, "documents.favorite.delete", "delete", "documents.favorite.delete");
|
|
63
|
+
}
|
|
64
|
+
const openApi = withDocumentsContextErrors({
|
|
65
|
+
tag: "Documents",
|
|
66
|
+
summary: "Document favorite toggle",
|
|
67
|
+
pathParams: z.object({ id: z.string().uuid() }),
|
|
68
|
+
methods: {
|
|
69
|
+
POST: {
|
|
70
|
+
summary: "Star a document for the current user",
|
|
71
|
+
responses: [{ status: 200, description: "Favorite state", schema: toggleResponseSchema }],
|
|
72
|
+
errors: [
|
|
73
|
+
{ status: 401, description: "Unauthorized", schema: routeErrorSchema },
|
|
74
|
+
{ status: 403, description: "Forbidden", schema: routeErrorSchema },
|
|
75
|
+
{ status: 404, description: "Document not found", schema: routeErrorSchema }
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
DELETE: {
|
|
79
|
+
summary: "Remove the current user star from a document",
|
|
80
|
+
responses: [{ status: 200, description: "Favorite state", schema: toggleResponseSchema }],
|
|
81
|
+
errors: [
|
|
82
|
+
{ status: 401, description: "Unauthorized", schema: routeErrorSchema },
|
|
83
|
+
{ status: 403, description: "Forbidden", schema: routeErrorSchema }
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
var route_default = { POST, DELETE };
|
|
89
|
+
export {
|
|
90
|
+
DELETE,
|
|
91
|
+
POST,
|
|
92
|
+
route_default as default,
|
|
93
|
+
metadata,
|
|
94
|
+
openApi
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/documents/api/%5Bid%5D/favorite/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { randomUUID } from 'node:crypto'\nimport { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport type { CommandBus } from '@open-mercato/shared/lib/commands'\nimport { DOCUMENTS_ENTITY_IDS } from '../../../lib/constants'\nimport type { FavoriteCommandInput, FavoriteCommandResult } from '../../../commands/favorites'\nimport {\n buildDocumentsCommandRuntimeContext,\n resolveDocumentsCommandBus,\n} from '../../_commands'\nimport {\n handleDocumentsRouteError,\n resolveActorUserId,\n resolveDocumentsContext,\n routeErrorSchema,\n runMutationGuardAfterSuccess,\n validateMutationGuard,\n type DocumentsRouteContext,\n withDocumentsContextErrors,\n} from '../../_shared'\n\ntype RouteContext = {\n params: Promise<{ id: string }> | { id: string }\n}\n\nconst toggleResponseSchema = z.object({\n id: z.string().uuid(),\n active: z.boolean(),\n})\n\nexport const metadata = {\n POST: { requireAuth: true, requireFeatures: ['documents.view'] },\n DELETE: { requireAuth: true, requireFeatures: ['documents.view'] },\n}\n\nasync function runFavoriteToggle(\n request: Request,\n context: RouteContext,\n commandId: 'documents.favorite.create' | 'documents.favorite.delete',\n operation: 'create' | 'delete',\n errorScope: string,\n): Promise<Response> {\n try {\n const { id: documentId } = await context.params\n const ctx: DocumentsRouteContext = await resolveDocumentsContext(request, ['documents.view'])\n const guardResult = await validateMutationGuard(ctx, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFavorite,\n resourceId: documentId,\n operation,\n mutationPayload: { documentId },\n })\n\n const input: FavoriteCommandInput = {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n documentId,\n favoriteId: randomUUID(),\n actorUserId: resolveActorUserId(ctx.auth),\n }\n const commandBus: CommandBus = resolveDocumentsCommandBus(ctx)\n const { result } = await commandBus.execute<FavoriteCommandInput, FavoriteCommandResult>(\n commandId,\n { input, ctx: buildDocumentsCommandRuntimeContext(ctx) },\n )\n await runMutationGuardAfterSuccess(ctx, guardResult, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentFavorite,\n resourceId: documentId,\n operation,\n })\n return NextResponse.json({ id: result.id, active: result.active })\n } catch (error) {\n return handleDocumentsRouteError(error, errorScope)\n }\n}\n\nexport async function POST(request: Request, context: RouteContext): Promise<Response> {\n return runFavoriteToggle(request, context, 'documents.favorite.create', 'create', 'documents.favorite.create')\n}\n\nexport async function DELETE(request: Request, context: RouteContext): Promise<Response> {\n return runFavoriteToggle(request, context, 'documents.favorite.delete', 'delete', 'documents.favorite.delete')\n}\n\nexport const openApi: OpenApiRouteDoc = withDocumentsContextErrors({\n tag: 'Documents',\n summary: 'Document favorite toggle',\n pathParams: z.object({ id: z.string().uuid() }),\n methods: {\n POST: {\n summary: 'Star a document for the current user',\n responses: [{ status: 200, description: 'Favorite state', schema: toggleResponseSchema }],\n errors: [\n { status: 401, description: 'Unauthorized', schema: routeErrorSchema },\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n { status: 404, description: 'Document not found', schema: routeErrorSchema },\n ],\n },\n DELETE: {\n summary: 'Remove the current user star from a document',\n responses: [{ status: 200, description: 'Favorite state', schema: toggleResponseSchema }],\n errors: [\n { status: 401, description: 'Unauthorized', schema: routeErrorSchema },\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n ],\n },\n },\n})\n\nexport default { POST, DELETE }\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { DOCUMENTS_ENTITY_IDS } from "../../../../lib/constants.js";
|
|
4
|
+
import { assertTier } from "../../../../lib/permissions.js";
|
|
5
|
+
import {
|
|
6
|
+
assertDocumentNotArchived,
|
|
7
|
+
handleDocumentsRouteError,
|
|
8
|
+
resolveDocumentsContext,
|
|
9
|
+
routeErrorSchema,
|
|
10
|
+
runMutationGuardAfterSuccess,
|
|
11
|
+
validateMutationGuard,
|
|
12
|
+
withDocumentsContextErrors
|
|
13
|
+
} from "../../../_shared.js";
|
|
14
|
+
import {
|
|
15
|
+
attachDocumentsOperationMetadata,
|
|
16
|
+
buildDocumentsCommandRuntimeContext,
|
|
17
|
+
resolveDocumentsCommandBus
|
|
18
|
+
} from "../../../_commands.js";
|
|
19
|
+
const deleteResponseSchema = z.object({
|
|
20
|
+
ok: z.boolean(),
|
|
21
|
+
id: z.string().uuid(),
|
|
22
|
+
updatedAt: z.string()
|
|
23
|
+
});
|
|
24
|
+
const metadata = {
|
|
25
|
+
DELETE: { requireAuth: true, requireFeatures: ["documents.edit"] }
|
|
26
|
+
};
|
|
27
|
+
async function DELETE(request, context) {
|
|
28
|
+
try {
|
|
29
|
+
const params = await context.params;
|
|
30
|
+
const ctx = await resolveDocumentsContext(request, ["documents.edit"]);
|
|
31
|
+
await assertTier(ctx.em, params.id, ctx.auth, "editor");
|
|
32
|
+
await assertDocumentNotArchived(ctx, params.id);
|
|
33
|
+
const guardResult = await validateMutationGuard(ctx, {
|
|
34
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,
|
|
35
|
+
resourceId: params.linkId,
|
|
36
|
+
operation: "delete"
|
|
37
|
+
});
|
|
38
|
+
const input = {
|
|
39
|
+
tenantId: ctx.tenantId,
|
|
40
|
+
organizationId: ctx.organizationId,
|
|
41
|
+
documentId: params.id,
|
|
42
|
+
linkId: params.linkId
|
|
43
|
+
};
|
|
44
|
+
const { result, logEntry } = await resolveDocumentsCommandBus(ctx).execute("documents.link.delete", {
|
|
45
|
+
input,
|
|
46
|
+
ctx: buildDocumentsCommandRuntimeContext(ctx)
|
|
47
|
+
});
|
|
48
|
+
await runMutationGuardAfterSuccess(ctx, guardResult, {
|
|
49
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,
|
|
50
|
+
resourceId: params.linkId,
|
|
51
|
+
operation: "delete"
|
|
52
|
+
});
|
|
53
|
+
const response = NextResponse.json({ ok: true, ...result });
|
|
54
|
+
return attachDocumentsOperationMetadata(response, logEntry, {
|
|
55
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,
|
|
56
|
+
resourceId: params.linkId
|
|
57
|
+
});
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return handleDocumentsRouteError(error, "documents.links.delete");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const openApi = withDocumentsContextErrors({
|
|
63
|
+
tag: "Documents",
|
|
64
|
+
summary: "Delete a document entity link",
|
|
65
|
+
pathParams: z.object({ id: z.string().uuid(), linkId: z.string().uuid() }),
|
|
66
|
+
methods: {
|
|
67
|
+
DELETE: {
|
|
68
|
+
summary: "Soft-delete a document entity link",
|
|
69
|
+
responses: [{ status: 200, description: "Link deleted", schema: deleteResponseSchema }],
|
|
70
|
+
errors: [
|
|
71
|
+
{ status: 403, description: "Forbidden", schema: routeErrorSchema },
|
|
72
|
+
{ status: 404, description: "Link not found", schema: routeErrorSchema },
|
|
73
|
+
{ status: 409, description: "Optimistic lock conflict", schema: routeErrorSchema }
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
var route_default = { DELETE };
|
|
79
|
+
export {
|
|
80
|
+
DELETE,
|
|
81
|
+
route_default as default,
|
|
82
|
+
metadata,
|
|
83
|
+
openApi
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../../src/modules/documents/api/%5Bid%5D/links/%5BlinkId%5D/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { DOCUMENTS_ENTITY_IDS } from '../../../../lib/constants'\nimport { assertTier } from '../../../../lib/permissions'\nimport {\n assertDocumentNotArchived,\n handleDocumentsRouteError,\n resolveDocumentsContext,\n routeErrorSchema,\n runMutationGuardAfterSuccess,\n validateMutationGuard,\n withDocumentsContextErrors,\n} from '../../../_shared'\nimport {\n attachDocumentsOperationMetadata,\n buildDocumentsCommandRuntimeContext,\n resolveDocumentsCommandBus,\n} from '../../../_commands'\nimport type { LinkDeleteCommandInput } from '../../../../commands/links'\n\ntype RouteContext = {\n params: Promise<{ id: string; linkId: string }> | { id: string; linkId: string }\n}\n\nconst deleteResponseSchema = z.object({\n ok: z.boolean(),\n id: z.string().uuid(),\n updatedAt: z.string(),\n})\n\nexport const metadata = {\n DELETE: { requireAuth: true, requireFeatures: ['documents.edit'] },\n}\n\nexport async function DELETE(request: Request, context: RouteContext): Promise<Response> {\n try {\n const params = await context.params\n const ctx = await resolveDocumentsContext(request, ['documents.edit'])\n await assertTier(ctx.em, params.id, ctx.auth, 'editor')\n await assertDocumentNotArchived(ctx, params.id)\n const guardResult = await validateMutationGuard(ctx, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,\n resourceId: params.linkId,\n operation: 'delete',\n })\n const input: LinkDeleteCommandInput = {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n documentId: params.id,\n linkId: params.linkId,\n }\n const { result, logEntry } = await resolveDocumentsCommandBus(ctx).execute<\n LinkDeleteCommandInput,\n { id: string; updatedAt: string }\n >('documents.link.delete', {\n input,\n ctx: buildDocumentsCommandRuntimeContext(ctx),\n })\n await runMutationGuardAfterSuccess(ctx, guardResult, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,\n resourceId: params.linkId,\n operation: 'delete',\n })\n const response = NextResponse.json({ ok: true, ...result })\n return attachDocumentsOperationMetadata(response, logEntry, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,\n resourceId: params.linkId,\n })\n } catch (error) {\n return handleDocumentsRouteError(error, 'documents.links.delete')\n }\n}\n\nexport const openApi: OpenApiRouteDoc = withDocumentsContextErrors({\n tag: 'Documents',\n summary: 'Delete a document entity link',\n pathParams: z.object({ id: z.string().uuid(), linkId: z.string().uuid() }),\n methods: {\n DELETE: {\n summary: 'Soft-delete a document entity link',\n responses: [{ status: 200, description: 'Link deleted', schema: deleteResponseSchema }],\n errors: [\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n { status: 404, description: 'Link not found', schema: routeErrorSchema },\n { status: 409, description: 'Optimistic lock conflict', schema: routeErrorSchema },\n ],\n },\n },\n})\n\nexport default { DELETE }\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAElB,SAAS,4BAA4B;AACrC,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAOP,MAAM,uBAAuB,EAAE,OAAO;AAAA,EACpC,IAAI,EAAE,QAAQ;AAAA,EACd,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,WAAW,EAAE,OAAO;AACtB,CAAC;AAEM,MAAM,WAAW;AAAA,EACtB,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,gBAAgB,EAAE;AACnE;AAEA,eAAsB,OAAO,SAAkB,SAA0C;AACvF,MAAI;AACF,UAAM,SAAS,MAAM,QAAQ;AAC7B,UAAM,MAAM,MAAM,wBAAwB,SAAS,CAAC,gBAAgB,CAAC;AACrE,UAAM,WAAW,IAAI,IAAI,OAAO,IAAI,IAAI,MAAM,QAAQ;AACtD,UAAM,0BAA0B,KAAK,OAAO,EAAE;AAC9C,UAAM,cAAc,MAAM,sBAAsB,KAAK;AAAA,MACnD,cAAc,qBAAqB;AAAA,MACnC,YAAY,OAAO;AAAA,MACnB,WAAW;AAAA,IACb,CAAC;AACD,UAAM,QAAgC;AAAA,MACpC,UAAU,IAAI;AAAA,MACd,gBAAgB,IAAI;AAAA,MACpB,YAAY,OAAO;AAAA,MACnB,QAAQ,OAAO;AAAA,IACjB;AACA,UAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,2BAA2B,GAAG,EAAE,QAGjE,yBAAyB;AAAA,MACzB;AAAA,MACA,KAAK,oCAAoC,GAAG;AAAA,IAC9C,CAAC;AACD,UAAM,6BAA6B,KAAK,aAAa;AAAA,MACnD,cAAc,qBAAqB;AAAA,MACnC,YAAY,OAAO;AAAA,MACnB,WAAW;AAAA,IACb,CAAC;AACD,UAAM,WAAW,aAAa,KAAK,EAAE,IAAI,MAAM,GAAG,OAAO,CAAC;AAC1D,WAAO,iCAAiC,UAAU,UAAU;AAAA,MAC1D,cAAc,qBAAqB;AAAA,MACnC,YAAY,OAAO;AAAA,IACrB,CAAC;AAAA,EACH,SAAS,OAAO;AACd,WAAO,0BAA0B,OAAO,wBAAwB;AAAA,EAClE;AACF;AAEO,MAAM,UAA2B,2BAA2B;AAAA,EACjE,KAAK;AAAA,EACL,SAAS;AAAA,EACT,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,GAAG,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAAA,EACzE,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,SAAS;AAAA,MACT,WAAW,CAAC,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,qBAAqB,CAAC;AAAA,MACtF,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,aAAa,QAAQ,iBAAiB;AAAA,QAClE,EAAE,QAAQ,KAAK,aAAa,kBAAkB,QAAQ,iBAAiB;AAAA,QACvE,EAAE,QAAQ,KAAK,aAAa,4BAA4B,QAAQ,iBAAiB;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AACF,CAAC;AAED,IAAO,gBAAQ,EAAE,OAAO;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { NextResponse } from "next/server";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
5
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
6
|
+
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
|
|
7
|
+
import { DocumentEntityLink } from "../../../data/entities.js";
|
|
8
|
+
import {
|
|
9
|
+
documentEntityLinkCreateSchema,
|
|
10
|
+
documentEntityLinkSourceSchema,
|
|
11
|
+
documentEntityTypeSchema
|
|
12
|
+
} from "../../../data/validators.js";
|
|
13
|
+
import { DOCUMENTS_ENTITY_IDS } from "../../../lib/constants.js";
|
|
14
|
+
import {
|
|
15
|
+
assertDocumentEntityLinkListWithinLimit,
|
|
16
|
+
findDocumentEntityLinks,
|
|
17
|
+
getDocumentEntityLinkEntityId,
|
|
18
|
+
getDocumentEntityLinkType,
|
|
19
|
+
serializeDocumentEntityLink
|
|
20
|
+
} from "../../../lib/entityLinks.js";
|
|
21
|
+
import { getEntityRegistryEntry } from "../../../lib/entityRegistry.js";
|
|
22
|
+
import { isDocumentEntityRegistryModuleEnabled } from "../../../lib/entityRegistryAvailability.server.js";
|
|
23
|
+
import { verifyEntityRegistryTargetAccess } from "../../../lib/entityRegistry.server.js";
|
|
24
|
+
import { assertTier } from "../../../lib/permissions.js";
|
|
25
|
+
import {
|
|
26
|
+
assertDocumentNotArchived,
|
|
27
|
+
handleDocumentsRouteError,
|
|
28
|
+
hasDocumentsFeature,
|
|
29
|
+
readBody,
|
|
30
|
+
resolveDocumentsContext,
|
|
31
|
+
routeErrorSchema,
|
|
32
|
+
runMutationGuardAfterSuccess,
|
|
33
|
+
validateMutationGuard,
|
|
34
|
+
withDocumentsContextErrors
|
|
35
|
+
} from "../../_shared.js";
|
|
36
|
+
import {
|
|
37
|
+
attachDocumentsOperationMetadata,
|
|
38
|
+
buildDocumentsCommandRuntimeContext,
|
|
39
|
+
resolveDocumentsCommandBus
|
|
40
|
+
} from "../../_commands.js";
|
|
41
|
+
const linkItemSchema = z.object({
|
|
42
|
+
id: z.string().uuid(),
|
|
43
|
+
entityType: documentEntityTypeSchema,
|
|
44
|
+
entityId: z.string().uuid().nullable(),
|
|
45
|
+
label: z.string(),
|
|
46
|
+
href: z.string().nullable(),
|
|
47
|
+
canOpen: z.boolean(),
|
|
48
|
+
archivedAt: z.string().nullable().optional(),
|
|
49
|
+
values: z.record(
|
|
50
|
+
z.string().min(1).max(64),
|
|
51
|
+
z.string().max(1e4).nullable()
|
|
52
|
+
).optional(),
|
|
53
|
+
source: documentEntityLinkSourceSchema,
|
|
54
|
+
createdAt: z.string(),
|
|
55
|
+
updatedAt: z.string()
|
|
56
|
+
});
|
|
57
|
+
const linksResponseSchema = z.object({ items: z.array(linkItemSchema) });
|
|
58
|
+
const LINK_TARGET_VERIFICATION_CONCURRENCY = 4;
|
|
59
|
+
const metadata = {
|
|
60
|
+
GET: { requireAuth: true, requireFeatures: ["documents.view"] },
|
|
61
|
+
POST: { requireAuth: true, requireFeatures: ["documents.edit"] }
|
|
62
|
+
};
|
|
63
|
+
async function resolveId(context) {
|
|
64
|
+
return (await context.params).id;
|
|
65
|
+
}
|
|
66
|
+
async function loadCreatedLink(em, id, scope) {
|
|
67
|
+
const link = await findOneWithDecryption(
|
|
68
|
+
em,
|
|
69
|
+
DocumentEntityLink,
|
|
70
|
+
{ id, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },
|
|
71
|
+
void 0,
|
|
72
|
+
scope
|
|
73
|
+
);
|
|
74
|
+
if (!link) throw new Error("[internal] created document link was not found");
|
|
75
|
+
return link;
|
|
76
|
+
}
|
|
77
|
+
function getLinkEntityType(link) {
|
|
78
|
+
return link.linkedDocumentId ? "document" : getDocumentEntityLinkType(link);
|
|
79
|
+
}
|
|
80
|
+
function getLinkEntityId(link) {
|
|
81
|
+
return link.linkedDocumentId ?? getDocumentEntityLinkEntityId(link);
|
|
82
|
+
}
|
|
83
|
+
function linkTargetVerificationKey(input) {
|
|
84
|
+
return JSON.stringify([input.entityType, input.entityId]);
|
|
85
|
+
}
|
|
86
|
+
async function verifyLinkTargets(request, inputs) {
|
|
87
|
+
const results = /* @__PURE__ */ new Map();
|
|
88
|
+
let nextIndex = 0;
|
|
89
|
+
const workers = Array.from(
|
|
90
|
+
{ length: Math.min(LINK_TARGET_VERIFICATION_CONCURRENCY, inputs.length) },
|
|
91
|
+
async () => {
|
|
92
|
+
while (nextIndex < inputs.length) {
|
|
93
|
+
const index = nextIndex;
|
|
94
|
+
nextIndex += 1;
|
|
95
|
+
const input = inputs[index];
|
|
96
|
+
const key = linkTargetVerificationKey(input);
|
|
97
|
+
try {
|
|
98
|
+
const verified = await verifyEntityRegistryTargetAccess(request, input);
|
|
99
|
+
results.set(key, {
|
|
100
|
+
id: verified.id,
|
|
101
|
+
label: verified.label,
|
|
102
|
+
href: verified.href,
|
|
103
|
+
values: verified.values,
|
|
104
|
+
archivedAt: verified.archivedAt
|
|
105
|
+
});
|
|
106
|
+
} catch {
|
|
107
|
+
results.set(key, null);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
await Promise.all(workers);
|
|
113
|
+
return results;
|
|
114
|
+
}
|
|
115
|
+
async function GET(request, context) {
|
|
116
|
+
try {
|
|
117
|
+
const documentId = await resolveId(context);
|
|
118
|
+
const ctx = await resolveDocumentsContext(request, ["documents.view"]);
|
|
119
|
+
await assertTier(ctx.em, documentId, ctx.auth, "viewer");
|
|
120
|
+
const { translate } = await resolveTranslations();
|
|
121
|
+
const links = await findDocumentEntityLinks(
|
|
122
|
+
ctx.em,
|
|
123
|
+
documentId,
|
|
124
|
+
{ tenantId: ctx.tenantId, organizationId: ctx.organizationId }
|
|
125
|
+
);
|
|
126
|
+
assertDocumentEntityLinkListWithinLimit(links);
|
|
127
|
+
const verificationInputByLinkId = /* @__PURE__ */ new Map();
|
|
128
|
+
const uniqueVerificationInputs = /* @__PURE__ */ new Map();
|
|
129
|
+
for (const link of links) {
|
|
130
|
+
const entityType = getLinkEntityType(link);
|
|
131
|
+
const entry = getEntityRegistryEntry(entityType);
|
|
132
|
+
if (!entry || !isDocumentEntityRegistryModuleEnabled(entry) || !hasDocumentsFeature(ctx.auth, entry.requiredFeature)) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const input = {
|
|
136
|
+
entityType,
|
|
137
|
+
entityId: getLinkEntityId(link)
|
|
138
|
+
};
|
|
139
|
+
verificationInputByLinkId.set(link.id, input);
|
|
140
|
+
uniqueVerificationInputs.set(linkTargetVerificationKey(input), input);
|
|
141
|
+
}
|
|
142
|
+
const verifiedTargets = await verifyLinkTargets(
|
|
143
|
+
request,
|
|
144
|
+
Array.from(uniqueVerificationInputs.values())
|
|
145
|
+
);
|
|
146
|
+
return NextResponse.json({
|
|
147
|
+
items: links.map((link) => {
|
|
148
|
+
const entityType = getLinkEntityType(link);
|
|
149
|
+
const verificationInput = verificationInputByLinkId.get(link.id);
|
|
150
|
+
const canonicalTarget = verificationInput ? verifiedTargets.get(linkTargetVerificationKey(verificationInput)) ?? null : null;
|
|
151
|
+
const serialized = serializeDocumentEntityLink(link, {
|
|
152
|
+
canOpen: Boolean(canonicalTarget),
|
|
153
|
+
restrictedLabel: translate("documents.links.restrictedRecord", "Restricted record"),
|
|
154
|
+
canonicalTarget: canonicalTarget ?? void 0
|
|
155
|
+
});
|
|
156
|
+
if (entityType !== "document") return serialized;
|
|
157
|
+
return {
|
|
158
|
+
...serialized,
|
|
159
|
+
entityType,
|
|
160
|
+
entityId: canonicalTarget?.id ?? null,
|
|
161
|
+
...canonicalTarget ? { archivedAt: canonicalTarget.archivedAt ?? null } : {}
|
|
162
|
+
};
|
|
163
|
+
})
|
|
164
|
+
});
|
|
165
|
+
} catch (error) {
|
|
166
|
+
return handleDocumentsRouteError(error, "documents.links.list");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async function POST(request, context) {
|
|
170
|
+
try {
|
|
171
|
+
const documentId = await resolveId(context);
|
|
172
|
+
const ctx = await resolveDocumentsContext(request, ["documents.edit"]);
|
|
173
|
+
await assertTier(ctx.em, documentId, ctx.auth, "editor");
|
|
174
|
+
await assertDocumentNotArchived(ctx, documentId);
|
|
175
|
+
const input = documentEntityLinkCreateSchema.parse(await readBody(request));
|
|
176
|
+
if (input.entityType === "document" && input.entityId === documentId) {
|
|
177
|
+
throw new CrudHttpError(400, { error: "documents.links.selfLinkForbidden" });
|
|
178
|
+
}
|
|
179
|
+
const registryEntry = getEntityRegistryEntry(input.entityType);
|
|
180
|
+
if (!registryEntry || !isDocumentEntityRegistryModuleEnabled(registryEntry) || !hasDocumentsFeature(ctx.auth, registryEntry.requiredFeature)) {
|
|
181
|
+
throw new CrudHttpError(403, { error: "api.errors.forbidden" });
|
|
182
|
+
}
|
|
183
|
+
const guardResult = await validateMutationGuard(ctx, {
|
|
184
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,
|
|
185
|
+
resourceId: "new",
|
|
186
|
+
operation: "create",
|
|
187
|
+
mutationPayload: input,
|
|
188
|
+
mutationPayloadSchema: documentEntityLinkCreateSchema
|
|
189
|
+
});
|
|
190
|
+
const commandInput = {
|
|
191
|
+
tenantId: ctx.tenantId,
|
|
192
|
+
organizationId: ctx.organizationId,
|
|
193
|
+
documentId,
|
|
194
|
+
linkId: randomUUID(),
|
|
195
|
+
link: input
|
|
196
|
+
};
|
|
197
|
+
const { result, logEntry } = await resolveDocumentsCommandBus(ctx).execute("documents.link.create", {
|
|
198
|
+
input: commandInput,
|
|
199
|
+
ctx: buildDocumentsCommandRuntimeContext(ctx)
|
|
200
|
+
});
|
|
201
|
+
const link = await loadCreatedLink(ctx.em, result.id, {
|
|
202
|
+
tenantId: ctx.tenantId,
|
|
203
|
+
organizationId: ctx.organizationId
|
|
204
|
+
});
|
|
205
|
+
await runMutationGuardAfterSuccess(ctx, guardResult, {
|
|
206
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,
|
|
207
|
+
resourceId: "new",
|
|
208
|
+
operation: "create"
|
|
209
|
+
});
|
|
210
|
+
const response = NextResponse.json(
|
|
211
|
+
serializeDocumentEntityLink(link, { canOpen: true, restrictedLabel: link.labelSnapshot }),
|
|
212
|
+
{ status: result.created ? 201 : 200 }
|
|
213
|
+
);
|
|
214
|
+
return attachDocumentsOperationMetadata(response, logEntry, {
|
|
215
|
+
resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,
|
|
216
|
+
resourceId: result.id
|
|
217
|
+
});
|
|
218
|
+
} catch (error) {
|
|
219
|
+
return handleDocumentsRouteError(error, "documents.links.create");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
const openApi = withDocumentsContextErrors({
|
|
223
|
+
tag: "Documents",
|
|
224
|
+
summary: "Document entity links",
|
|
225
|
+
pathParams: z.object({ id: z.string().uuid() }),
|
|
226
|
+
methods: {
|
|
227
|
+
GET: {
|
|
228
|
+
summary: "List entity links visible to the document viewer",
|
|
229
|
+
responses: [{ status: 200, description: "Document entity links", schema: linksResponseSchema }],
|
|
230
|
+
errors: [
|
|
231
|
+
{ status: 401, description: "Unauthorized", schema: routeErrorSchema },
|
|
232
|
+
{ status: 403, description: "Forbidden", schema: routeErrorSchema },
|
|
233
|
+
{ status: 413, description: "Request body or document link limit exceeds the safe resource bound", schema: routeErrorSchema }
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
POST: {
|
|
237
|
+
summary: "Link a document to an entity",
|
|
238
|
+
requestBody: { contentType: "application/json", schema: documentEntityLinkCreateSchema },
|
|
239
|
+
responses: [{ status: 201, description: "Link created", schema: linkItemSchema }],
|
|
240
|
+
errors: [
|
|
241
|
+
{ status: 400, description: "Validation failed", schema: routeErrorSchema },
|
|
242
|
+
{ status: 403, description: "Forbidden", schema: routeErrorSchema },
|
|
243
|
+
{ status: 413, description: "Document link limit exceeded", schema: routeErrorSchema },
|
|
244
|
+
{ status: 503, description: "Target lookup unavailable", schema: routeErrorSchema }
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
var route_default = { GET, POST };
|
|
250
|
+
export {
|
|
251
|
+
GET,
|
|
252
|
+
POST,
|
|
253
|
+
route_default as default,
|
|
254
|
+
metadata,
|
|
255
|
+
openApi
|
|
256
|
+
};
|
|
257
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/modules/documents/api/%5Bid%5D/links/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { randomUUID } from 'node:crypto'\nimport { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { DocumentEntityLink } from '../../../data/entities'\nimport {\n documentEntityLinkCreateSchema,\n documentEntityLinkSourceSchema,\n documentEntityTypeSchema,\n} from '../../../data/validators'\nimport { DOCUMENTS_ENTITY_IDS } from '../../../lib/constants'\nimport {\n assertDocumentEntityLinkListWithinLimit,\n findDocumentEntityLinks,\n getDocumentEntityLinkEntityId,\n getDocumentEntityLinkType,\n serializeDocumentEntityLink,\n type DocumentEntityLinkCanonicalTarget,\n} from '../../../lib/entityLinks'\nimport { getEntityRegistryEntry } from '../../../lib/entityRegistry'\nimport { isDocumentEntityRegistryModuleEnabled } from '../../../lib/entityRegistryAvailability.server'\nimport { verifyEntityRegistryTargetAccess } from '../../../lib/entityRegistry.server'\nimport { assertTier } from '../../../lib/permissions'\nimport {\n assertDocumentNotArchived,\n handleDocumentsRouteError,\n hasDocumentsFeature,\n readBody,\n resolveDocumentsContext,\n routeErrorSchema,\n runMutationGuardAfterSuccess,\n validateMutationGuard,\n withDocumentsContextErrors,\n} from '../../_shared'\nimport {\n attachDocumentsOperationMetadata,\n buildDocumentsCommandRuntimeContext,\n resolveDocumentsCommandBus,\n} from '../../_commands'\nimport type { LinkCreateCommandInput } from '../../../commands/links'\n\ntype RouteContext = {\n params: Promise<{ id: string }> | { id: string }\n}\n\nconst linkItemSchema = z.object({\n id: z.string().uuid(),\n entityType: documentEntityTypeSchema,\n entityId: z.string().uuid().nullable(),\n label: z.string(),\n href: z.string().nullable(),\n canOpen: z.boolean(),\n archivedAt: z.string().nullable().optional(),\n values: z.record(\n z.string().min(1).max(64),\n z.string().max(10000).nullable(),\n ).optional(),\n source: documentEntityLinkSourceSchema,\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\nconst linksResponseSchema = z.object({ items: z.array(linkItemSchema) })\nconst LINK_TARGET_VERIFICATION_CONCURRENCY = 4\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['documents.view'] },\n POST: { requireAuth: true, requireFeatures: ['documents.edit'] },\n}\n\nasync function resolveId(context: RouteContext): Promise<string> {\n return (await context.params).id\n}\n\nasync function loadCreatedLink(\n em: EntityManager,\n id: string,\n scope: { tenantId: string; organizationId: string },\n): Promise<DocumentEntityLink> {\n const link = await findOneWithDecryption(\n em,\n DocumentEntityLink,\n { id, tenantId: scope.tenantId, organizationId: scope.organizationId, deletedAt: null },\n undefined,\n scope,\n )\n if (!link) throw new Error('[internal] created document link was not found')\n return link\n}\n\ntype LinkTargetVerificationInput = {\n entityType: z.infer<typeof documentEntityTypeSchema>\n entityId: string\n}\n\ntype VerifiedLinkTarget = DocumentEntityLinkCanonicalTarget & {\n archivedAt?: string | null\n}\n\nfunction getLinkEntityType(link: DocumentEntityLink): z.infer<typeof documentEntityTypeSchema> {\n return link.linkedDocumentId ? 'document' : getDocumentEntityLinkType(link)\n}\n\nfunction getLinkEntityId(link: DocumentEntityLink): string {\n return link.linkedDocumentId ?? getDocumentEntityLinkEntityId(link)\n}\n\nfunction linkTargetVerificationKey(input: LinkTargetVerificationInput): string {\n return JSON.stringify([input.entityType, input.entityId])\n}\n\nasync function verifyLinkTargets(\n request: Request,\n inputs: LinkTargetVerificationInput[],\n): Promise<Map<string, VerifiedLinkTarget | null>> {\n const results = new Map<string, VerifiedLinkTarget | null>()\n let nextIndex = 0\n const workers = Array.from(\n { length: Math.min(LINK_TARGET_VERIFICATION_CONCURRENCY, inputs.length) },\n async () => {\n while (nextIndex < inputs.length) {\n const index = nextIndex\n nextIndex += 1\n const input = inputs[index]!\n const key = linkTargetVerificationKey(input)\n try {\n const verified = await verifyEntityRegistryTargetAccess(request, input)\n results.set(key, {\n id: verified.id,\n label: verified.label,\n href: verified.href,\n values: verified.values,\n archivedAt: verified.archivedAt,\n })\n } catch {\n results.set(key, null)\n }\n }\n },\n )\n await Promise.all(workers)\n return results\n}\n\nexport async function GET(request: Request, context: RouteContext): Promise<Response> {\n try {\n const documentId = await resolveId(context)\n const ctx = await resolveDocumentsContext(request, ['documents.view'])\n await assertTier(ctx.em, documentId, ctx.auth, 'viewer')\n const { translate } = await resolveTranslations()\n const links = await findDocumentEntityLinks(\n ctx.em,\n documentId,\n { tenantId: ctx.tenantId, organizationId: ctx.organizationId },\n )\n // Keep the route safe even when a custom repository/DI override returns a\n // body that did not pass through the default bounded reader.\n assertDocumentEntityLinkListWithinLimit(links)\n const verificationInputByLinkId = new Map<string, LinkTargetVerificationInput>()\n const uniqueVerificationInputs = new Map<string, LinkTargetVerificationInput>()\n for (const link of links) {\n const entityType = getLinkEntityType(link)\n const entry = getEntityRegistryEntry(entityType)\n if (\n !entry\n || !isDocumentEntityRegistryModuleEnabled(entry)\n || !hasDocumentsFeature(ctx.auth, entry.requiredFeature)\n ) {\n continue\n }\n const input = {\n entityType,\n entityId: getLinkEntityId(link),\n }\n verificationInputByLinkId.set(link.id, input)\n uniqueVerificationInputs.set(linkTargetVerificationKey(input), input)\n }\n const verifiedTargets = await verifyLinkTargets(\n request,\n Array.from(uniqueVerificationInputs.values()),\n )\n return NextResponse.json({\n items: links.map((link) => {\n const entityType = getLinkEntityType(link)\n const verificationInput = verificationInputByLinkId.get(link.id)\n const canonicalTarget = verificationInput\n ? verifiedTargets.get(linkTargetVerificationKey(verificationInput)) ?? null\n : null\n const serialized = serializeDocumentEntityLink(link, {\n canOpen: Boolean(canonicalTarget),\n restrictedLabel: translate('documents.links.restrictedRecord', 'Restricted record'),\n canonicalTarget: canonicalTarget ?? undefined,\n })\n if (entityType !== 'document') return serialized\n return {\n ...serialized,\n entityType,\n entityId: canonicalTarget?.id ?? null,\n ...(canonicalTarget ? { archivedAt: canonicalTarget.archivedAt ?? null } : {}),\n }\n }),\n })\n } catch (error) {\n return handleDocumentsRouteError(error, 'documents.links.list')\n }\n}\n\nexport async function POST(request: Request, context: RouteContext): Promise<Response> {\n try {\n const documentId = await resolveId(context)\n const ctx = await resolveDocumentsContext(request, ['documents.edit'])\n await assertTier(ctx.em, documentId, ctx.auth, 'editor')\n await assertDocumentNotArchived(ctx, documentId)\n const input = documentEntityLinkCreateSchema.parse(await readBody(request))\n if (input.entityType === 'document' && input.entityId === documentId) {\n throw new CrudHttpError(400, { error: 'documents.links.selfLinkForbidden' })\n }\n const registryEntry = getEntityRegistryEntry(input.entityType)\n if (\n !registryEntry\n || !isDocumentEntityRegistryModuleEnabled(registryEntry)\n || !hasDocumentsFeature(ctx.auth, registryEntry.requiredFeature)\n ) {\n throw new CrudHttpError(403, { error: 'api.errors.forbidden' })\n }\n const guardResult = await validateMutationGuard(ctx, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,\n resourceId: 'new',\n operation: 'create',\n mutationPayload: input,\n mutationPayloadSchema: documentEntityLinkCreateSchema,\n })\n const commandInput: LinkCreateCommandInput = {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n documentId,\n linkId: randomUUID(),\n link: input,\n }\n const { result, logEntry } = await resolveDocumentsCommandBus(ctx).execute<\n LinkCreateCommandInput,\n { id: string; created: boolean; updatedAt: string }\n >('documents.link.create', {\n input: commandInput,\n ctx: buildDocumentsCommandRuntimeContext(ctx),\n })\n const link = await loadCreatedLink(ctx.em, result.id, {\n tenantId: ctx.tenantId,\n organizationId: ctx.organizationId,\n })\n await runMutationGuardAfterSuccess(ctx, guardResult, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,\n resourceId: 'new',\n operation: 'create',\n })\n const response = NextResponse.json(\n serializeDocumentEntityLink(link, { canOpen: true, restrictedLabel: link.labelSnapshot }),\n { status: result.created ? 201 : 200 },\n )\n return attachDocumentsOperationMetadata(response, logEntry, {\n resourceKind: DOCUMENTS_ENTITY_IDS.documentEntityLink,\n resourceId: result.id,\n })\n } catch (error) {\n return handleDocumentsRouteError(error, 'documents.links.create')\n }\n}\n\nexport const openApi: OpenApiRouteDoc = withDocumentsContextErrors({\n tag: 'Documents',\n summary: 'Document entity links',\n pathParams: z.object({ id: z.string().uuid() }),\n methods: {\n GET: {\n summary: 'List entity links visible to the document viewer',\n responses: [{ status: 200, description: 'Document entity links', schema: linksResponseSchema }],\n errors: [\n { status: 401, description: 'Unauthorized', schema: routeErrorSchema },\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n { status: 413, description: 'Request body or document link limit exceeds the safe resource bound', schema: routeErrorSchema },\n ],\n },\n POST: {\n summary: 'Link a document to an entity',\n requestBody: { contentType: 'application/json', schema: documentEntityLinkCreateSchema },\n responses: [{ status: 201, description: 'Link created', schema: linkItemSchema }],\n errors: [\n { status: 400, description: 'Validation failed', schema: routeErrorSchema },\n { status: 403, description: 'Forbidden', schema: routeErrorSchema },\n { status: 413, description: 'Document link limit exceeded', schema: routeErrorSchema },\n { status: 503, description: 'Target lookup unavailable', schema: routeErrorSchema },\n ],\n },\n },\n})\n\nexport default { GET, POST }\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|