@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.
Files changed (602) hide show
  1. package/README.md +88 -0
  2. package/build.mjs +23 -0
  3. package/dist/index.js +5 -0
  4. package/dist/index.js.map +7 -0
  5. package/dist/modules/documents/acl.js +15 -0
  6. package/dist/modules/documents/acl.js.map +7 -0
  7. package/dist/modules/documents/api/[id]/archive/route.js +116 -0
  8. package/dist/modules/documents/api/[id]/archive/route.js.map +7 -0
  9. package/dist/modules/documents/api/[id]/attachments/[attachmentId]/route.js +155 -0
  10. package/dist/modules/documents/api/[id]/attachments/[attachmentId]/route.js.map +7 -0
  11. package/dist/modules/documents/api/[id]/attachments/route.js +153 -0
  12. package/dist/modules/documents/api/[id]/attachments/route.js.map +7 -0
  13. package/dist/modules/documents/api/[id]/collab-token/route.js +180 -0
  14. package/dist/modules/documents/api/[id]/collab-token/route.js.map +7 -0
  15. package/dist/modules/documents/api/[id]/comments/access-check/route.js +86 -0
  16. package/dist/modules/documents/api/[id]/comments/access-check/route.js.map +7 -0
  17. package/dist/modules/documents/api/[id]/comments/route.js +387 -0
  18. package/dist/modules/documents/api/[id]/comments/route.js.map +7 -0
  19. package/dist/modules/documents/api/[id]/content/route.js +143 -0
  20. package/dist/modules/documents/api/[id]/content/route.js.map +7 -0
  21. package/dist/modules/documents/api/[id]/duplicate/route.js +200 -0
  22. package/dist/modules/documents/api/[id]/duplicate/route.js.map +7 -0
  23. package/dist/modules/documents/api/[id]/export/route.js +421 -0
  24. package/dist/modules/documents/api/[id]/export/route.js.map +7 -0
  25. package/dist/modules/documents/api/[id]/favorite/route.js +96 -0
  26. package/dist/modules/documents/api/[id]/favorite/route.js.map +7 -0
  27. package/dist/modules/documents/api/[id]/links/[linkId]/route.js +85 -0
  28. package/dist/modules/documents/api/[id]/links/[linkId]/route.js.map +7 -0
  29. package/dist/modules/documents/api/[id]/links/route.js +257 -0
  30. package/dist/modules/documents/api/[id]/links/route.js.map +7 -0
  31. package/dist/modules/documents/api/[id]/principals/route.js +299 -0
  32. package/dist/modules/documents/api/[id]/principals/route.js.map +7 -0
  33. package/dist/modules/documents/api/[id]/route.js +246 -0
  34. package/dist/modules/documents/api/[id]/route.js.map +7 -0
  35. package/dist/modules/documents/api/[id]/shares/route.js +335 -0
  36. package/dist/modules/documents/api/[id]/shares/route.js.map +7 -0
  37. package/dist/modules/documents/api/[id]/unarchive/route.js +39 -0
  38. package/dist/modules/documents/api/[id]/unarchive/route.js.map +7 -0
  39. package/dist/modules/documents/api/[id]/versions/[versionId]/restore/route.js +133 -0
  40. package/dist/modules/documents/api/[id]/versions/[versionId]/restore/route.js.map +7 -0
  41. package/dist/modules/documents/api/[id]/versions/[versionId]/route.js +93 -0
  42. package/dist/modules/documents/api/[id]/versions/[versionId]/route.js.map +7 -0
  43. package/dist/modules/documents/api/[id]/versions/route.js +193 -0
  44. package/dist/modules/documents/api/[id]/versions/route.js.map +7 -0
  45. package/dist/modules/documents/api/[id]/watch/route.js +97 -0
  46. package/dist/modules/documents/api/[id]/watch/route.js.map +7 -0
  47. package/dist/modules/documents/api/_commands.js +34 -0
  48. package/dist/modules/documents/api/_commands.js.map +7 -0
  49. package/dist/modules/documents/api/_shared.js +490 -0
  50. package/dist/modules/documents/api/_shared.js.map +7 -0
  51. package/dist/modules/documents/api/folders/route.js +256 -0
  52. package/dist/modules/documents/api/folders/route.js.map +7 -0
  53. package/dist/modules/documents/api/instantiate/route.js +108 -0
  54. package/dist/modules/documents/api/instantiate/route.js.map +7 -0
  55. package/dist/modules/documents/api/route.js +322 -0
  56. package/dist/modules/documents/api/route.js.map +7 -0
  57. package/dist/modules/documents/api/templates/[templateId]/preview/route.js +94 -0
  58. package/dist/modules/documents/api/templates/[templateId]/preview/route.js.map +7 -0
  59. package/dist/modules/documents/api/templates/[templateId]/route.js +82 -0
  60. package/dist/modules/documents/api/templates/[templateId]/route.js.map +7 -0
  61. package/dist/modules/documents/api/templates/route.js +344 -0
  62. package/dist/modules/documents/api/templates/route.js.map +7 -0
  63. package/dist/modules/documents/backend/documents/DocumentsPageClient.js +160 -0
  64. package/dist/modules/documents/backend/documents/DocumentsPageClient.js.map +7 -0
  65. package/dist/modules/documents/backend/documents/DocumentsTable.js +143 -0
  66. package/dist/modules/documents/backend/documents/DocumentsTable.js.map +7 -0
  67. package/dist/modules/documents/backend/documents/FolderDialog.js +55 -0
  68. package/dist/modules/documents/backend/documents/FolderDialog.js.map +7 -0
  69. package/dist/modules/documents/backend/documents/FolderTree.js +40 -0
  70. package/dist/modules/documents/backend/documents/FolderTree.js.map +7 -0
  71. package/dist/modules/documents/backend/documents/MoveDocumentDialog.js +64 -0
  72. package/dist/modules/documents/backend/documents/MoveDocumentDialog.js.map +7 -0
  73. package/dist/modules/documents/backend/documents/[id]/CommentAnchorNavigation.js +77 -0
  74. package/dist/modules/documents/backend/documents/[id]/CommentAnchorNavigation.js.map +7 -0
  75. package/dist/modules/documents/backend/documents/[id]/CommentComposer.js +126 -0
  76. package/dist/modules/documents/backend/documents/[id]/CommentComposer.js.map +7 -0
  77. package/dist/modules/documents/backend/documents/[id]/CommentThreadList.js +88 -0
  78. package/dist/modules/documents/backend/documents/[id]/CommentThreadList.js.map +7 -0
  79. package/dist/modules/documents/backend/documents/[id]/CommentsRail.js +123 -0
  80. package/dist/modules/documents/backend/documents/[id]/CommentsRail.js.map +7 -0
  81. package/dist/modules/documents/backend/documents/[id]/DocumentCanvas.js +91 -0
  82. package/dist/modules/documents/backend/documents/[id]/DocumentCanvas.js.map +7 -0
  83. package/dist/modules/documents/backend/documents/[id]/DocumentEditorErrorBoundary.js +27 -0
  84. package/dist/modules/documents/backend/documents/[id]/DocumentEditorErrorBoundary.js.map +7 -0
  85. package/dist/modules/documents/backend/documents/[id]/DocumentEditorIsland.js +50 -0
  86. package/dist/modules/documents/backend/documents/[id]/DocumentEditorIsland.js.map +7 -0
  87. package/dist/modules/documents/backend/documents/[id]/DocumentEditorSurface.js +168 -0
  88. package/dist/modules/documents/backend/documents/[id]/DocumentEditorSurface.js.map +7 -0
  89. package/dist/modules/documents/backend/documents/[id]/DocumentNavigator.js +129 -0
  90. package/dist/modules/documents/backend/documents/[id]/DocumentNavigator.js.map +7 -0
  91. package/dist/modules/documents/backend/documents/[id]/DocumentPageClient.js +429 -0
  92. package/dist/modules/documents/backend/documents/[id]/DocumentPageClient.js.map +7 -0
  93. package/dist/modules/documents/backend/documents/[id]/EditorColorTools.js +68 -0
  94. package/dist/modules/documents/backend/documents/[id]/EditorColorTools.js.map +7 -0
  95. package/dist/modules/documents/backend/documents/[id]/EditorStatusPresence.js +69 -0
  96. package/dist/modules/documents/backend/documents/[id]/EditorStatusPresence.js.map +7 -0
  97. package/dist/modules/documents/backend/documents/[id]/EditorToolbar.js +151 -0
  98. package/dist/modules/documents/backend/documents/[id]/EditorToolbar.js.map +7 -0
  99. package/dist/modules/documents/backend/documents/[id]/ExportMenu.js +121 -0
  100. package/dist/modules/documents/backend/documents/[id]/ExportMenu.js.map +7 -0
  101. package/dist/modules/documents/backend/documents/[id]/MentionPicker.js +114 -0
  102. package/dist/modules/documents/backend/documents/[id]/MentionPicker.js.map +7 -0
  103. package/dist/modules/documents/backend/documents/[id]/OutlinePane.js +70 -0
  104. package/dist/modules/documents/backend/documents/[id]/OutlinePane.js.map +7 -0
  105. package/dist/modules/documents/backend/documents/[id]/RecordFieldsDialog.js +157 -0
  106. package/dist/modules/documents/backend/documents/[id]/RecordFieldsDialog.js.map +7 -0
  107. package/dist/modules/documents/backend/documents/[id]/RelatedRecordsPanel.js +266 -0
  108. package/dist/modules/documents/backend/documents/[id]/RelatedRecordsPanel.js.map +7 -0
  109. package/dist/modules/documents/backend/documents/[id]/VersionHistoryPanel.js +227 -0
  110. package/dist/modules/documents/backend/documents/[id]/VersionHistoryPanel.js.map +7 -0
  111. package/dist/modules/documents/backend/documents/[id]/VersionPreviewDialog.js +157 -0
  112. package/dist/modules/documents/backend/documents/[id]/VersionPreviewDialog.js.map +7 -0
  113. package/dist/modules/documents/backend/documents/[id]/commentTypes.js +150 -0
  114. package/dist/modules/documents/backend/documents/[id]/commentTypes.js.map +7 -0
  115. package/dist/modules/documents/backend/documents/[id]/componentCapabilities.js +13 -0
  116. package/dist/modules/documents/backend/documents/[id]/componentCapabilities.js.map +7 -0
  117. package/dist/modules/documents/backend/documents/[id]/documentPagination.js +295 -0
  118. package/dist/modules/documents/backend/documents/[id]/documentPagination.js.map +7 -0
  119. package/dist/modules/documents/backend/documents/[id]/editorPresenceStyles.js +81 -0
  120. package/dist/modules/documents/backend/documents/[id]/editorPresenceStyles.js.map +7 -0
  121. package/dist/modules/documents/backend/documents/[id]/editorTypes.js +52 -0
  122. package/dist/modules/documents/backend/documents/[id]/editorTypes.js.map +7 -0
  123. package/dist/modules/documents/backend/documents/[id]/page.js +10 -0
  124. package/dist/modules/documents/backend/documents/[id]/page.js.map +7 -0
  125. package/dist/modules/documents/backend/documents/[id]/page.meta.js +16 -0
  126. package/dist/modules/documents/backend/documents/[id]/page.meta.js.map +7 -0
  127. package/dist/modules/documents/backend/documents/[id]/relatedRecordModel.js +38 -0
  128. package/dist/modules/documents/backend/documents/[id]/relatedRecordModel.js.map +7 -0
  129. package/dist/modules/documents/backend/documents/[id]/restoreVersion.js +33 -0
  130. package/dist/modules/documents/backend/documents/[id]/restoreVersion.js.map +7 -0
  131. package/dist/modules/documents/backend/documents/[id]/useDocumentCollaboration.js +392 -0
  132. package/dist/modules/documents/backend/documents/[id]/useDocumentCollaboration.js.map +7 -0
  133. package/dist/modules/documents/backend/documents/[id]/useDocumentComments.js +253 -0
  134. package/dist/modules/documents/backend/documents/[id]/useDocumentComments.js.map +7 -0
  135. package/dist/modules/documents/backend/documents/[id]/useDocumentEditor.js +149 -0
  136. package/dist/modules/documents/backend/documents/[id]/useDocumentEditor.js.map +7 -0
  137. package/dist/modules/documents/backend/documents/[id]/useDocumentTitle.js +82 -0
  138. package/dist/modules/documents/backend/documents/[id]/useDocumentTitle.js.map +7 -0
  139. package/dist/modules/documents/backend/documents/[id]/useEditorInsertions.js +144 -0
  140. package/dist/modules/documents/backend/documents/[id]/useEditorInsertions.js.map +7 -0
  141. package/dist/modules/documents/backend/documents/[id]/useFallbackContentPersistence.js +237 -0
  142. package/dist/modules/documents/backend/documents/[id]/useFallbackContentPersistence.js.map +7 -0
  143. package/dist/modules/documents/backend/documents/[id]/useMentionPicker.js +216 -0
  144. package/dist/modules/documents/backend/documents/[id]/useMentionPicker.js.map +7 -0
  145. package/dist/modules/documents/backend/documents/[id]/versionHistoryModel.js +25 -0
  146. package/dist/modules/documents/backend/documents/[id]/versionHistoryModel.js.map +7 -0
  147. package/dist/modules/documents/backend/documents/components/EntityPicker.js +156 -0
  148. package/dist/modules/documents/backend/documents/components/EntityPicker.js.map +7 -0
  149. package/dist/modules/documents/backend/documents/components/EntityPickerResults.js +46 -0
  150. package/dist/modules/documents/backend/documents/components/EntityPickerResults.js.map +7 -0
  151. package/dist/modules/documents/backend/documents/components/NewFromTemplateDialog.js +127 -0
  152. package/dist/modules/documents/backend/documents/components/NewFromTemplateDialog.js.map +7 -0
  153. package/dist/modules/documents/backend/documents/components/PrincipalPicker.js +84 -0
  154. package/dist/modules/documents/backend/documents/components/PrincipalPicker.js.map +7 -0
  155. package/dist/modules/documents/backend/documents/components/ShareDialog.js +77 -0
  156. package/dist/modules/documents/backend/documents/components/ShareDialog.js.map +7 -0
  157. package/dist/modules/documents/backend/documents/components/ShareDialogAddForm.js +93 -0
  158. package/dist/modules/documents/backend/documents/components/ShareDialogAddForm.js.map +7 -0
  159. package/dist/modules/documents/backend/documents/components/ShareDialogList.js +82 -0
  160. package/dist/modules/documents/backend/documents/components/ShareDialogList.js.map +7 -0
  161. package/dist/modules/documents/backend/documents/components/TemplateBodyEditor.js +96 -0
  162. package/dist/modules/documents/backend/documents/components/TemplateBodyEditor.js.map +7 -0
  163. package/dist/modules/documents/backend/documents/components/TemplateEditorDialog.js +169 -0
  164. package/dist/modules/documents/backend/documents/components/TemplateEditorDialog.js.map +7 -0
  165. package/dist/modules/documents/backend/documents/components/TemplatePreview.js +38 -0
  166. package/dist/modules/documents/backend/documents/components/TemplatePreview.js.map +7 -0
  167. package/dist/modules/documents/backend/documents/components/TemplateSlotFields.js +69 -0
  168. package/dist/modules/documents/backend/documents/components/TemplateSlotFields.js.map +7 -0
  169. package/dist/modules/documents/backend/documents/components/TemplateSlotsEditor.js +71 -0
  170. package/dist/modules/documents/backend/documents/components/TemplateSlotsEditor.js.map +7 -0
  171. package/dist/modules/documents/backend/documents/components/principalPickerModel.js +63 -0
  172. package/dist/modules/documents/backend/documents/components/principalPickerModel.js.map +7 -0
  173. package/dist/modules/documents/backend/documents/components/shareDialogModel.js +68 -0
  174. package/dist/modules/documents/backend/documents/components/shareDialogModel.js.map +7 -0
  175. package/dist/modules/documents/backend/documents/components/templateUi.js +89 -0
  176. package/dist/modules/documents/backend/documents/components/templateUi.js.map +7 -0
  177. package/dist/modules/documents/backend/documents/components/useAvailableEntityRegistry.js +30 -0
  178. package/dist/modules/documents/backend/documents/components/useAvailableEntityRegistry.js.map +7 -0
  179. package/dist/modules/documents/backend/documents/components/useEntitySearch.js +191 -0
  180. package/dist/modules/documents/backend/documents/components/useEntitySearch.js.map +7 -0
  181. package/dist/modules/documents/backend/documents/components/usePrincipalPicker.js +221 -0
  182. package/dist/modules/documents/backend/documents/components/usePrincipalPicker.js.map +7 -0
  183. package/dist/modules/documents/backend/documents/components/useShareDialog.js +236 -0
  184. package/dist/modules/documents/backend/documents/components/useShareDialog.js.map +7 -0
  185. package/dist/modules/documents/backend/documents/components/useTemplateDetail.js +49 -0
  186. package/dist/modules/documents/backend/documents/components/useTemplateDetail.js.map +7 -0
  187. package/dist/modules/documents/backend/documents/components/useTemplateInstantiation.js +234 -0
  188. package/dist/modules/documents/backend/documents/components/useTemplateInstantiation.js.map +7 -0
  189. package/dist/modules/documents/backend/documents/documentUi.js +106 -0
  190. package/dist/modules/documents/backend/documents/documentUi.js.map +7 -0
  191. package/dist/modules/documents/backend/documents/documentsListTypes.js +132 -0
  192. package/dist/modules/documents/backend/documents/documentsListTypes.js.map +7 -0
  193. package/dist/modules/documents/backend/documents/page.js +9 -0
  194. package/dist/modules/documents/backend/documents/page.js.map +7 -0
  195. package/dist/modules/documents/backend/documents/page.meta.js +26 -0
  196. package/dist/modules/documents/backend/documents/page.meta.js.map +7 -0
  197. package/dist/modules/documents/backend/documents/templates/TemplatesPageClient.js +91 -0
  198. package/dist/modules/documents/backend/documents/templates/TemplatesPageClient.js.map +7 -0
  199. package/dist/modules/documents/backend/documents/templates/TemplatesTable.js +58 -0
  200. package/dist/modules/documents/backend/documents/templates/TemplatesTable.js.map +7 -0
  201. package/dist/modules/documents/backend/documents/templates/page.js +9 -0
  202. package/dist/modules/documents/backend/documents/templates/page.js.map +7 -0
  203. package/dist/modules/documents/backend/documents/templates/page.meta.js +34 -0
  204. package/dist/modules/documents/backend/documents/templates/page.meta.js.map +7 -0
  205. package/dist/modules/documents/backend/documents/templates/useTemplatesPage.js +139 -0
  206. package/dist/modules/documents/backend/documents/templates/useTemplatesPage.js.map +7 -0
  207. package/dist/modules/documents/backend/documents/useDocumentsList.js +314 -0
  208. package/dist/modules/documents/backend/documents/useDocumentsList.js.map +7 -0
  209. package/dist/modules/documents/ce.js +8 -0
  210. package/dist/modules/documents/ce.js.map +7 -0
  211. package/dist/modules/documents/commands/aggregate.js +99 -0
  212. package/dist/modules/documents/commands/aggregate.js.map +7 -0
  213. package/dist/modules/documents/commands/attachments.js +252 -0
  214. package/dist/modules/documents/commands/attachments.js.map +7 -0
  215. package/dist/modules/documents/commands/comments.js +782 -0
  216. package/dist/modules/documents/commands/comments.js.map +7 -0
  217. package/dist/modules/documents/commands/content.js +238 -0
  218. package/dist/modules/documents/commands/content.js.map +7 -0
  219. package/dist/modules/documents/commands/document-crud.js +505 -0
  220. package/dist/modules/documents/commands/document-crud.js.map +7 -0
  221. package/dist/modules/documents/commands/documents.js +473 -0
  222. package/dist/modules/documents/commands/documents.js.map +7 -0
  223. package/dist/modules/documents/commands/duplicate.js +640 -0
  224. package/dist/modules/documents/commands/duplicate.js.map +7 -0
  225. package/dist/modules/documents/commands/favorites.js +150 -0
  226. package/dist/modules/documents/commands/favorites.js.map +7 -0
  227. package/dist/modules/documents/commands/folders.js +420 -0
  228. package/dist/modules/documents/commands/folders.js.map +7 -0
  229. package/dist/modules/documents/commands/index.js +64 -0
  230. package/dist/modules/documents/commands/index.js.map +7 -0
  231. package/dist/modules/documents/commands/interceptors.js +300 -0
  232. package/dist/modules/documents/commands/interceptors.js.map +7 -0
  233. package/dist/modules/documents/commands/lifecycle.js +249 -0
  234. package/dist/modules/documents/commands/lifecycle.js.map +7 -0
  235. package/dist/modules/documents/commands/links.js +410 -0
  236. package/dist/modules/documents/commands/links.js.map +7 -0
  237. package/dist/modules/documents/commands/mutation-helpers.js +42 -0
  238. package/dist/modules/documents/commands/mutation-helpers.js.map +7 -0
  239. package/dist/modules/documents/commands/projection-types.js +1 -0
  240. package/dist/modules/documents/commands/projection-types.js.map +7 -0
  241. package/dist/modules/documents/commands/shared.js +143 -0
  242. package/dist/modules/documents/commands/shared.js.map +7 -0
  243. package/dist/modules/documents/commands/shares.js +527 -0
  244. package/dist/modules/documents/commands/shares.js.map +7 -0
  245. package/dist/modules/documents/commands/side-effects.js +103 -0
  246. package/dist/modules/documents/commands/side-effects.js.map +7 -0
  247. package/dist/modules/documents/commands/templates.js +461 -0
  248. package/dist/modules/documents/commands/templates.js.map +7 -0
  249. package/dist/modules/documents/commands/versions.js +432 -0
  250. package/dist/modules/documents/commands/versions.js.map +7 -0
  251. package/dist/modules/documents/commands/watchers.js +164 -0
  252. package/dist/modules/documents/commands/watchers.js.map +7 -0
  253. package/dist/modules/documents/data/entities.js +653 -0
  254. package/dist/modules/documents/data/entities.js.map +7 -0
  255. package/dist/modules/documents/data/extensions.js +44 -0
  256. package/dist/modules/documents/data/extensions.js.map +7 -0
  257. package/dist/modules/documents/data/validators.js +219 -0
  258. package/dist/modules/documents/data/validators.js.map +7 -0
  259. package/dist/modules/documents/di.js +35 -0
  260. package/dist/modules/documents/di.js.map +7 -0
  261. package/dist/modules/documents/encryption.js +12 -0
  262. package/dist/modules/documents/encryption.js.map +7 -0
  263. package/dist/modules/documents/events.js +27 -0
  264. package/dist/modules/documents/events.js.map +7 -0
  265. package/dist/modules/documents/index.js +19 -0
  266. package/dist/modules/documents/index.js.map +7 -0
  267. package/dist/modules/documents/lib/attachmentServicePort.js +30 -0
  268. package/dist/modules/documents/lib/attachmentServicePort.js.map +7 -0
  269. package/dist/modules/documents/lib/capabilities.js +32 -0
  270. package/dist/modules/documents/lib/capabilities.js.map +7 -0
  271. package/dist/modules/documents/lib/collabCloseEvents.js +17 -0
  272. package/dist/modules/documents/lib/collabCloseEvents.js.map +7 -0
  273. package/dist/modules/documents/lib/collabEndpoint.js +22 -0
  274. package/dist/modules/documents/lib/collabEndpoint.js.map +7 -0
  275. package/dist/modules/documents/lib/collabMaterializer.js +107 -0
  276. package/dist/modules/documents/lib/collabMaterializer.js.map +7 -0
  277. package/dist/modules/documents/lib/collabToken.js +120 -0
  278. package/dist/modules/documents/lib/collabToken.js.map +7 -0
  279. package/dist/modules/documents/lib/collaborationAwareness.js +68 -0
  280. package/dist/modules/documents/lib/collaborationAwareness.js.map +7 -0
  281. package/dist/modules/documents/lib/commentAnchors.js +15 -0
  282. package/dist/modules/documents/lib/commentAnchors.js.map +7 -0
  283. package/dist/modules/documents/lib/constants.js +25 -0
  284. package/dist/modules/documents/lib/constants.js.map +7 -0
  285. package/dist/modules/documents/lib/contentService.js +248 -0
  286. package/dist/modules/documents/lib/contentService.js.map +7 -0
  287. package/dist/modules/documents/lib/displayLabels.js +23 -0
  288. package/dist/modules/documents/lib/displayLabels.js.map +7 -0
  289. package/dist/modules/documents/lib/docxRenderer.js +601 -0
  290. package/dist/modules/documents/lib/docxRenderer.js.map +7 -0
  291. package/dist/modules/documents/lib/duplicateContent.js +22 -0
  292. package/dist/modules/documents/lib/duplicateContent.js.map +7 -0
  293. package/dist/modules/documents/lib/editorConfig.js +287 -0
  294. package/dist/modules/documents/lib/editorConfig.js.map +7 -0
  295. package/dist/modules/documents/lib/entityLinks.js +148 -0
  296. package/dist/modules/documents/lib/entityLinks.js.map +7 -0
  297. package/dist/modules/documents/lib/entityRegistry.js +258 -0
  298. package/dist/modules/documents/lib/entityRegistry.js.map +7 -0
  299. package/dist/modules/documents/lib/entityRegistry.server.js +189 -0
  300. package/dist/modules/documents/lib/entityRegistry.server.js.map +7 -0
  301. package/dist/modules/documents/lib/entityRegistryAvailability.server.js +9 -0
  302. package/dist/modules/documents/lib/entityRegistryAvailability.server.js.map +7 -0
  303. package/dist/modules/documents/lib/entitySuggestion.js +50 -0
  304. package/dist/modules/documents/lib/entitySuggestion.js.map +7 -0
  305. package/dist/modules/documents/lib/favorites.js +22 -0
  306. package/dist/modules/documents/lib/favorites.js.map +7 -0
  307. package/dist/modules/documents/lib/folderHierarchySerialization.js +19 -0
  308. package/dist/modules/documents/lib/folderHierarchySerialization.js.map +7 -0
  309. package/dist/modules/documents/lib/historyLimits.js +100 -0
  310. package/dist/modules/documents/lib/historyLimits.js.map +7 -0
  311. package/dist/modules/documents/lib/historyPolicy.js +14 -0
  312. package/dist/modules/documents/lib/historyPolicy.js.map +7 -0
  313. package/dist/modules/documents/lib/organizationAccess.js +17 -0
  314. package/dist/modules/documents/lib/organizationAccess.js.map +7 -0
  315. package/dist/modules/documents/lib/pdfHtml.js +62 -0
  316. package/dist/modules/documents/lib/pdfHtml.js.map +7 -0
  317. package/dist/modules/documents/lib/pdfRenderer.js +284 -0
  318. package/dist/modules/documents/lib/pdfRenderer.js.map +7 -0
  319. package/dist/modules/documents/lib/permissions.js +222 -0
  320. package/dist/modules/documents/lib/permissions.js.map +7 -0
  321. package/dist/modules/documents/lib/platformServices.js +35 -0
  322. package/dist/modules/documents/lib/platformServices.js.map +7 -0
  323. package/dist/modules/documents/lib/recordFieldInsertion.js +58 -0
  324. package/dist/modules/documents/lib/recordFieldInsertion.js.map +7 -0
  325. package/dist/modules/documents/lib/requestBody.js +80 -0
  326. package/dist/modules/documents/lib/requestBody.js.map +7 -0
  327. package/dist/modules/documents/lib/resourceLimits.js +62 -0
  328. package/dist/modules/documents/lib/resourceLimits.js.map +7 -0
  329. package/dist/modules/documents/lib/shareCounts.js +25 -0
  330. package/dist/modules/documents/lib/shareCounts.js.map +7 -0
  331. package/dist/modules/documents/lib/templateFill.js +84 -0
  332. package/dist/modules/documents/lib/templateFill.js.map +7 -0
  333. package/dist/modules/documents/lib/templateInstantiation.js +147 -0
  334. package/dist/modules/documents/lib/templateInstantiation.js.map +7 -0
  335. package/dist/modules/documents/lib/templatePreviewDigest.js +82 -0
  336. package/dist/modules/documents/lib/templatePreviewDigest.js.map +7 -0
  337. package/dist/modules/documents/lib/templateSeeds.js +201 -0
  338. package/dist/modules/documents/lib/templateSeeds.js.map +7 -0
  339. package/dist/modules/documents/lib/userLabels.js +37 -0
  340. package/dist/modules/documents/lib/userLabels.js.map +7 -0
  341. package/dist/modules/documents/lib/versionContent.js +131 -0
  342. package/dist/modules/documents/lib/versionContent.js.map +7 -0
  343. package/dist/modules/documents/lib/versionLabels.js +12 -0
  344. package/dist/modules/documents/lib/versionLabels.js.map +7 -0
  345. package/dist/modules/documents/lib/versioning.js +14 -0
  346. package/dist/modules/documents/lib/versioning.js.map +7 -0
  347. package/dist/modules/documents/lib/visibility.js +422 -0
  348. package/dist/modules/documents/lib/visibility.js.map +7 -0
  349. package/dist/modules/documents/lib/watchers.js +106 -0
  350. package/dist/modules/documents/lib/watchers.js.map +7 -0
  351. package/dist/modules/documents/migrations/Migration20260708163836_documents.js +44 -0
  352. package/dist/modules/documents/migrations/Migration20260708163836_documents.js.map +7 -0
  353. package/dist/modules/documents/migrations/Migration20260709164720_documents.js +17 -0
  354. package/dist/modules/documents/migrations/Migration20260709164720_documents.js.map +7 -0
  355. package/dist/modules/documents/migrations/Migration20260710002318_documents.js +32 -0
  356. package/dist/modules/documents/migrations/Migration20260710002318_documents.js.map +7 -0
  357. package/dist/modules/documents/migrations/Migration20260710071003_documents.js +13 -0
  358. package/dist/modules/documents/migrations/Migration20260710071003_documents.js.map +7 -0
  359. package/dist/modules/documents/migrations/Migration20260712120000_documents.js +13 -0
  360. package/dist/modules/documents/migrations/Migration20260712120000_documents.js.map +7 -0
  361. package/dist/modules/documents/migrations/Migration20260712183000_documents.js +14 -0
  362. package/dist/modules/documents/migrations/Migration20260712183000_documents.js.map +7 -0
  363. package/dist/modules/documents/migrations/Migration20260713092156_documents.js +29 -0
  364. package/dist/modules/documents/migrations/Migration20260713092156_documents.js.map +7 -0
  365. package/dist/modules/documents/migrations/Migration20260717000000_documents.js +37 -0
  366. package/dist/modules/documents/migrations/Migration20260717000000_documents.js.map +7 -0
  367. package/dist/modules/documents/notifications.js +47 -0
  368. package/dist/modules/documents/notifications.js.map +7 -0
  369. package/dist/modules/documents/search.js +101 -0
  370. package/dist/modules/documents/search.js.map +7 -0
  371. package/dist/modules/documents/setup.js +19 -0
  372. package/dist/modules/documents/setup.js.map +7 -0
  373. package/dist/modules/documents/widgets/injection/related-documents/LinkDocumentDialog.js +214 -0
  374. package/dist/modules/documents/widgets/injection/related-documents/LinkDocumentDialog.js.map +7 -0
  375. package/dist/modules/documents/widgets/injection/related-documents/context.js +84 -0
  376. package/dist/modules/documents/widgets/injection/related-documents/context.js.map +7 -0
  377. package/dist/modules/documents/widgets/injection/related-documents/useRelatedDocuments.js +98 -0
  378. package/dist/modules/documents/widgets/injection/related-documents/useRelatedDocuments.js.map +7 -0
  379. package/dist/modules/documents/widgets/injection/related-documents/widget.client.js +83 -0
  380. package/dist/modules/documents/widgets/injection/related-documents/widget.client.js.map +7 -0
  381. package/dist/modules/documents/widgets/injection/related-documents/widget.js +19 -0
  382. package/dist/modules/documents/widgets/injection/related-documents/widget.js.map +7 -0
  383. package/dist/modules/documents/widgets/injection-table.js +21 -0
  384. package/dist/modules/documents/widgets/injection-table.js.map +7 -0
  385. package/dist/server/documents-collab-server.js +2260 -0
  386. package/dist/server/documents-collab-server.js.map +7 -0
  387. package/generated/entities/document/index.ts +12 -0
  388. package/generated/entities/document_attachment/index.ts +9 -0
  389. package/generated/entities/document_comment/index.ts +14 -0
  390. package/generated/entities/document_content/index.ts +11 -0
  391. package/generated/entities/document_entity_link/index.ts +19 -0
  392. package/generated/entities/document_favorite/index.ts +7 -0
  393. package/generated/entities/document_folder/index.ts +9 -0
  394. package/generated/entities/document_share/index.ts +11 -0
  395. package/generated/entities/document_template/index.ts +13 -0
  396. package/generated/entities/document_version/index.ts +9 -0
  397. package/generated/entities/document_watcher/index.ts +7 -0
  398. package/generated/entities.ids.generated.ts +21 -0
  399. package/generated/entity-fields-registry.ts +151 -0
  400. package/jest.config.cjs +34 -0
  401. package/package.json +149 -0
  402. package/server/documents-collab-server.ts +3416 -0
  403. package/src/index.ts +1 -0
  404. package/src/modules/documents/acl.ts +11 -0
  405. package/src/modules/documents/api/[id]/archive/route.ts +132 -0
  406. package/src/modules/documents/api/[id]/attachments/[attachmentId]/route.ts +166 -0
  407. package/src/modules/documents/api/[id]/attachments/route.ts +173 -0
  408. package/src/modules/documents/api/[id]/collab-token/route.ts +203 -0
  409. package/src/modules/documents/api/[id]/comments/access-check/route.ts +96 -0
  410. package/src/modules/documents/api/[id]/comments/route.ts +442 -0
  411. package/src/modules/documents/api/[id]/content/route.ts +156 -0
  412. package/src/modules/documents/api/[id]/duplicate/route.ts +231 -0
  413. package/src/modules/documents/api/[id]/export/route.ts +535 -0
  414. package/src/modules/documents/api/[id]/favorite/route.ts +110 -0
  415. package/src/modules/documents/api/[id]/links/[linkId]/route.ts +92 -0
  416. package/src/modules/documents/api/[id]/links/route.ts +301 -0
  417. package/src/modules/documents/api/[id]/principals/route.ts +375 -0
  418. package/src/modules/documents/api/[id]/route.ts +267 -0
  419. package/src/modules/documents/api/[id]/shares/route.ts +372 -0
  420. package/src/modules/documents/api/[id]/unarchive/route.ts +42 -0
  421. package/src/modules/documents/api/[id]/versions/[versionId]/restore/route.ts +152 -0
  422. package/src/modules/documents/api/[id]/versions/[versionId]/route.ts +100 -0
  423. package/src/modules/documents/api/[id]/versions/route.ts +207 -0
  424. package/src/modules/documents/api/[id]/watch/route.ts +111 -0
  425. package/src/modules/documents/api/_commands.ts +53 -0
  426. package/src/modules/documents/api/_shared.ts +676 -0
  427. package/src/modules/documents/api/folders/route.ts +287 -0
  428. package/src/modules/documents/api/instantiate/route.ts +114 -0
  429. package/src/modules/documents/api/route.ts +362 -0
  430. package/src/modules/documents/api/templates/[templateId]/preview/route.ts +97 -0
  431. package/src/modules/documents/api/templates/[templateId]/route.ts +92 -0
  432. package/src/modules/documents/api/templates/route.ts +370 -0
  433. package/src/modules/documents/backend/documents/DocumentsPageClient.tsx +150 -0
  434. package/src/modules/documents/backend/documents/DocumentsTable.tsx +168 -0
  435. package/src/modules/documents/backend/documents/FolderDialog.tsx +62 -0
  436. package/src/modules/documents/backend/documents/FolderTree.tsx +72 -0
  437. package/src/modules/documents/backend/documents/MoveDocumentDialog.tsx +70 -0
  438. package/src/modules/documents/backend/documents/[id]/CommentAnchorNavigation.ts +88 -0
  439. package/src/modules/documents/backend/documents/[id]/CommentComposer.tsx +136 -0
  440. package/src/modules/documents/backend/documents/[id]/CommentThreadList.tsx +131 -0
  441. package/src/modules/documents/backend/documents/[id]/CommentsRail.tsx +138 -0
  442. package/src/modules/documents/backend/documents/[id]/DocumentCanvas.tsx +111 -0
  443. package/src/modules/documents/backend/documents/[id]/DocumentEditorErrorBoundary.tsx +39 -0
  444. package/src/modules/documents/backend/documents/[id]/DocumentEditorIsland.tsx +50 -0
  445. package/src/modules/documents/backend/documents/[id]/DocumentEditorSurface.tsx +162 -0
  446. package/src/modules/documents/backend/documents/[id]/DocumentNavigator.tsx +129 -0
  447. package/src/modules/documents/backend/documents/[id]/DocumentPageClient.tsx +463 -0
  448. package/src/modules/documents/backend/documents/[id]/EditorColorTools.tsx +71 -0
  449. package/src/modules/documents/backend/documents/[id]/EditorStatusPresence.tsx +78 -0
  450. package/src/modules/documents/backend/documents/[id]/EditorToolbar.tsx +108 -0
  451. package/src/modules/documents/backend/documents/[id]/ExportMenu.tsx +144 -0
  452. package/src/modules/documents/backend/documents/[id]/MentionPicker.tsx +137 -0
  453. package/src/modules/documents/backend/documents/[id]/OutlinePane.tsx +98 -0
  454. package/src/modules/documents/backend/documents/[id]/RecordFieldsDialog.tsx +185 -0
  455. package/src/modules/documents/backend/documents/[id]/RelatedRecordsPanel.tsx +320 -0
  456. package/src/modules/documents/backend/documents/[id]/VersionHistoryPanel.tsx +244 -0
  457. package/src/modules/documents/backend/documents/[id]/VersionPreviewDialog.tsx +197 -0
  458. package/src/modules/documents/backend/documents/[id]/commentTypes.ts +192 -0
  459. package/src/modules/documents/backend/documents/[id]/componentCapabilities.ts +17 -0
  460. package/src/modules/documents/backend/documents/[id]/documentPagination.ts +352 -0
  461. package/src/modules/documents/backend/documents/[id]/editorPresenceStyles.ts +77 -0
  462. package/src/modules/documents/backend/documents/[id]/editorTypes.ts +84 -0
  463. package/src/modules/documents/backend/documents/[id]/page.meta.ts +12 -0
  464. package/src/modules/documents/backend/documents/[id]/page.tsx +6 -0
  465. package/src/modules/documents/backend/documents/[id]/relatedRecordModel.ts +49 -0
  466. package/src/modules/documents/backend/documents/[id]/restoreVersion.ts +49 -0
  467. package/src/modules/documents/backend/documents/[id]/useDocumentCollaboration.ts +458 -0
  468. package/src/modules/documents/backend/documents/[id]/useDocumentComments.ts +286 -0
  469. package/src/modules/documents/backend/documents/[id]/useDocumentEditor.ts +157 -0
  470. package/src/modules/documents/backend/documents/[id]/useDocumentTitle.ts +77 -0
  471. package/src/modules/documents/backend/documents/[id]/useEditorInsertions.ts +147 -0
  472. package/src/modules/documents/backend/documents/[id]/useFallbackContentPersistence.ts +277 -0
  473. package/src/modules/documents/backend/documents/[id]/useMentionPicker.ts +259 -0
  474. package/src/modules/documents/backend/documents/[id]/versionHistoryModel.ts +29 -0
  475. package/src/modules/documents/backend/documents/components/EntityPicker.tsx +171 -0
  476. package/src/modules/documents/backend/documents/components/EntityPickerResults.tsx +64 -0
  477. package/src/modules/documents/backend/documents/components/NewFromTemplateDialog.tsx +136 -0
  478. package/src/modules/documents/backend/documents/components/PrincipalPicker.tsx +90 -0
  479. package/src/modules/documents/backend/documents/components/ShareDialog.tsx +88 -0
  480. package/src/modules/documents/backend/documents/components/ShareDialogAddForm.tsx +113 -0
  481. package/src/modules/documents/backend/documents/components/ShareDialogList.tsx +117 -0
  482. package/src/modules/documents/backend/documents/components/TemplateBodyEditor.tsx +96 -0
  483. package/src/modules/documents/backend/documents/components/TemplateEditorDialog.tsx +171 -0
  484. package/src/modules/documents/backend/documents/components/TemplatePreview.tsx +43 -0
  485. package/src/modules/documents/backend/documents/components/TemplateSlotFields.tsx +72 -0
  486. package/src/modules/documents/backend/documents/components/TemplateSlotsEditor.tsx +72 -0
  487. package/src/modules/documents/backend/documents/components/principalPickerModel.ts +86 -0
  488. package/src/modules/documents/backend/documents/components/shareDialogModel.ts +94 -0
  489. package/src/modules/documents/backend/documents/components/templateUi.ts +128 -0
  490. package/src/modules/documents/backend/documents/components/useAvailableEntityRegistry.ts +43 -0
  491. package/src/modules/documents/backend/documents/components/useEntitySearch.ts +197 -0
  492. package/src/modules/documents/backend/documents/components/usePrincipalPicker.ts +165 -0
  493. package/src/modules/documents/backend/documents/components/useShareDialog.ts +267 -0
  494. package/src/modules/documents/backend/documents/components/useTemplateDetail.ts +54 -0
  495. package/src/modules/documents/backend/documents/components/useTemplateInstantiation.ts +252 -0
  496. package/src/modules/documents/backend/documents/documentUi.ts +134 -0
  497. package/src/modules/documents/backend/documents/documentsListTypes.ts +163 -0
  498. package/src/modules/documents/backend/documents/page.meta.ts +24 -0
  499. package/src/modules/documents/backend/documents/page.tsx +5 -0
  500. package/src/modules/documents/backend/documents/templates/TemplatesPageClient.tsx +93 -0
  501. package/src/modules/documents/backend/documents/templates/TemplatesTable.tsx +71 -0
  502. package/src/modules/documents/backend/documents/templates/page.meta.ts +32 -0
  503. package/src/modules/documents/backend/documents/templates/page.tsx +5 -0
  504. package/src/modules/documents/backend/documents/templates/useTemplatesPage.tsx +148 -0
  505. package/src/modules/documents/backend/documents/useDocumentsList.tsx +305 -0
  506. package/src/modules/documents/ce.ts +6 -0
  507. package/src/modules/documents/commands/aggregate.ts +128 -0
  508. package/src/modules/documents/commands/attachments.ts +309 -0
  509. package/src/modules/documents/commands/comments.ts +966 -0
  510. package/src/modules/documents/commands/content.ts +294 -0
  511. package/src/modules/documents/commands/document-crud.ts +609 -0
  512. package/src/modules/documents/commands/documents.ts +581 -0
  513. package/src/modules/documents/commands/duplicate.ts +772 -0
  514. package/src/modules/documents/commands/favorites.ts +171 -0
  515. package/src/modules/documents/commands/folders.ts +506 -0
  516. package/src/modules/documents/commands/index.ts +33 -0
  517. package/src/modules/documents/commands/interceptors.ts +402 -0
  518. package/src/modules/documents/commands/lifecycle.ts +333 -0
  519. package/src/modules/documents/commands/links.ts +486 -0
  520. package/src/modules/documents/commands/mutation-helpers.ts +48 -0
  521. package/src/modules/documents/commands/projection-types.ts +77 -0
  522. package/src/modules/documents/commands/shared.ts +219 -0
  523. package/src/modules/documents/commands/shares.ts +612 -0
  524. package/src/modules/documents/commands/side-effects.ts +130 -0
  525. package/src/modules/documents/commands/templates.ts +522 -0
  526. package/src/modules/documents/commands/versions.ts +537 -0
  527. package/src/modules/documents/commands/watchers.ts +181 -0
  528. package/src/modules/documents/data/entities.ts +631 -0
  529. package/src/modules/documents/data/extensions.ts +42 -0
  530. package/src/modules/documents/data/validators.ts +248 -0
  531. package/src/modules/documents/di.ts +33 -0
  532. package/src/modules/documents/encryption.ts +14 -0
  533. package/src/modules/documents/events.ts +23 -0
  534. package/src/modules/documents/i18n/.hardcoded-allowlist.json +9 -0
  535. package/src/modules/documents/i18n/de.json +522 -0
  536. package/src/modules/documents/i18n/en.json +522 -0
  537. package/src/modules/documents/i18n/es.json +522 -0
  538. package/src/modules/documents/i18n/ko.json +522 -0
  539. package/src/modules/documents/i18n/pl.json +522 -0
  540. package/src/modules/documents/index.ts +17 -0
  541. package/src/modules/documents/lib/attachmentServicePort.ts +94 -0
  542. package/src/modules/documents/lib/capabilities.ts +57 -0
  543. package/src/modules/documents/lib/collabCloseEvents.ts +26 -0
  544. package/src/modules/documents/lib/collabEndpoint.ts +43 -0
  545. package/src/modules/documents/lib/collabMaterializer.ts +140 -0
  546. package/src/modules/documents/lib/collabToken.ts +170 -0
  547. package/src/modules/documents/lib/collaborationAwareness.ts +102 -0
  548. package/src/modules/documents/lib/commentAnchors.ts +19 -0
  549. package/src/modules/documents/lib/constants.ts +39 -0
  550. package/src/modules/documents/lib/contentService.ts +340 -0
  551. package/src/modules/documents/lib/displayLabels.ts +31 -0
  552. package/src/modules/documents/lib/docxRenderer.ts +685 -0
  553. package/src/modules/documents/lib/duplicateContent.ts +32 -0
  554. package/src/modules/documents/lib/editorConfig.ts +371 -0
  555. package/src/modules/documents/lib/entityLinks.ts +250 -0
  556. package/src/modules/documents/lib/entityRegistry.server.ts +267 -0
  557. package/src/modules/documents/lib/entityRegistry.ts +345 -0
  558. package/src/modules/documents/lib/entityRegistryAvailability.server.ts +19 -0
  559. package/src/modules/documents/lib/entitySuggestion.ts +61 -0
  560. package/src/modules/documents/lib/favorites.ts +35 -0
  561. package/src/modules/documents/lib/folderHierarchySerialization.ts +34 -0
  562. package/src/modules/documents/lib/historyLimits.ts +154 -0
  563. package/src/modules/documents/lib/historyPolicy.ts +7 -0
  564. package/src/modules/documents/lib/organizationAccess.ts +44 -0
  565. package/src/modules/documents/lib/pdfHtml.ts +65 -0
  566. package/src/modules/documents/lib/pdfRenderer.ts +367 -0
  567. package/src/modules/documents/lib/permissions.ts +299 -0
  568. package/src/modules/documents/lib/platformServices.ts +70 -0
  569. package/src/modules/documents/lib/recordFieldInsertion.ts +72 -0
  570. package/src/modules/documents/lib/requestBody.ts +97 -0
  571. package/src/modules/documents/lib/resourceLimits.ts +94 -0
  572. package/src/modules/documents/lib/shareCounts.ts +44 -0
  573. package/src/modules/documents/lib/templateFill.ts +138 -0
  574. package/src/modules/documents/lib/templateInstantiation.ts +206 -0
  575. package/src/modules/documents/lib/templatePreviewDigest.ts +122 -0
  576. package/src/modules/documents/lib/templateSeeds.ts +248 -0
  577. package/src/modules/documents/lib/userLabels.ts +58 -0
  578. package/src/modules/documents/lib/versionContent.ts +163 -0
  579. package/src/modules/documents/lib/versionLabels.ts +9 -0
  580. package/src/modules/documents/lib/versioning.ts +29 -0
  581. package/src/modules/documents/lib/visibility.ts +610 -0
  582. package/src/modules/documents/lib/watchers.ts +129 -0
  583. package/src/modules/documents/migrations/.snapshot-open-mercato.json +2892 -0
  584. package/src/modules/documents/migrations/Migration20260708163836_documents.ts +50 -0
  585. package/src/modules/documents/migrations/Migration20260709164720_documents.ts +19 -0
  586. package/src/modules/documents/migrations/Migration20260710002318_documents.ts +35 -0
  587. package/src/modules/documents/migrations/Migration20260710071003_documents.ts +13 -0
  588. package/src/modules/documents/migrations/Migration20260712120000_documents.ts +13 -0
  589. package/src/modules/documents/migrations/Migration20260712183000_documents.ts +12 -0
  590. package/src/modules/documents/migrations/Migration20260713092156_documents.ts +43 -0
  591. package/src/modules/documents/migrations/Migration20260717000000_documents.ts +40 -0
  592. package/src/modules/documents/notifications.ts +45 -0
  593. package/src/modules/documents/search.ts +118 -0
  594. package/src/modules/documents/setup.ts +19 -0
  595. package/src/modules/documents/widgets/injection/related-documents/LinkDocumentDialog.tsx +224 -0
  596. package/src/modules/documents/widgets/injection/related-documents/context.ts +101 -0
  597. package/src/modules/documents/widgets/injection/related-documents/useRelatedDocuments.ts +112 -0
  598. package/src/modules/documents/widgets/injection/related-documents/widget.client.tsx +76 -0
  599. package/src/modules/documents/widgets/injection/related-documents/widget.ts +19 -0
  600. package/src/modules/documents/widgets/injection-table.ts +20 -0
  601. package/tsconfig.json +9 -0
  602. package/watch.mjs +6 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/documents/lib/entityLinks.ts"],
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { DocumentEntityLink } from '../data/entities'\nimport type {\n DocumentEntityLinkCreateInput,\n DocumentEntityType,\n} from '../data/validators'\nimport { sanitizeDocumentsDisplayLabel } from './displayLabels'\nimport { getEntityTokenFieldNames } from './entityRegistry'\nimport { DOCUMENTS_MAX_ENTITY_LINKS_PER_DOCUMENT } from './resourceLimits'\n\nexport type DocumentEntityLinkScope = {\n tenantId: string\n organizationId: string\n}\n\nexport type DocumentEntityLinkCanonicalTarget = {\n id: string\n label: string\n href: string\n values?: Record<string, string | null>\n}\n\ntype LinkTargetFields = Pick<\n DocumentEntityLink,\n | 'customerEntityId'\n | 'customerKind'\n | 'dealId'\n | 'productId'\n | 'catalogOfferId'\n | 'quoteId'\n | 'salesOrderId'\n | 'linkedDocumentId'\n>\n\nexport type DocumentEntityLinkCreateData = LinkTargetFields & {\n id: string\n documentId: string\n tenantId: string\n organizationId: string\n labelSnapshot: string\n hrefSnapshot: string\n source: DocumentEntityLinkCreateInput['source']\n createdByUserId: string\n}\n\nconst EMPTY_TARGET: LinkTargetFields = {\n customerEntityId: null,\n customerKind: null,\n dealId: null,\n productId: null,\n catalogOfferId: null,\n quoteId: null,\n salesOrderId: null,\n linkedDocumentId: null,\n}\n\nfunction sanitizeDocumentEntityValue(value: unknown): string | null {\n const label = sanitizeDocumentsDisplayLabel(value)\n return label && label.length <= 10_000 ? label : null\n}\n\nexport function buildDocumentEntityLinkTarget(\n entityType: DocumentEntityType,\n entityId: string,\n): LinkTargetFields {\n const target = { ...EMPTY_TARGET }\n if (entityType === 'customer-person' || entityType === 'customer-company') {\n target.customerEntityId = entityId\n target.customerKind = entityType === 'customer-person' ? 'person' : 'company'\n } else if (entityType === 'deal') {\n target.dealId = entityId\n } else if (entityType === 'product') {\n target.productId = entityId\n } else if (entityType === 'catalog-offer') {\n target.catalogOfferId = entityId\n } else if (entityType === 'quote') {\n target.quoteId = entityId\n } else if (entityType === 'document') {\n target.linkedDocumentId = entityId\n } else {\n target.salesOrderId = entityId\n }\n return target\n}\n\nexport function buildDocumentEntityLinkTargetWhere(\n entityType: DocumentEntityType,\n entityId: string,\n): LinkTargetFields {\n return buildDocumentEntityLinkTarget(entityType, entityId)\n}\n\nexport function getDocumentEntityLinkType(link: DocumentEntityLink): DocumentEntityType {\n if (link.customerEntityId) {\n return link.customerKind === 'company' ? 'customer-company' : 'customer-person'\n }\n if (link.dealId) return 'deal'\n if (link.productId) return 'product'\n if (link.catalogOfferId) return 'catalog-offer'\n if (link.quoteId) return 'quote'\n if (link.linkedDocumentId) return 'document'\n return 'sales-order'\n}\n\nexport function getDocumentEntityLinkEntityId(link: DocumentEntityLink): string {\n return link.customerEntityId\n ?? link.dealId\n ?? link.productId\n ?? link.catalogOfferId\n ?? link.quoteId\n ?? link.linkedDocumentId\n ?? link.salesOrderId\n ?? ''\n}\n\nexport function createDocumentEntityLinkData(input: {\n id: string\n documentId: string\n scope: DocumentEntityLinkScope\n actorUserId: string\n link: DocumentEntityLinkCreateInput\n}): DocumentEntityLinkCreateData {\n const labelSnapshot = sanitizeDocumentsDisplayLabel(input.link.label)\n if (!labelSnapshot) {\n throw new Error('[internal] document entity link label crossed persistence without a readable label')\n }\n return {\n id: input.id,\n documentId: input.documentId,\n tenantId: input.scope.tenantId,\n organizationId: input.scope.organizationId,\n labelSnapshot,\n hrefSnapshot: input.link.href,\n source: input.link.source,\n createdByUserId: input.actorUserId,\n ...buildDocumentEntityLinkTarget(input.link.entityType, input.link.entityId),\n }\n}\n\nexport async function findDocumentEntityLinks(\n em: EntityManager,\n documentId: string,\n scope: DocumentEntityLinkScope,\n options: { withDeleted?: boolean } = {},\n): Promise<DocumentEntityLink[]> {\n const links = await findWithDecryption(\n em,\n DocumentEntityLink,\n {\n documentId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n ...(options.withDeleted ? {} : { deletedAt: null }),\n },\n options.withDeleted\n ? { orderBy: { createdAt: 'ASC' } }\n : {\n orderBy: { createdAt: 'ASC' },\n limit: DOCUMENTS_MAX_ENTITY_LINKS_PER_DOCUMENT + 1,\n },\n scope,\n )\n if (!options.withDeleted) assertDocumentEntityLinkListWithinLimit(links)\n return links\n}\n\nexport function assertDocumentEntityLinkListWithinLimit(\n links: readonly DocumentEntityLink[],\n): void {\n if (links.length <= DOCUMENTS_MAX_ENTITY_LINKS_PER_DOCUMENT) return\n throw new CrudHttpError(413, { error: 'documents.links.limitExceeded' })\n}\n\n/** Call only while holding the document aggregate lock. */\nexport async function assertDocumentEntityLinkCapacity(\n em: EntityManager,\n documentId: string,\n scope: DocumentEntityLinkScope,\n): Promise<void> {\n const activeCount = await em.count(DocumentEntityLink, {\n documentId,\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n })\n if (activeCount < DOCUMENTS_MAX_ENTITY_LINKS_PER_DOCUMENT) return\n throw new CrudHttpError(413, { error: 'documents.links.limitExceeded' })\n}\n\nexport function serializeDocumentEntityLink(\n link: DocumentEntityLink,\n options: {\n canOpen: boolean\n restrictedLabel: string\n canonicalTarget?: DocumentEntityLinkCanonicalTarget\n },\n): {\n id: string\n entityType: DocumentEntityType\n entityId: string | null\n label: string\n href: string | null\n canOpen: boolean\n source: string\n createdAt: string\n updatedAt: string\n values?: Record<string, string | null>\n} {\n const entityType = getDocumentEntityLinkType(link)\n const restrictedLabel = sanitizeDocumentsDisplayLabel(options.restrictedLabel)\n const canonicalLabel = options.canonicalTarget\n ? sanitizeDocumentsDisplayLabel(options.canonicalTarget.label)\n : null\n const snapshotLabel = sanitizeDocumentsDisplayLabel(link.labelSnapshot)\n const canOpen = options.canOpen && (\n options.canonicalTarget ? Boolean(canonicalLabel) : Boolean(snapshotLabel)\n )\n const readableLabel = canOpen ? canonicalLabel ?? snapshotLabel : restrictedLabel\n if (!readableLabel) {\n throw new Error('[internal] document entity link serialization requires a readable fallback label')\n }\n const allowedValueFields = getEntityTokenFieldNames(entityType)\n const values = options.canonicalTarget?.values\n ? Object.fromEntries(Array.from(allowedValueFields, (field) => [\n field,\n sanitizeDocumentEntityValue(options.canonicalTarget?.values?.[field]),\n ]))\n : null\n const hasReadableValues = values\n ? Object.values(values).some((value) => value !== null)\n : false\n return {\n id: link.id,\n entityType,\n entityId: canOpen\n ? options.canonicalTarget?.id ?? getDocumentEntityLinkEntityId(link)\n : null,\n label: canOpen ? readableLabel : restrictedLabel ?? readableLabel,\n href: canOpen\n ? options.canonicalTarget?.href ?? link.hrefSnapshot\n : null,\n canOpen,\n source: link.source,\n createdAt: link.createdAt.toISOString(),\n updatedAt: link.updatedAt.toISOString(),\n ...(canOpen && hasReadableValues && values ? { values } : {}),\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,258 @@
1
+ import {
2
+ firstSafeDocumentsDisplayLabel,
3
+ sanitizeDocumentsDisplayLabel
4
+ } from "./displayLabels.js";
5
+ function readRecord(value) {
6
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
7
+ }
8
+ function readString(item, ...keys) {
9
+ for (const key of keys) {
10
+ const value = item[key];
11
+ if (typeof value === "string" && value.trim().length > 0) return value.trim();
12
+ }
13
+ return null;
14
+ }
15
+ function readDisplayString(item, ...keys) {
16
+ return firstSafeDocumentsDisplayLabel(...keys.map((key) => item[key]));
17
+ }
18
+ function readNestedString(item, parentKey, ...keys) {
19
+ const parent = readRecord(item[parentKey]);
20
+ return parent ? readString(parent, ...keys) : null;
21
+ }
22
+ function readNestedDisplayString(item, parentKey, ...keys) {
23
+ const parent = readRecord(item[parentKey]);
24
+ return parent ? readDisplayString(parent, ...keys) : null;
25
+ }
26
+ function readDisplayTextValue(item, ...keys) {
27
+ for (const key of keys) {
28
+ const value = item[key];
29
+ const safe = typeof value === "number" && Number.isFinite(value) ? sanitizeDocumentsDisplayLabel(String(value)) : sanitizeDocumentsDisplayLabel(value);
30
+ if (safe) return safe;
31
+ }
32
+ return null;
33
+ }
34
+ function optionalSubtitle(value) {
35
+ return value ?? void 0;
36
+ }
37
+ function mapCustomerItem(item) {
38
+ const id = readString(item, "id");
39
+ const email = readDisplayString(item, "email", "primaryEmail", "primary_email");
40
+ const label = readDisplayString(item, "name", "displayName", "display_name") ?? email;
41
+ if (!id || !label) return null;
42
+ return { id, label, subtitle: optionalSubtitle(email) };
43
+ }
44
+ function mapDealItem(item) {
45
+ const id = readString(item, "id");
46
+ const label = readDisplayString(item, "title");
47
+ if (!id || !label) return null;
48
+ return { id, label, subtitle: optionalSubtitle(readDisplayString(item, "status")) };
49
+ }
50
+ function mapProductItem(item) {
51
+ const id = readString(item, "id");
52
+ const label = readDisplayString(item, "title");
53
+ if (!id || !label) return null;
54
+ return { id, label, subtitle: optionalSubtitle(readDisplayString(item, "sku")) };
55
+ }
56
+ function mapCatalogOfferItem(item) {
57
+ const id = readString(item, "id");
58
+ const productId = readString(item, "productId", "product_id") ?? readNestedString(item, "product", "id");
59
+ const productTitle = readNestedDisplayString(item, "product", "title", "name");
60
+ const label = readDisplayString(item, "title", "name") ?? productTitle;
61
+ if (!id || !productId || !label) return null;
62
+ const productSku = readNestedDisplayString(item, "product", "sku");
63
+ return {
64
+ id,
65
+ label,
66
+ subtitle: optionalSubtitle(productTitle ?? productSku),
67
+ href: `/backend/catalog/products/${productId}`
68
+ };
69
+ }
70
+ function mapSalesDocumentItem(item, numberKeys) {
71
+ const id = readString(item, "id");
72
+ const label = readDisplayString(item, ...numberKeys, "number", "title");
73
+ if (!id || !label) return null;
74
+ return { id, label, subtitle: optionalSubtitle(readDisplayString(item, "status")) };
75
+ }
76
+ function mapDocumentItem(item) {
77
+ const id = readString(item, "id");
78
+ const label = readDisplayString(item, "title");
79
+ if (!id || !label) return null;
80
+ const archivedAt = item.archivedAt ?? item.archived_at;
81
+ return {
82
+ id,
83
+ label,
84
+ archivedAt: typeof archivedAt === "string" && archivedAt.length > 0 ? archivedAt : null
85
+ };
86
+ }
87
+ function field(fieldName, labelKey, keys) {
88
+ return {
89
+ field: fieldName,
90
+ labelKey,
91
+ extract: (item) => readDisplayTextValue(item, ...keys)
92
+ };
93
+ }
94
+ function exactIdPath(pathPrefix, id) {
95
+ return `${pathPrefix}/${id}`;
96
+ }
97
+ const CATALOG_PRODUCT_HREF_PATTERN = /^\/backend\/catalog\/products\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
98
+ function buildIdAddressableEntry(input) {
99
+ return {
100
+ ...input,
101
+ resolveHref: (item) => input.href(item.id),
102
+ isCanonicalHref: (item, href) => href === input.href(item.id)
103
+ };
104
+ }
105
+ function readItemsArray(response) {
106
+ if (Array.isArray(response)) {
107
+ return response.map(readRecord).filter((item) => item !== null);
108
+ }
109
+ const record = readRecord(response);
110
+ const candidates = [record?.items, record?.data];
111
+ for (const candidate of candidates) {
112
+ if (Array.isArray(candidate)) {
113
+ return candidate.map(readRecord).filter((item) => item !== null);
114
+ }
115
+ }
116
+ return [];
117
+ }
118
+ const DOCUMENT_ENTITY_REGISTRY = [
119
+ buildIdAddressableEntry({
120
+ type: "customer-person",
121
+ labelKey: "documents.entities.customerPerson",
122
+ searchPath: "/api/customers/people",
123
+ mapItem: mapCustomerItem,
124
+ href: (id) => exactIdPath("/backend/customers/people", id),
125
+ requiredModule: "customers",
126
+ requiredFeatureModule: "customers",
127
+ requiredFeature: "customers.people.view",
128
+ tokenFields: [
129
+ field("name", "documents.entityFields.name", ["name", "displayName", "display_name"]),
130
+ field("email", "documents.entityFields.email", ["email", "primaryEmail", "primary_email"]),
131
+ field("phone", "documents.entityFields.phone", ["phone", "primaryPhone", "primary_phone"])
132
+ ]
133
+ }),
134
+ buildIdAddressableEntry({
135
+ type: "customer-company",
136
+ labelKey: "documents.entities.customerCompany",
137
+ searchPath: "/api/customers/companies",
138
+ mapItem: mapCustomerItem,
139
+ href: (id) => exactIdPath("/backend/customers/companies", id),
140
+ requiredModule: "customers",
141
+ requiredFeatureModule: "customers",
142
+ requiredFeature: "customers.companies.view",
143
+ tokenFields: [
144
+ field("name", "documents.entityFields.name", ["name", "displayName", "display_name"]),
145
+ field("email", "documents.entityFields.email", ["email", "primaryEmail", "primary_email"]),
146
+ field("phone", "documents.entityFields.phone", ["phone", "primaryPhone", "primary_phone"])
147
+ ]
148
+ }),
149
+ buildIdAddressableEntry({
150
+ type: "deal",
151
+ labelKey: "documents.entities.deal",
152
+ searchPath: "/api/customers/deals",
153
+ mapItem: mapDealItem,
154
+ href: (id) => exactIdPath("/backend/customers/deals", id),
155
+ requiredModule: "customers",
156
+ requiredFeatureModule: "customers",
157
+ requiredFeature: "customers.deals.view",
158
+ tokenFields: [
159
+ field("title", "documents.entityFields.title", ["title"]),
160
+ field("status", "documents.entityFields.status", ["status"]),
161
+ field("value", "documents.entityFields.value", ["value", "valueAmount", "value_amount"]),
162
+ field("valueCurrency", "documents.entityFields.valueCurrency", ["valueCurrency", "value_currency"])
163
+ ]
164
+ }),
165
+ buildIdAddressableEntry({
166
+ type: "product",
167
+ labelKey: "documents.entities.product",
168
+ searchPath: "/api/catalog/products",
169
+ mapItem: mapProductItem,
170
+ href: (id) => exactIdPath("/backend/catalog/products", id),
171
+ requiredModule: "catalog",
172
+ requiredFeatureModule: "catalog",
173
+ requiredFeature: "catalog.products.view",
174
+ tokenFields: [
175
+ field("title", "documents.entityFields.title", ["title"]),
176
+ field("subtitle", "documents.entityFields.subtitle", ["subtitle"]),
177
+ field("sku", "documents.entityFields.sku", ["sku"])
178
+ ]
179
+ }),
180
+ {
181
+ type: "catalog-offer",
182
+ labelKey: "documents.entities.catalogOffer",
183
+ searchPath: "/api/catalog/offers",
184
+ mapItem: mapCatalogOfferItem,
185
+ href: () => "",
186
+ resolveHref: (item) => {
187
+ const href = item.href ?? null;
188
+ return href && CATALOG_PRODUCT_HREF_PATTERN.test(href) ? href : null;
189
+ },
190
+ isCanonicalHref: (item, href) => Boolean(item.href && href === item.href && CATALOG_PRODUCT_HREF_PATTERN.test(href)),
191
+ requiredModule: "catalog",
192
+ requiredFeatureModule: "sales",
193
+ requiredFeature: "sales.channels.manage",
194
+ tokenFields: [
195
+ field("title", "documents.entityFields.title", ["title", "name"]),
196
+ field("description", "documents.entityFields.description", ["description"])
197
+ ]
198
+ },
199
+ buildIdAddressableEntry({
200
+ type: "quote",
201
+ labelKey: "documents.entities.quote",
202
+ searchPath: "/api/sales/quotes",
203
+ mapItem: (item) => mapSalesDocumentItem(item, ["quoteNumber", "quote_number"]),
204
+ href: (id) => exactIdPath("/backend/sales/quotes", id),
205
+ requiredModule: "sales",
206
+ requiredFeatureModule: "sales",
207
+ requiredFeature: "sales.quotes.view",
208
+ tokenFields: [
209
+ field("number", "documents.entityFields.number", ["quoteNumber", "quote_number", "number"]),
210
+ field("status", "documents.entityFields.status", ["status"]),
211
+ field("total", "documents.entityFields.total", ["grandTotalGross", "grand_total_gross", "total"]),
212
+ field("currency", "documents.entityFields.currency", ["currencyCode", "currency_code"])
213
+ ]
214
+ }),
215
+ buildIdAddressableEntry({
216
+ type: "sales-order",
217
+ labelKey: "documents.entities.salesOrder",
218
+ searchPath: "/api/sales/orders",
219
+ mapItem: (item) => mapSalesDocumentItem(item, ["orderNumber", "order_number"]),
220
+ href: (id) => exactIdPath("/backend/sales/orders", id),
221
+ requiredModule: "sales",
222
+ requiredFeatureModule: "sales",
223
+ requiredFeature: "sales.orders.view",
224
+ tokenFields: [
225
+ field("number", "documents.entityFields.number", ["orderNumber", "order_number", "number"]),
226
+ field("status", "documents.entityFields.status", ["status"]),
227
+ field("total", "documents.entityFields.total", ["grandTotalGross", "grand_total_gross", "total"]),
228
+ field("currency", "documents.entityFields.currency", ["currencyCode", "currency_code"])
229
+ ]
230
+ }),
231
+ buildIdAddressableEntry({
232
+ type: "document",
233
+ labelKey: "documents.entities.document",
234
+ searchPath: "/api/documents",
235
+ mapItem: mapDocumentItem,
236
+ href: (id) => exactIdPath("/backend/documents", id),
237
+ requiredModule: "documents",
238
+ requiredFeatureModule: "documents",
239
+ requiredFeature: "documents.view",
240
+ tokenFields: [
241
+ field("title", "documents.entityFields.title", ["title"])
242
+ ]
243
+ })
244
+ ];
245
+ function getEntityRegistryEntry(type) {
246
+ return DOCUMENT_ENTITY_REGISTRY.find((entry) => entry.type === type) ?? null;
247
+ }
248
+ function getEntityTokenFieldNames(type) {
249
+ const entry = getEntityRegistryEntry(type);
250
+ return new Set(entry?.tokenFields.map((tokenField) => tokenField.field) ?? []);
251
+ }
252
+ export {
253
+ DOCUMENT_ENTITY_REGISTRY,
254
+ getEntityRegistryEntry,
255
+ getEntityTokenFieldNames,
256
+ readItemsArray
257
+ };
258
+ //# sourceMappingURL=entityRegistry.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/documents/lib/entityRegistry.ts"],
4
+ "sourcesContent": ["import type { DocumentEntityType } from '../data/validators'\nimport {\n firstSafeDocumentsDisplayLabel,\n sanitizeDocumentsDisplayLabel,\n} from './displayLabels'\n\nexport type { DocumentEntityType } from '../data/validators'\n\nexport type EntityPickerItem = {\n id: string\n label: string\n subtitle?: string\n href?: string\n archivedAt?: string | null\n}\n\nexport type EntityTokenField = {\n field: string\n labelKey: string\n extract: (item: Record<string, unknown>) => string | null\n}\n\nexport type EntityRegistryEntry = {\n type: DocumentEntityType\n labelKey: string\n searchPath: string\n mapItem: (item: Record<string, unknown>) => EntityPickerItem | null\n href: (id: string) => string\n tokenFields: EntityTokenField[]\n}\n\n/**\n * Internal registry contract used by Documents integrations. Keep the\n * long-standing EntityRegistryEntry shape above assignable for deep-import\n * consumers while requiring every built-in entry to declare its capability\n * and canonical-link policy.\n */\nexport type DocumentEntityRegistryEntry = EntityRegistryEntry & {\n resolveHref: (item: EntityPickerItem) => string | null\n isCanonicalHref: (item: Pick<EntityPickerItem, 'id' | 'href'>, href: string) => boolean\n requiredModule: string\n /**\n * Module that owns `requiredFeature`. This is usually the same as\n * `requiredModule`, but catalog offers are rendered by Catalog while their\n * channel-access feature is owned by Sales. Keeping it explicit lets the\n * server and ClientBootstrap-backed picker make the same fail-closed choice.\n */\n requiredFeatureModule: string\n requiredFeature: string\n}\n\nfunction readRecord(value: unknown): Record<string, unknown> | null {\n return value && typeof value === 'object' && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null\n}\n\nfunction readString(item: Record<string, unknown>, ...keys: string[]): string | null {\n for (const key of keys) {\n const value = item[key]\n if (typeof value === 'string' && value.trim().length > 0) return value.trim()\n }\n return null\n}\n\n/**\n * Cross-module records are an untrusted display boundary. Their identifiers\n * remain available to the registry for canonical routing, but a name, status,\n * SKU, or other rendered value must never fall back to an identifier-shaped\n * string. Continue through aliases so a malformed preferred field does not\n * hide a later readable value.\n */\nfunction readDisplayString(item: Record<string, unknown>, ...keys: string[]): string | null {\n return firstSafeDocumentsDisplayLabel(...keys.map((key) => item[key]))\n}\n\nfunction readNestedString(\n item: Record<string, unknown>,\n parentKey: string,\n ...keys: string[]\n): string | null {\n const parent = readRecord(item[parentKey])\n return parent ? readString(parent, ...keys) : null\n}\n\nfunction readNestedDisplayString(\n item: Record<string, unknown>,\n parentKey: string,\n ...keys: string[]\n): string | null {\n const parent = readRecord(item[parentKey])\n return parent ? readDisplayString(parent, ...keys) : null\n}\n\nfunction readDisplayTextValue(item: Record<string, unknown>, ...keys: string[]): string | null {\n for (const key of keys) {\n const value = item[key]\n const safe = typeof value === 'number' && Number.isFinite(value)\n ? sanitizeDocumentsDisplayLabel(String(value))\n : sanitizeDocumentsDisplayLabel(value)\n if (safe) return safe\n }\n return null\n}\n\nfunction optionalSubtitle(value: string | null): string | undefined {\n return value ?? undefined\n}\n\nfunction mapCustomerItem(item: Record<string, unknown>): EntityPickerItem | null {\n const id = readString(item, 'id')\n const email = readDisplayString(item, 'email', 'primaryEmail', 'primary_email')\n const label = readDisplayString(item, 'name', 'displayName', 'display_name') ?? email\n if (!id || !label) return null\n return { id, label, subtitle: optionalSubtitle(email) }\n}\n\nfunction mapDealItem(item: Record<string, unknown>): EntityPickerItem | null {\n const id = readString(item, 'id')\n const label = readDisplayString(item, 'title')\n if (!id || !label) return null\n return { id, label, subtitle: optionalSubtitle(readDisplayString(item, 'status')) }\n}\n\nfunction mapProductItem(item: Record<string, unknown>): EntityPickerItem | null {\n const id = readString(item, 'id')\n const label = readDisplayString(item, 'title')\n if (!id || !label) return null\n return { id, label, subtitle: optionalSubtitle(readDisplayString(item, 'sku')) }\n}\n\nfunction mapCatalogOfferItem(item: Record<string, unknown>): EntityPickerItem | null {\n const id = readString(item, 'id')\n const productId = readString(item, 'productId', 'product_id')\n ?? readNestedString(item, 'product', 'id')\n const productTitle = readNestedDisplayString(item, 'product', 'title', 'name')\n const label = readDisplayString(item, 'title', 'name') ?? productTitle\n if (!id || !productId || !label) return null\n const productSku = readNestedDisplayString(item, 'product', 'sku')\n return {\n id,\n label,\n subtitle: optionalSubtitle(productTitle ?? productSku),\n href: `/backend/catalog/products/${productId}`,\n }\n}\n\nfunction mapSalesDocumentItem(\n item: Record<string, unknown>,\n numberKeys: string[],\n): EntityPickerItem | null {\n const id = readString(item, 'id')\n const label = readDisplayString(item, ...numberKeys, 'number', 'title')\n if (!id || !label) return null\n return { id, label, subtitle: optionalSubtitle(readDisplayString(item, 'status')) }\n}\n\nfunction mapDocumentItem(item: Record<string, unknown>): EntityPickerItem | null {\n const id = readString(item, 'id')\n const label = readDisplayString(item, 'title')\n if (!id || !label) return null\n const archivedAt = item.archivedAt ?? item.archived_at\n return {\n id,\n label,\n archivedAt: typeof archivedAt === 'string' && archivedAt.length > 0 ? archivedAt : null,\n }\n}\n\nfunction field(fieldName: string, labelKey: string, keys: string[]): EntityTokenField {\n return {\n field: fieldName,\n labelKey,\n extract: (item) => readDisplayTextValue(item, ...keys),\n }\n}\n\nfunction exactIdPath(pathPrefix: string, id: string): string {\n return `${pathPrefix}/${id}`\n}\n\nconst CATALOG_PRODUCT_HREF_PATTERN =\n /^\\/backend\\/catalog\\/products\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\n\nfunction buildIdAddressableEntry(\n input: Omit<DocumentEntityRegistryEntry, 'resolveHref' | 'isCanonicalHref'>,\n): DocumentEntityRegistryEntry {\n return {\n ...input,\n resolveHref: (item) => input.href(item.id),\n isCanonicalHref: (item, href) => href === input.href(item.id),\n }\n}\n\nexport function readItemsArray(response: unknown): Record<string, unknown>[] {\n if (Array.isArray(response)) {\n return response.map(readRecord).filter((item): item is Record<string, unknown> => item !== null)\n }\n\n const record = readRecord(response)\n const candidates = [record?.items, record?.data]\n for (const candidate of candidates) {\n if (Array.isArray(candidate)) {\n return candidate.map(readRecord).filter((item): item is Record<string, unknown> => item !== null)\n }\n }\n return []\n}\n\nexport const DOCUMENT_ENTITY_REGISTRY: DocumentEntityRegistryEntry[] = [\n buildIdAddressableEntry({\n type: 'customer-person',\n labelKey: 'documents.entities.customerPerson',\n searchPath: '/api/customers/people',\n mapItem: mapCustomerItem,\n href: (id) => exactIdPath('/backend/customers/people', id),\n requiredModule: 'customers',\n requiredFeatureModule: 'customers',\n requiredFeature: 'customers.people.view',\n tokenFields: [\n field('name', 'documents.entityFields.name', ['name', 'displayName', 'display_name']),\n field('email', 'documents.entityFields.email', ['email', 'primaryEmail', 'primary_email']),\n field('phone', 'documents.entityFields.phone', ['phone', 'primaryPhone', 'primary_phone']),\n ],\n }),\n buildIdAddressableEntry({\n type: 'customer-company',\n labelKey: 'documents.entities.customerCompany',\n searchPath: '/api/customers/companies',\n mapItem: mapCustomerItem,\n href: (id) => exactIdPath('/backend/customers/companies', id),\n requiredModule: 'customers',\n requiredFeatureModule: 'customers',\n requiredFeature: 'customers.companies.view',\n tokenFields: [\n field('name', 'documents.entityFields.name', ['name', 'displayName', 'display_name']),\n field('email', 'documents.entityFields.email', ['email', 'primaryEmail', 'primary_email']),\n field('phone', 'documents.entityFields.phone', ['phone', 'primaryPhone', 'primary_phone']),\n ],\n }),\n buildIdAddressableEntry({\n type: 'deal',\n labelKey: 'documents.entities.deal',\n searchPath: '/api/customers/deals',\n mapItem: mapDealItem,\n href: (id) => exactIdPath('/backend/customers/deals', id),\n requiredModule: 'customers',\n requiredFeatureModule: 'customers',\n requiredFeature: 'customers.deals.view',\n tokenFields: [\n field('title', 'documents.entityFields.title', ['title']),\n field('status', 'documents.entityFields.status', ['status']),\n field('value', 'documents.entityFields.value', ['value', 'valueAmount', 'value_amount']),\n field('valueCurrency', 'documents.entityFields.valueCurrency', ['valueCurrency', 'value_currency']),\n ],\n }),\n buildIdAddressableEntry({\n type: 'product',\n labelKey: 'documents.entities.product',\n searchPath: '/api/catalog/products',\n mapItem: mapProductItem,\n href: (id) => exactIdPath('/backend/catalog/products', id),\n requiredModule: 'catalog',\n requiredFeatureModule: 'catalog',\n requiredFeature: 'catalog.products.view',\n tokenFields: [\n field('title', 'documents.entityFields.title', ['title']),\n field('subtitle', 'documents.entityFields.subtitle', ['subtitle']),\n field('sku', 'documents.entityFields.sku', ['sku']),\n ],\n }),\n {\n type: 'catalog-offer',\n labelKey: 'documents.entities.catalogOffer',\n searchPath: '/api/catalog/offers',\n mapItem: mapCatalogOfferItem,\n href: () => '',\n resolveHref: (item) => {\n const href = item.href ?? null\n return href && CATALOG_PRODUCT_HREF_PATTERN.test(href) ? href : null\n },\n isCanonicalHref: (item, href) => Boolean(item.href && href === item.href && CATALOG_PRODUCT_HREF_PATTERN.test(href)),\n requiredModule: 'catalog',\n requiredFeatureModule: 'sales',\n requiredFeature: 'sales.channels.manage',\n tokenFields: [\n field('title', 'documents.entityFields.title', ['title', 'name']),\n field('description', 'documents.entityFields.description', ['description']),\n ],\n },\n buildIdAddressableEntry({\n type: 'quote',\n labelKey: 'documents.entities.quote',\n searchPath: '/api/sales/quotes',\n mapItem: (item) => mapSalesDocumentItem(item, ['quoteNumber', 'quote_number']),\n href: (id) => exactIdPath('/backend/sales/quotes', id),\n requiredModule: 'sales',\n requiredFeatureModule: 'sales',\n requiredFeature: 'sales.quotes.view',\n tokenFields: [\n field('number', 'documents.entityFields.number', ['quoteNumber', 'quote_number', 'number']),\n field('status', 'documents.entityFields.status', ['status']),\n field('total', 'documents.entityFields.total', ['grandTotalGross', 'grand_total_gross', 'total']),\n field('currency', 'documents.entityFields.currency', ['currencyCode', 'currency_code']),\n ],\n }),\n buildIdAddressableEntry({\n type: 'sales-order',\n labelKey: 'documents.entities.salesOrder',\n searchPath: '/api/sales/orders',\n mapItem: (item) => mapSalesDocumentItem(item, ['orderNumber', 'order_number']),\n href: (id) => exactIdPath('/backend/sales/orders', id),\n requiredModule: 'sales',\n requiredFeatureModule: 'sales',\n requiredFeature: 'sales.orders.view',\n tokenFields: [\n field('number', 'documents.entityFields.number', ['orderNumber', 'order_number', 'number']),\n field('status', 'documents.entityFields.status', ['status']),\n field('total', 'documents.entityFields.total', ['grandTotalGross', 'grand_total_gross', 'total']),\n field('currency', 'documents.entityFields.currency', ['currencyCode', 'currency_code']),\n ],\n }),\n buildIdAddressableEntry({\n type: 'document',\n labelKey: 'documents.entities.document',\n searchPath: '/api/documents',\n mapItem: mapDocumentItem,\n href: (id) => exactIdPath('/backend/documents', id),\n requiredModule: 'documents',\n requiredFeatureModule: 'documents',\n requiredFeature: 'documents.view',\n tokenFields: [\n field('title', 'documents.entityFields.title', ['title']),\n ],\n }),\n]\n\nexport function getEntityRegistryEntry(type: string): DocumentEntityRegistryEntry | null {\n return DOCUMENT_ENTITY_REGISTRY.find((entry) => entry.type === type) ?? null\n}\n\nexport function getEntityTokenFieldNames(type: DocumentEntityType): Set<string> {\n const entry = getEntityRegistryEntry(type)\n return new Set(entry?.tokenFields.map((tokenField) => tokenField.field) ?? [])\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,189 @@
1
+ import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
2
+ import {
3
+ fetchWithTimeout,
4
+ resolveTimeoutMs,
5
+ withTimeout
6
+ } from "@open-mercato/shared/lib/http/fetchWithTimeout";
7
+ import { getSecurityEmailBaseUrl } from "@open-mercato/shared/lib/url";
8
+ import {
9
+ getEntityRegistryEntry,
10
+ readItemsArray
11
+ } from "./entityRegistry.js";
12
+ import { isDocumentEntityRegistryModuleEnabled } from "./entityRegistryAvailability.server.js";
13
+ const DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS = 3e3;
14
+ const MAX_REGISTRY_RESPONSE_BYTES = 1e6;
15
+ async function readRegistryJsonBody(response, callerSignal, timeoutMs) {
16
+ return withTimeout(async (timeoutSignal) => {
17
+ const signals = [callerSignal, timeoutSignal];
18
+ for (const signal of signals) {
19
+ if (signal.aborted) {
20
+ throw signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
21
+ }
22
+ }
23
+ const reader = response.body?.getReader();
24
+ if (!reader) return null;
25
+ let aborted = null;
26
+ const listeners = signals.map((signal) => {
27
+ let handled = false;
28
+ const listener = () => {
29
+ if (handled) return;
30
+ handled = true;
31
+ aborted = signal.reason instanceof Error ? signal.reason : new DOMException("Aborted", "AbortError");
32
+ void reader.cancel(aborted).catch(() => void 0);
33
+ };
34
+ signal.addEventListener("abort", listener, { once: true });
35
+ if (signal.aborted) listener();
36
+ return { signal, listener };
37
+ });
38
+ const decoder = new TextDecoder();
39
+ let decoded = "";
40
+ let totalBytes = 0;
41
+ try {
42
+ while (true) {
43
+ const { done, value } = await reader.read();
44
+ if (done) break;
45
+ totalBytes += value.byteLength;
46
+ if (totalBytes > MAX_REGISTRY_RESPONSE_BYTES) {
47
+ await reader.cancel().catch(() => void 0);
48
+ throw new Error("[internal] Entity registry response exceeded the size limit");
49
+ }
50
+ decoded += decoder.decode(value, { stream: true });
51
+ }
52
+ if (aborted) throw aborted;
53
+ decoded += decoder.decode();
54
+ } finally {
55
+ for (const { signal, listener } of listeners) {
56
+ signal.removeEventListener("abort", listener);
57
+ }
58
+ reader.releaseLock();
59
+ }
60
+ try {
61
+ return JSON.parse(decoded);
62
+ } catch {
63
+ return null;
64
+ }
65
+ }, timeoutMs, "documents entity-registry response");
66
+ }
67
+ function buildForwardedHeaders(request) {
68
+ const headers = new Headers();
69
+ const cookie = request.headers.get("cookie");
70
+ const authorization = request.headers.get("authorization");
71
+ const apiKey = request.headers.get("x-api-key");
72
+ if (cookie) headers.set("cookie", cookie);
73
+ if (authorization) headers.set("authorization", authorization);
74
+ if (apiKey) headers.set("x-api-key", apiKey);
75
+ return headers;
76
+ }
77
+ async function verifyEntityRegistryTarget(request, input, options = {}) {
78
+ const entry = getEntityRegistryEntry(input.entityType);
79
+ if (!entry) {
80
+ throw new CrudHttpError(400, { error: "documents.links.invalidEntityType" });
81
+ }
82
+ if (!isDocumentEntityRegistryModuleEnabled(entry)) {
83
+ throw new CrudHttpError(503, { error: "documents.links.targetUnavailable" });
84
+ }
85
+ const timeoutMs = Math.min(
86
+ resolveTimeoutMs(options.timeoutMs, DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS),
87
+ DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS
88
+ );
89
+ const deadline = Date.now() + timeoutMs;
90
+ let response;
91
+ try {
92
+ const lookupUrl = new URL(entry.searchPath, getSecurityEmailBaseUrl());
93
+ lookupUrl.searchParams.set("id", input.entityId);
94
+ lookupUrl.searchParams.set("pageSize", "1");
95
+ const fetchImpl = options.fetchImpl ?? fetchWithTimeout;
96
+ response = await fetchImpl(lookupUrl, {
97
+ method: "GET",
98
+ headers: buildForwardedHeaders(request),
99
+ cache: "no-store",
100
+ redirect: "manual",
101
+ signal: request.signal,
102
+ timeoutMs
103
+ });
104
+ } catch {
105
+ throw new CrudHttpError(503, { error: "documents.links.targetUnavailable" });
106
+ }
107
+ if (response.status === 404) {
108
+ throw new CrudHttpError(options.maskTargetAbsence ? 403 : 503, {
109
+ error: options.maskTargetAbsence ? "documents.links.targetRestricted" : "documents.links.targetUnavailable"
110
+ });
111
+ }
112
+ if (response.status >= 500) {
113
+ throw new CrudHttpError(503, { error: "documents.links.targetUnavailable" });
114
+ }
115
+ if (!response.ok) {
116
+ throw new CrudHttpError(response.status === 401 ? 401 : 403, {
117
+ error: "documents.links.targetRestricted"
118
+ });
119
+ }
120
+ let payload;
121
+ try {
122
+ payload = await readRegistryJsonBody(
123
+ response,
124
+ request.signal,
125
+ Math.max(1, deadline - Date.now())
126
+ );
127
+ } catch {
128
+ throw new CrudHttpError(503, { error: "documents.links.targetUnavailable" });
129
+ }
130
+ const rawItem = readItemsArray(payload).find((candidate) => entry.mapItem(candidate)?.id === input.entityId) ?? null;
131
+ const mapped = rawItem ? entry.mapItem(rawItem) : null;
132
+ const resolvedHref = mapped ? entry.resolveHref(mapped) : null;
133
+ if (!mapped || !rawItem || !resolvedHref || !entry.isCanonicalHref(mapped, resolvedHref)) {
134
+ throw new CrudHttpError(options.maskTargetAbsence ? 403 : 400, {
135
+ error: options.maskTargetAbsence ? "documents.links.targetRestricted" : "documents.links.targetMismatch"
136
+ });
137
+ }
138
+ return {
139
+ ...mapped,
140
+ href: resolvedHref,
141
+ values: Object.fromEntries(entry.tokenFields.map((field) => [field.field, field.extract(rawItem)]))
142
+ };
143
+ }
144
+ async function verifyEntityRegistrySelection(request, input, options = {}) {
145
+ return verifyEntityRegistryTarget(request, input, options);
146
+ }
147
+ async function verifyEntityRegistryTargetAccess(request, input, options = {}) {
148
+ try {
149
+ return await verifyEntityRegistryTarget(request, input, {
150
+ ...options,
151
+ maskTargetAbsence: true
152
+ });
153
+ } catch (error) {
154
+ if (isCrudHttpError(error) && error.status >= 400 && error.status < 500) {
155
+ throw new CrudHttpError(403, { error: "documents.links.targetRestricted" });
156
+ }
157
+ throw error;
158
+ }
159
+ }
160
+ async function verifyEntityRegistrySelections(request, inputs, options = {}) {
161
+ const deduped = Array.from(
162
+ new Map(inputs.map((input) => [`${input.entityType}:${input.entityId}`, input])).values()
163
+ );
164
+ if (deduped.length > 20) {
165
+ throw new CrudHttpError(400, { error: "documents.templates.tooManySlots" });
166
+ }
167
+ const concurrency = Math.max(1, Math.min(4, options.concurrency ?? 4));
168
+ const verified = /* @__PURE__ */ new Map();
169
+ let nextIndex = 0;
170
+ const workers = Array.from({ length: Math.min(concurrency, deduped.length) }, async () => {
171
+ while (nextIndex < deduped.length) {
172
+ const index = nextIndex;
173
+ nextIndex += 1;
174
+ const input = deduped[index];
175
+ verified.set(
176
+ `${input.entityType}:${input.entityId}`,
177
+ await verifyEntityRegistrySelection(request, input, options)
178
+ );
179
+ }
180
+ });
181
+ await Promise.all(workers);
182
+ return verified;
183
+ }
184
+ export {
185
+ verifyEntityRegistrySelection,
186
+ verifyEntityRegistrySelections,
187
+ verifyEntityRegistryTargetAccess
188
+ };
189
+ //# sourceMappingURL=entityRegistry.server.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/documents/lib/entityRegistry.server.ts"],
4
+ "sourcesContent": ["import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n fetchWithTimeout,\n type FetchWithTimeoutInit,\n resolveTimeoutMs,\n withTimeout,\n} from '@open-mercato/shared/lib/http/fetchWithTimeout'\nimport { getSecurityEmailBaseUrl } from '@open-mercato/shared/lib/url'\nimport type { DocumentEntityType } from '../data/validators'\nimport {\n getEntityRegistryEntry,\n readItemsArray,\n type EntityPickerItem,\n} from './entityRegistry'\nimport { isDocumentEntityRegistryModuleEnabled } from './entityRegistryAvailability.server'\n\nexport type VerifyEntityRegistrySelectionInput = {\n entityType: DocumentEntityType\n entityId: string\n label: string\n href: string\n}\n\nexport type VerifyEntityRegistryTargetAccessInput = Pick<\n VerifyEntityRegistrySelectionInput,\n 'entityType' | 'entityId'\n>\n\nexport type VerifiedEntityRegistrySelection = EntityPickerItem & {\n href: string\n values: Record<string, string | null>\n}\n\ntype RegistryFetch = (\n input: RequestInfo | URL,\n init?: FetchWithTimeoutInit,\n) => Promise<Response>\n\nconst DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS = 3_000\nconst MAX_REGISTRY_RESPONSE_BYTES = 1_000_000\n\nasync function readRegistryJsonBody(\n response: Response,\n callerSignal: AbortSignal,\n timeoutMs: number,\n): Promise<unknown> {\n return withTimeout(async (timeoutSignal) => {\n const signals = [callerSignal, timeoutSignal]\n for (const signal of signals) {\n if (signal.aborted) {\n throw signal.reason instanceof Error\n ? signal.reason\n : new DOMException('Aborted', 'AbortError')\n }\n }\n\n const reader = response.body?.getReader()\n if (!reader) return null\n let aborted: unknown = null\n const listeners = signals.map((signal) => {\n let handled = false\n const listener = () => {\n if (handled) return\n handled = true\n aborted = signal.reason instanceof Error\n ? signal.reason\n : new DOMException('Aborted', 'AbortError')\n void reader.cancel(aborted).catch(() => undefined)\n }\n signal.addEventListener('abort', listener, { once: true })\n if (signal.aborted) listener()\n return { signal, listener }\n })\n\n const decoder = new TextDecoder()\n let decoded = ''\n let totalBytes = 0\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n totalBytes += value.byteLength\n if (totalBytes > MAX_REGISTRY_RESPONSE_BYTES) {\n await reader.cancel().catch(() => undefined)\n throw new Error('[internal] Entity registry response exceeded the size limit')\n }\n decoded += decoder.decode(value, { stream: true })\n }\n if (aborted) throw aborted\n decoded += decoder.decode()\n } finally {\n for (const { signal, listener } of listeners) {\n signal.removeEventListener('abort', listener)\n }\n reader.releaseLock()\n }\n\n try {\n return JSON.parse(decoded) as unknown\n } catch {\n return null\n }\n }, timeoutMs, 'documents entity-registry response')\n}\n\nfunction buildForwardedHeaders(request: Request): Headers {\n const headers = new Headers()\n const cookie = request.headers.get('cookie')\n const authorization = request.headers.get('authorization')\n const apiKey = request.headers.get('x-api-key')\n if (cookie) headers.set('cookie', cookie)\n if (authorization) headers.set('authorization', authorization)\n if (apiKey) headers.set('x-api-key', apiKey)\n return headers\n}\n\ntype RegistryVerificationOptions = {\n fetchImpl?: RegistryFetch\n timeoutMs?: number\n maskTargetAbsence?: boolean\n}\n\nasync function verifyEntityRegistryTarget(\n request: Request,\n input: VerifyEntityRegistryTargetAccessInput,\n options: RegistryVerificationOptions = {},\n): Promise<VerifiedEntityRegistrySelection> {\n const entry = getEntityRegistryEntry(input.entityType)\n if (!entry) {\n throw new CrudHttpError(400, { error: 'documents.links.invalidEntityType' })\n }\n if (!isDocumentEntityRegistryModuleEnabled(entry)) {\n throw new CrudHttpError(503, { error: 'documents.links.targetUnavailable' })\n }\n\n const timeoutMs = Math.min(\n resolveTimeoutMs(options.timeoutMs, DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS),\n DEFAULT_REGISTRY_LOOKUP_TIMEOUT_MS,\n )\n const deadline = Date.now() + timeoutMs\n let response: Response\n try {\n // This request carries the caller's credentials, so its destination must\n // come from the configured application URL rather than request.url/Host.\n // getSecurityEmailBaseUrl intentionally has a fixed loopback development\n // fallback and requires APP_URL in production.\n const lookupUrl = new URL(entry.searchPath, getSecurityEmailBaseUrl())\n lookupUrl.searchParams.set('id', input.entityId)\n lookupUrl.searchParams.set('pageSize', '1')\n const fetchImpl = options.fetchImpl ?? fetchWithTimeout\n response = await fetchImpl(lookupUrl, {\n method: 'GET',\n headers: buildForwardedHeaders(request),\n cache: 'no-store',\n redirect: 'manual',\n signal: request.signal,\n timeoutMs,\n })\n } catch {\n throw new CrudHttpError(503, { error: 'documents.links.targetUnavailable' })\n }\n\n if (response.status === 404) {\n throw new CrudHttpError(options.maskTargetAbsence ? 403 : 503, {\n error: options.maskTargetAbsence\n ? 'documents.links.targetRestricted'\n : 'documents.links.targetUnavailable',\n })\n }\n if (response.status >= 500) {\n throw new CrudHttpError(503, { error: 'documents.links.targetUnavailable' })\n }\n if (!response.ok) {\n throw new CrudHttpError(response.status === 401 ? 401 : 403, {\n error: 'documents.links.targetRestricted',\n })\n }\n\n let payload: unknown\n try {\n payload = await readRegistryJsonBody(\n response,\n request.signal,\n Math.max(1, deadline - Date.now()),\n )\n } catch {\n throw new CrudHttpError(503, { error: 'documents.links.targetUnavailable' })\n }\n const rawItem = readItemsArray(payload).find((candidate) => (\n entry.mapItem(candidate)?.id === input.entityId\n )) ?? null\n const mapped = rawItem ? entry.mapItem(rawItem) : null\n const resolvedHref = mapped ? entry.resolveHref(mapped) : null\n if (!mapped || !rawItem || !resolvedHref || !entry.isCanonicalHref(mapped, resolvedHref)) {\n throw new CrudHttpError(options.maskTargetAbsence ? 403 : 400, {\n error: options.maskTargetAbsence\n ? 'documents.links.targetRestricted'\n : 'documents.links.targetMismatch',\n })\n }\n return {\n ...mapped,\n href: resolvedHref,\n values: Object.fromEntries(entry.tokenFields.map((field) => [field.field, field.extract(rawItem)])),\n }\n}\n\nexport async function verifyEntityRegistrySelection(\n request: Request,\n input: VerifyEntityRegistrySelectionInput,\n options: { fetchImpl?: RegistryFetch; timeoutMs?: number } = {},\n): Promise<VerifiedEntityRegistrySelection> {\n return verifyEntityRegistryTarget(request, input, options)\n}\n\n/**\n * Verify access to one exact peer record before using its UUID as a reverse\n * relation filter. Missing and restricted targets intentionally share the same\n * denial so the Documents collection cannot become a peer-record oracle.\n */\nexport async function verifyEntityRegistryTargetAccess(\n request: Request,\n input: VerifyEntityRegistryTargetAccessInput,\n options: { fetchImpl?: RegistryFetch; timeoutMs?: number } = {},\n): Promise<VerifiedEntityRegistrySelection> {\n try {\n return await verifyEntityRegistryTarget(request, input, {\n ...options,\n maskTargetAbsence: true,\n })\n } catch (error) {\n if (isCrudHttpError(error) && error.status >= 400 && error.status < 500) {\n throw new CrudHttpError(403, { error: 'documents.links.targetRestricted' })\n }\n throw error\n }\n}\n\nexport async function verifyEntityRegistrySelections(\n request: Request,\n inputs: VerifyEntityRegistrySelectionInput[],\n options: { fetchImpl?: RegistryFetch; concurrency?: number; timeoutMs?: number } = {},\n): Promise<Map<string, VerifiedEntityRegistrySelection>> {\n const deduped = Array.from(\n new Map(inputs.map((input) => [`${input.entityType}:${input.entityId}`, input])).values(),\n )\n if (deduped.length > 20) {\n throw new CrudHttpError(400, { error: 'documents.templates.tooManySlots' })\n }\n\n const concurrency = Math.max(1, Math.min(4, options.concurrency ?? 4))\n const verified = new Map<string, VerifiedEntityRegistrySelection>()\n let nextIndex = 0\n const workers = Array.from({ length: Math.min(concurrency, deduped.length) }, async () => {\n while (nextIndex < deduped.length) {\n const index = nextIndex\n nextIndex += 1\n const input = deduped[index]!\n verified.set(\n `${input.entityType}:${input.entityId}`,\n await verifyEntityRegistrySelection(request, input, options),\n )\n }\n })\n await Promise.all(workers)\n return verified\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,9 @@
1
+ import { getEnabledModuleIds } from "@open-mercato/shared/security/enabledModulesRegistry";
2
+ function isDocumentEntityRegistryModuleEnabled(entry) {
3
+ const enabledModuleIds = new Set(getEnabledModuleIds());
4
+ return enabledModuleIds.has(entry.requiredModule) && enabledModuleIds.has(entry.requiredFeatureModule);
5
+ }
6
+ export {
7
+ isDocumentEntityRegistryModuleEnabled
8
+ };
9
+ //# sourceMappingURL=entityRegistryAvailability.server.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/documents/lib/entityRegistryAvailability.server.ts"],
4
+ "sourcesContent": ["import { getEnabledModuleIds } from '@open-mercato/shared/security/enabledModulesRegistry'\nimport type { DocumentEntityRegistryEntry } from './entityRegistry'\n\n/**\n * Returns whether the peer module backing a Documents entity-registry entry\n * is enabled in the running application.\n *\n * The bootstrapped module registry is the canonical server-side source. An\n * empty/unavailable registry therefore fails closed for peer-backed entries;\n * stale ACL grants (including superadmin wildcards) must never make a disabled\n * module addressable through Documents.\n */\nexport function isDocumentEntityRegistryModuleEnabled(\n entry: Pick<DocumentEntityRegistryEntry, 'requiredModule' | 'requiredFeatureModule'>,\n): boolean {\n const enabledModuleIds = new Set(getEnabledModuleIds())\n return enabledModuleIds.has(entry.requiredModule)\n && enabledModuleIds.has(entry.requiredFeatureModule)\n}\n"],
5
+ "mappings": "AAAA,SAAS,2BAA2B;AAY7B,SAAS,sCACd,OACS;AACT,QAAM,mBAAmB,IAAI,IAAI,oBAAoB,CAAC;AACtD,SAAO,iBAAiB,IAAI,MAAM,cAAc,KAC3C,iBAAiB,IAAI,MAAM,qBAAqB;AACvD;",
6
+ "names": []
7
+ }
@@ -0,0 +1,50 @@
1
+ import { Extension } from "@tiptap/core";
2
+ import { Suggestion } from "@tiptap/suggestion";
3
+ function notifyTrigger(handlers, props) {
4
+ handlers.onTrigger({
5
+ query: props.query,
6
+ range: {
7
+ from: props.range.from,
8
+ to: props.range.to
9
+ }
10
+ });
11
+ }
12
+ function createEntitySuggestionExtension(handlers) {
13
+ return Extension.create({
14
+ name: "entitySuggestion",
15
+ addProseMirrorPlugins() {
16
+ return [
17
+ Suggestion({
18
+ editor: this.editor,
19
+ char: "@",
20
+ allowSpaces: false,
21
+ startOfLine: false,
22
+ items: () => [],
23
+ command: () => void 0,
24
+ render: () => ({
25
+ onStart: (props) => notifyTrigger(handlers, props),
26
+ onUpdate: (props) => notifyTrigger(handlers, props),
27
+ onExit: () => handlers.onClose()
28
+ })
29
+ })
30
+ ];
31
+ }
32
+ });
33
+ }
34
+ function insertEntityRef(editor, attrs) {
35
+ return editor.chain().focus().insertContent([
36
+ {
37
+ type: "entityRef",
38
+ attrs
39
+ },
40
+ {
41
+ type: "text",
42
+ text: " "
43
+ }
44
+ ]).run();
45
+ }
46
+ export {
47
+ createEntitySuggestionExtension,
48
+ insertEntityRef
49
+ };
50
+ //# sourceMappingURL=entitySuggestion.js.map