@aglyn/plugins-crm 1.0.0-beta.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +7 -0
- package/package.json +57 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +29 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/activity-list.d.ts +98 -0
- package/src/lib/components/activity-list.js +321 -0
- package/src/lib/components/activity-list.js.map +1 -0
- package/src/lib/components/activity-queries.d.ts +117 -0
- package/src/lib/components/activity-queries.js +198 -0
- package/src/lib/components/activity-queries.js.map +1 -0
- package/src/lib/components/add-to-list-button.d.ts +25 -0
- package/src/lib/components/add-to-list-button.js +64 -0
- package/src/lib/components/add-to-list-button.js.map +1 -0
- package/src/lib/components/add-to-list-dialog.d.ts +24 -0
- package/src/lib/components/add-to-list-dialog.js +327 -0
- package/src/lib/components/add-to-list-dialog.js.map +1 -0
- package/src/lib/components/assignment-rule-drawer.d.ts +43 -0
- package/src/lib/components/assignment-rule-drawer.js +293 -0
- package/src/lib/components/assignment-rule-drawer.js.map +1 -0
- package/src/lib/components/companies-bulk-bar.d.ts +29 -0
- package/src/lib/components/companies-bulk-bar.js +274 -0
- package/src/lib/components/companies-bulk-bar.js.map +1 -0
- package/src/lib/components/companies-section.d.ts +54 -0
- package/src/lib/components/companies-section.js +522 -0
- package/src/lib/components/companies-section.js.map +1 -0
- package/src/lib/components/company-contacts-card.d.ts +49 -0
- package/src/lib/components/company-contacts-card.js +435 -0
- package/src/lib/components/company-contacts-card.js.map +1 -0
- package/src/lib/components/company-deals-card.d.ts +20 -0
- package/src/lib/components/company-deals-card.js +38 -0
- package/src/lib/components/company-deals-card.js.map +1 -0
- package/src/lib/components/company-detail-page.d.ts +20 -0
- package/src/lib/components/company-detail-page.js +165 -0
- package/src/lib/components/company-detail-page.js.map +1 -0
- package/src/lib/components/company-edit-drawer.d.ts +65 -0
- package/src/lib/components/company-edit-drawer.js +433 -0
- package/src/lib/components/company-edit-drawer.js.map +1 -0
- package/src/lib/components/company-import-drawer.d.ts +42 -0
- package/src/lib/components/company-import-drawer.js +99 -0
- package/src/lib/components/company-import-drawer.js.map +1 -0
- package/src/lib/components/company-picker.d.ts +127 -0
- package/src/lib/components/company-picker.js +323 -0
- package/src/lib/components/company-picker.js.map +1 -0
- package/src/lib/components/company-properties-card.d.ts +47 -0
- package/src/lib/components/company-properties-card.js +289 -0
- package/src/lib/components/company-properties-card.js.map +1 -0
- package/src/lib/components/contact-address-fields.d.ts +29 -0
- package/src/lib/components/contact-address-fields.js +149 -0
- package/src/lib/components/contact-address-fields.js.map +1 -0
- package/src/lib/components/contact-associations-card.d.ts +72 -0
- package/src/lib/components/contact-associations-card.js +296 -0
- package/src/lib/components/contact-associations-card.js.map +1 -0
- package/src/lib/components/contact-custom-columns.d.ts +38 -0
- package/src/lib/components/contact-custom-columns.js +102 -0
- package/src/lib/components/contact-custom-columns.js.map +1 -0
- package/src/lib/components/contact-custom-fields-card.d.ts +39 -0
- package/src/lib/components/contact-custom-fields-card.js +204 -0
- package/src/lib/components/contact-custom-fields-card.js.map +1 -0
- package/src/lib/components/contact-deals-card.d.ts +20 -0
- package/src/lib/components/contact-deals-card.js +38 -0
- package/src/lib/components/contact-deals-card.js.map +1 -0
- package/src/lib/components/contact-detail-page.d.ts +46 -0
- package/src/lib/components/contact-detail-page.js +535 -0
- package/src/lib/components/contact-detail-page.js.map +1 -0
- package/src/lib/components/contact-duplicates-card.d.ts +42 -0
- package/src/lib/components/contact-duplicates-card.js +167 -0
- package/src/lib/components/contact-duplicates-card.js.map +1 -0
- package/src/lib/components/contact-field-drawer.d.ts +64 -0
- package/src/lib/components/contact-field-drawer.js +251 -0
- package/src/lib/components/contact-field-drawer.js.map +1 -0
- package/src/lib/components/contact-import-drawer.d.ts +46 -0
- package/src/lib/components/contact-import-drawer.js +149 -0
- package/src/lib/components/contact-import-drawer.js.map +1 -0
- package/src/lib/components/contact-known-by-card.d.ts +39 -0
- package/src/lib/components/contact-known-by-card.js +142 -0
- package/src/lib/components/contact-known-by-card.js.map +1 -0
- package/src/lib/components/contact-list-columns.d.ts +53 -0
- package/src/lib/components/contact-list-columns.js +288 -0
- package/src/lib/components/contact-list-columns.js.map +1 -0
- package/src/lib/components/contact-merge-dialog.d.ts +79 -0
- package/src/lib/components/contact-merge-dialog.js +405 -0
- package/src/lib/components/contact-merge-dialog.js.map +1 -0
- package/src/lib/components/contact-properties-card.d.ts +89 -0
- package/src/lib/components/contact-properties-card.js +492 -0
- package/src/lib/components/contact-properties-card.js.map +1 -0
- package/src/lib/components/contact-timeline-card.d.ts +68 -0
- package/src/lib/components/contact-timeline-card.js +435 -0
- package/src/lib/components/contact-timeline-card.js.map +1 -0
- package/src/lib/components/contacts-bulk-bar.d.ts +91 -0
- package/src/lib/components/contacts-bulk-bar.js +493 -0
- package/src/lib/components/contacts-bulk-bar.js.map +1 -0
- package/src/lib/components/contacts-section.d.ts +26 -0
- package/src/lib/components/contacts-section.js +1025 -0
- package/src/lib/components/contacts-section.js.map +1 -0
- package/src/lib/components/copy-capture-address-button.d.ts +33 -0
- package/src/lib/components/copy-capture-address-button.js +60 -0
- package/src/lib/components/copy-capture-address-button.js.map +1 -0
- package/src/lib/components/crm-attribution-zone.d.ts +38 -0
- package/src/lib/components/crm-attribution-zone.js +36 -0
- package/src/lib/components/crm-attribution-zone.js.map +1 -0
- package/src/lib/components/crm-booking-zone.d.ts +61 -0
- package/src/lib/components/crm-booking-zone.js +50 -0
- package/src/lib/components/crm-booking-zone.js.map +1 -0
- package/src/lib/components/crm-bulk-bar-frame.d.ts +47 -0
- package/src/lib/components/crm-bulk-bar-frame.js +137 -0
- package/src/lib/components/crm-bulk-bar-frame.js.map +1 -0
- package/src/lib/components/crm-call-actions.d.ts +65 -0
- package/src/lib/components/crm-call-actions.js +110 -0
- package/src/lib/components/crm-call-actions.js.map +1 -0
- package/src/lib/components/crm-column-menu.d.ts +21 -0
- package/src/lib/components/crm-column-menu.js +103 -0
- package/src/lib/components/crm-column-menu.js.map +1 -0
- package/src/lib/components/crm-console-page.d.ts +19 -0
- package/src/lib/components/crm-console-page.js +151 -0
- package/src/lib/components/crm-console-page.js.map +1 -0
- package/src/lib/components/crm-console-sections.d.ts +52 -0
- package/src/lib/components/crm-console-sections.js +83 -0
- package/src/lib/components/crm-console-sections.js.map +1 -0
- package/src/lib/components/crm-custom-field-control.d.ts +26 -0
- package/src/lib/components/crm-custom-field-control.js +131 -0
- package/src/lib/components/crm-custom-field-control.js.map +1 -0
- package/src/lib/components/crm-email-template-tools.d.ts +69 -0
- package/src/lib/components/crm-email-template-tools.js +240 -0
- package/src/lib/components/crm-email-template-tools.js.map +1 -0
- package/src/lib/components/crm-export-all-button.d.ts +39 -0
- package/src/lib/components/crm-export-all-button.js +98 -0
- package/src/lib/components/crm-export-all-button.js.map +1 -0
- package/src/lib/components/crm-filter-bar.d.ts +53 -0
- package/src/lib/components/crm-filter-bar.js +294 -0
- package/src/lib/components/crm-filter-bar.js.map +1 -0
- package/src/lib/components/crm-glance-card.d.ts +54 -0
- package/src/lib/components/crm-glance-card.js +219 -0
- package/src/lib/components/crm-glance-card.js.map +1 -0
- package/src/lib/components/crm-next-activity-column.d.ts +35 -0
- package/src/lib/components/crm-next-activity-column.js +100 -0
- package/src/lib/components/crm-next-activity-column.js.map +1 -0
- package/src/lib/components/crm-record-header.d.ts +97 -0
- package/src/lib/components/crm-record-header.js +160 -0
- package/src/lib/components/crm-record-header.js.map +1 -0
- package/src/lib/components/crm-record-insights-zone.d.ts +50 -0
- package/src/lib/components/crm-record-insights-zone.js +169 -0
- package/src/lib/components/crm-record-insights-zone.js.map +1 -0
- package/src/lib/components/crm-record-picker.d.ts +42 -0
- package/src/lib/components/crm-record-picker.js +104 -0
- package/src/lib/components/crm-record-picker.js.map +1 -0
- package/src/lib/components/crm-send-email-button.d.ts +39 -0
- package/src/lib/components/crm-send-email-button.js +81 -0
- package/src/lib/components/crm-send-email-button.js.map +1 -0
- package/src/lib/components/crm-send-email-dialog.d.ts +61 -0
- package/src/lib/components/crm-send-email-dialog.js +851 -0
- package/src/lib/components/crm-send-email-dialog.js.map +1 -0
- package/src/lib/components/crm-site-picker.d.ts +61 -0
- package/src/lib/components/crm-site-picker.js +99 -0
- package/src/lib/components/crm-site-picker.js.map +1 -0
- package/src/lib/components/crm-suite-lock.d.ts +29 -0
- package/src/lib/components/crm-suite-lock.js +114 -0
- package/src/lib/components/crm-suite-lock.js.map +1 -0
- package/src/lib/components/crm-tasks-due-card.d.ts +42 -0
- package/src/lib/components/crm-tasks-due-card.js +225 -0
- package/src/lib/components/crm-tasks-due-card.js.map +1 -0
- package/src/lib/components/crm-views-control.d.ts +65 -0
- package/src/lib/components/crm-views-control.js +518 -0
- package/src/lib/components/crm-views-control.js.map +1 -0
- package/src/lib/components/csv-import-drawer.d.ts +132 -0
- package/src/lib/components/csv-import-drawer.js +746 -0
- package/src/lib/components/csv-import-drawer.js.map +1 -0
- package/src/lib/components/deal-board.d.ts +70 -0
- package/src/lib/components/deal-board.js +478 -0
- package/src/lib/components/deal-board.js.map +1 -0
- package/src/lib/components/deal-detail-page.d.ts +18 -0
- package/src/lib/components/deal-detail-page.js +323 -0
- package/src/lib/components/deal-detail-page.js.map +1 -0
- package/src/lib/components/deal-edit-drawer.d.ts +59 -0
- package/src/lib/components/deal-edit-drawer.js +640 -0
- package/src/lib/components/deal-edit-drawer.js.map +1 -0
- package/src/lib/components/deal-import-drawer.d.ts +24 -0
- package/src/lib/components/deal-import-drawer.js +83 -0
- package/src/lib/components/deal-import-drawer.js.map +1 -0
- package/src/lib/components/deal-products-card.d.ts +48 -0
- package/src/lib/components/deal-products-card.js +614 -0
- package/src/lib/components/deal-products-card.js.map +1 -0
- package/src/lib/components/deal-properties-card.d.ts +29 -0
- package/src/lib/components/deal-properties-card.js +144 -0
- package/src/lib/components/deal-properties-card.js.map +1 -0
- package/src/lib/components/deal-stage-card.d.ts +24 -0
- package/src/lib/components/deal-stage-card.js +199 -0
- package/src/lib/components/deal-stage-card.js.map +1 -0
- package/src/lib/components/deals-bulk-bar.d.ts +31 -0
- package/src/lib/components/deals-bulk-bar.js +340 -0
- package/src/lib/components/deals-bulk-bar.js.map +1 -0
- package/src/lib/components/deals-section.d.ts +49 -0
- package/src/lib/components/deals-section.js +767 -0
- package/src/lib/components/deals-section.js.map +1 -0
- package/src/lib/components/email-capture-card.d.ts +42 -0
- package/src/lib/components/email-capture-card.js +134 -0
- package/src/lib/components/email-capture-card.js.map +1 -0
- package/src/lib/components/email-template-drawer.d.ts +33 -0
- package/src/lib/components/email-template-drawer.js +209 -0
- package/src/lib/components/email-template-drawer.js.map +1 -0
- package/src/lib/components/email-templates-card.d.ts +33 -0
- package/src/lib/components/email-templates-card.js +370 -0
- package/src/lib/components/email-templates-card.js.map +1 -0
- package/src/lib/components/erase-person-action.d.ts +92 -0
- package/src/lib/components/erase-person-action.js +261 -0
- package/src/lib/components/erase-person-action.js.map +1 -0
- package/src/lib/components/fields-section.d.ts +37 -0
- package/src/lib/components/fields-section.js +641 -0
- package/src/lib/components/fields-section.js.map +1 -0
- package/src/lib/components/form-contact-fields-card.d.ts +46 -0
- package/src/lib/components/form-contact-fields-card.js +253 -0
- package/src/lib/components/form-contact-fields-card.js.map +1 -0
- package/src/lib/components/insert-link-at-caret.d.ts +28 -0
- package/src/lib/components/insert-link-at-caret.js +37 -0
- package/src/lib/components/insert-link-at-caret.js.map +1 -0
- package/src/lib/components/lead-convert-dialog.d.ts +32 -0
- package/src/lib/components/lead-convert-dialog.js +493 -0
- package/src/lib/components/lead-convert-dialog.js.map +1 -0
- package/src/lib/components/lead-detail-page.d.ts +16 -0
- package/src/lib/components/lead-detail-page.js +163 -0
- package/src/lib/components/lead-detail-page.js.map +1 -0
- package/src/lib/components/lead-history-card.d.ts +32 -0
- package/src/lib/components/lead-history-card.js +165 -0
- package/src/lib/components/lead-history-card.js.map +1 -0
- package/src/lib/components/lead-import-drawer.d.ts +24 -0
- package/src/lib/components/lead-import-drawer.js +95 -0
- package/src/lib/components/lead-import-drawer.js.map +1 -0
- package/src/lib/components/lead-owner-select.d.ts +35 -0
- package/src/lib/components/lead-owner-select.js +91 -0
- package/src/lib/components/lead-owner-select.js.map +1 -0
- package/src/lib/components/lead-properties-card.d.ts +61 -0
- package/src/lib/components/lead-properties-card.js +395 -0
- package/src/lib/components/lead-properties-card.js.map +1 -0
- package/src/lib/components/lead-status-chip.d.ts +12 -0
- package/src/lib/components/lead-status-chip.js +43 -0
- package/src/lib/components/lead-status-chip.js.map +1 -0
- package/src/lib/components/lead-surfaces-note.d.ts +126 -0
- package/src/lib/components/lead-surfaces-note.js +262 -0
- package/src/lib/components/lead-surfaces-note.js.map +1 -0
- package/src/lib/components/lead-unqualify-dialog.d.ts +24 -0
- package/src/lib/components/lead-unqualify-dialog.js +125 -0
- package/src/lib/components/lead-unqualify-dialog.js.map +1 -0
- package/src/lib/components/leads-bulk-bar.d.ts +58 -0
- package/src/lib/components/leads-bulk-bar.js +307 -0
- package/src/lib/components/leads-bulk-bar.js.map +1 -0
- package/src/lib/components/leads-section.d.ts +23 -0
- package/src/lib/components/leads-section.js +664 -0
- package/src/lib/components/leads-section.js.map +1 -0
- package/src/lib/components/linked-deals-card.d.ts +32 -0
- package/src/lib/components/linked-deals-card.js +163 -0
- package/src/lib/components/linked-deals-card.js.map +1 -0
- package/src/lib/components/log-activity-dialog.d.ts +60 -0
- package/src/lib/components/log-activity-dialog.js +368 -0
- package/src/lib/components/log-activity-dialog.js.map +1 -0
- package/src/lib/components/lost-reason-dialog.d.ts +26 -0
- package/src/lib/components/lost-reason-dialog.js +95 -0
- package/src/lib/components/lost-reason-dialog.js.map +1 -0
- package/src/lib/components/new-contact-drawer.d.ts +78 -0
- package/src/lib/components/new-contact-drawer.js +343 -0
- package/src/lib/components/new-contact-drawer.js.map +1 -0
- package/src/lib/components/org-lead-surfaces-note.d.ts +57 -0
- package/src/lib/components/org-lead-surfaces-note.js +172 -0
- package/src/lib/components/org-lead-surfaces-note.js.map +1 -0
- package/src/lib/components/owner-avatar.d.ts +18 -0
- package/src/lib/components/owner-avatar.js +61 -0
- package/src/lib/components/owner-avatar.js.map +1 -0
- package/src/lib/components/pipeline-stages-dialog.d.ts +43 -0
- package/src/lib/components/pipeline-stages-dialog.js +339 -0
- package/src/lib/components/pipeline-stages-dialog.js.map +1 -0
- package/src/lib/components/pipelines-dialog.d.ts +55 -0
- package/src/lib/components/pipelines-dialog.js +517 -0
- package/src/lib/components/pipelines-dialog.js.map +1 -0
- package/src/lib/components/recent-activity-feed.d.ts +39 -0
- package/src/lib/components/recent-activity-feed.js +103 -0
- package/src/lib/components/recent-activity-feed.js.map +1 -0
- package/src/lib/components/recipes-card.d.ts +39 -0
- package/src/lib/components/recipes-card.js +485 -0
- package/src/lib/components/recipes-card.js.map +1 -0
- package/src/lib/components/record-activity-card.d.ts +26 -0
- package/src/lib/components/record-activity-card.js +121 -0
- package/src/lib/components/record-activity-card.js.map +1 -0
- package/src/lib/components/record-files-card.d.ts +67 -0
- package/src/lib/components/record-files-card.js +290 -0
- package/src/lib/components/record-files-card.js.map +1 -0
- package/src/lib/components/record-tasks-card.d.ts +32 -0
- package/src/lib/components/record-tasks-card.js +306 -0
- package/src/lib/components/record-tasks-card.js.map +1 -0
- package/src/lib/components/reports/activity-card.d.ts +57 -0
- package/src/lib/components/reports/activity-card.js +281 -0
- package/src/lib/components/reports/activity-card.js.map +1 -0
- package/src/lib/components/reports/closed-deals-card.d.ts +20 -0
- package/src/lib/components/reports/closed-deals-card.js +194 -0
- package/src/lib/components/reports/closed-deals-card.js.map +1 -0
- package/src/lib/components/reports/contacts-mix-card.d.ts +27 -0
- package/src/lib/components/reports/contacts-mix-card.js +161 -0
- package/src/lib/components/reports/contacts-mix-card.js.map +1 -0
- package/src/lib/components/reports/contacts-trend-card.d.ts +31 -0
- package/src/lib/components/reports/contacts-trend-card.js +144 -0
- package/src/lib/components/reports/contacts-trend-card.js.map +1 -0
- package/src/lib/components/reports/forecast-card.d.ts +22 -0
- package/src/lib/components/reports/forecast-card.js +251 -0
- package/src/lib/components/reports/forecast-card.js.map +1 -0
- package/src/lib/components/reports/lead-counts.d.ts +32 -0
- package/src/lib/components/reports/lead-counts.js +44 -0
- package/src/lib/components/reports/lead-counts.js.map +1 -0
- package/src/lib/components/reports/lead-funnel-card.d.ts +38 -0
- package/src/lib/components/reports/lead-funnel-card.js +375 -0
- package/src/lib/components/reports/lead-funnel-card.js.map +1 -0
- package/src/lib/components/reports/pipeline-card.d.ts +19 -0
- package/src/lib/components/reports/pipeline-card.js +338 -0
- package/src/lib/components/reports/pipeline-card.js.map +1 -0
- package/src/lib/components/reports/report-bar-chart.d.ts +39 -0
- package/src/lib/components/reports/report-bar-chart.js +133 -0
- package/src/lib/components/reports/report-bar-chart.js.map +1 -0
- package/src/lib/components/reports/report-breakdown.d.ts +32 -0
- package/src/lib/components/reports/report-breakdown.js +105 -0
- package/src/lib/components/reports/report-breakdown.js.map +1 -0
- package/src/lib/components/reports/report-export.d.ts +37 -0
- package/src/lib/components/reports/report-export.js +66 -0
- package/src/lib/components/reports/report-export.js.map +1 -0
- package/src/lib/components/reports/report-format.d.ts +36 -0
- package/src/lib/components/reports/report-format.js +43 -0
- package/src/lib/components/reports/report-format.js.map +1 -0
- package/src/lib/components/reports/report-scope.d.ts +81 -0
- package/src/lib/components/reports/report-scope.js +58 -0
- package/src/lib/components/reports/report-scope.js.map +1 -0
- package/src/lib/components/reports/report-stat-tile.d.ts +47 -0
- package/src/lib/components/reports/report-stat-tile.js +96 -0
- package/src/lib/components/reports/report-stat-tile.js.map +1 -0
- package/src/lib/components/reports/source-conversion-card.d.ts +28 -0
- package/src/lib/components/reports/source-conversion-card.js +205 -0
- package/src/lib/components/reports/source-conversion-card.js.map +1 -0
- package/src/lib/components/reports/tasks-card.d.ts +26 -0
- package/src/lib/components/reports/tasks-card.js +279 -0
- package/src/lib/components/reports/tasks-card.js.map +1 -0
- package/src/lib/components/reports/use-aggregate-read.d.ts +99 -0
- package/src/lib/components/reports/use-aggregate-read.js +195 -0
- package/src/lib/components/reports/use-aggregate-read.js.map +1 -0
- package/src/lib/components/reports/won-lost-by-owner-card.d.ts +30 -0
- package/src/lib/components/reports/won-lost-by-owner-card.js +168 -0
- package/src/lib/components/reports/won-lost-by-owner-card.js.map +1 -0
- package/src/lib/components/reports-section.d.ts +42 -0
- package/src/lib/components/reports-section.js +308 -0
- package/src/lib/components/reports-section.js.map +1 -0
- package/src/lib/components/sending-addresses-card.d.ts +49 -0
- package/src/lib/components/sending-addresses-card.js +262 -0
- package/src/lib/components/sending-addresses-card.js.map +1 -0
- package/src/lib/components/settings-section.d.ts +151 -0
- package/src/lib/components/settings-section.js +783 -0
- package/src/lib/components/settings-section.js.map +1 -0
- package/src/lib/components/task-cells.d.ts +51 -0
- package/src/lib/components/task-cells.js +139 -0
- package/src/lib/components/task-cells.js.map +1 -0
- package/src/lib/components/task-edit-drawer.d.ts +53 -0
- package/src/lib/components/task-edit-drawer.js +483 -0
- package/src/lib/components/task-edit-drawer.js.map +1 -0
- package/src/lib/components/task-import-drawer.d.ts +24 -0
- package/src/lib/components/task-import-drawer.js +82 -0
- package/src/lib/components/task-import-drawer.js.map +1 -0
- package/src/lib/components/task-snooze-menu.d.ts +65 -0
- package/src/lib/components/task-snooze-menu.js +207 -0
- package/src/lib/components/task-snooze-menu.js.map +1 -0
- package/src/lib/components/tasks-bulk-bar.d.ts +25 -0
- package/src/lib/components/tasks-bulk-bar.js +348 -0
- package/src/lib/components/tasks-bulk-bar.js.map +1 -0
- package/src/lib/components/tasks-calendar.d.ts +38 -0
- package/src/lib/components/tasks-calendar.js +228 -0
- package/src/lib/components/tasks-calendar.js.map +1 -0
- package/src/lib/components/tasks-section.d.ts +27 -0
- package/src/lib/components/tasks-section.js +579 -0
- package/src/lib/components/tasks-section.js.map +1 -0
- package/src/lib/components/use-contact-campaign-emails.d.ts +32 -0
- package/src/lib/components/use-contact-campaign-emails.js +83 -0
- package/src/lib/components/use-contact-campaign-emails.js.map +1 -0
- package/src/lib/components/use-crm-api.d.ts +44 -0
- package/src/lib/components/use-crm-api.js +84 -0
- package/src/lib/components/use-crm-api.js.map +1 -0
- package/src/lib/components/use-crm-inbound-address.d.ts +60 -0
- package/src/lib/components/use-crm-inbound-address.js +124 -0
- package/src/lib/components/use-crm-inbound-address.js.map +1 -0
- package/src/lib/components/use-emails-hub-path.d.ts +24 -0
- package/src/lib/components/use-emails-hub-path.js +59 -0
- package/src/lib/components/use-emails-hub-path.js.map +1 -0
- package/src/lib/components/use-member-email-aliases.d.ts +54 -0
- package/src/lib/components/use-member-email-aliases.js +186 -0
- package/src/lib/components/use-member-email-aliases.js.map +1 -0
- package/src/lib/components/use-org-members.d.ts +40 -0
- package/src/lib/components/use-org-members.js +100 -0
- package/src/lib/components/use-org-members.js.map +1 -0
- package/src/lib/constants/api-routes.d.ts +109 -0
- package/src/lib/constants/api-routes.js +74 -0
- package/src/lib/constants/api-routes.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +14 -0
- package/src/lib/constants/bundle-common.js +14 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/company-filters.d.ts +18 -0
- package/src/lib/constants/company-filters.js +51 -0
- package/src/lib/constants/company-filters.js.map +1 -0
- package/src/lib/constants/contact-filters.d.ts +38 -0
- package/src/lib/constants/contact-filters.js +294 -0
- package/src/lib/constants/contact-filters.js.map +1 -0
- package/src/lib/hooks/use-contact-field-definitions.d.ts +48 -0
- package/src/lib/hooks/use-contact-field-definitions.js +72 -0
- package/src/lib/hooks/use-contact-field-definitions.js.map +1 -0
- package/src/lib/hooks/use-contact-update.d.ts +25 -0
- package/src/lib/hooks/use-contact-update.js +80 -0
- package/src/lib/hooks/use-contact-update.js.map +1 -0
- package/src/lib/hooks/use-crm-activity-logger.d.ts +73 -0
- package/src/lib/hooks/use-crm-activity-logger.js +101 -0
- package/src/lib/hooks/use-crm-activity-logger.js.map +1 -0
- package/src/lib/hooks/use-crm-bulk-apply.d.ts +52 -0
- package/src/lib/hooks/use-crm-bulk-apply.js +112 -0
- package/src/lib/hooks/use-crm-bulk-apply.js.map +1 -0
- package/src/lib/hooks/use-crm-default-view.d.ts +24 -0
- package/src/lib/hooks/use-crm-default-view.js +64 -0
- package/src/lib/hooks/use-crm-default-view.js.map +1 -0
- package/src/lib/hooks/use-crm-email-templates.d.ts +59 -0
- package/src/lib/hooks/use-crm-email-templates.js +103 -0
- package/src/lib/hooks/use-crm-email-templates.js.map +1 -0
- package/src/lib/hooks/use-crm-hub-path.d.ts +29 -0
- package/src/lib/hooks/use-crm-hub-path.js +41 -0
- package/src/lib/hooks/use-crm-hub-path.js.map +1 -0
- package/src/lib/hooks/use-crm-org-mount.d.ts +97 -0
- package/src/lib/hooks/use-crm-org-mount.js +215 -0
- package/src/lib/hooks/use-crm-org-mount.js.map +1 -0
- package/src/lib/hooks/use-crm-record-names.d.ts +52 -0
- package/src/lib/hooks/use-crm-record-names.js +126 -0
- package/src/lib/hooks/use-crm-record-names.js.map +1 -0
- package/src/lib/hooks/use-crm-records-quota.d.ts +68 -0
- package/src/lib/hooks/use-crm-records-quota.js +118 -0
- package/src/lib/hooks/use-crm-records-quota.js.map +1 -0
- package/src/lib/hooks/use-crm-saved-view.d.ts +96 -0
- package/src/lib/hooks/use-crm-saved-view.js +329 -0
- package/src/lib/hooks/use-crm-saved-view.js.map +1 -0
- package/src/lib/hooks/use-crm-scope.d.ts +117 -0
- package/src/lib/hooks/use-crm-scope.js +147 -0
- package/src/lib/hooks/use-crm-scope.js.map +1 -0
- package/src/lib/hooks/use-crm-tasks.d.ts +85 -0
- package/src/lib/hooks/use-crm-tasks.js +153 -0
- package/src/lib/hooks/use-crm-tasks.js.map +1 -0
- package/src/lib/hooks/use-crm-view-grid.d.ts +55 -0
- package/src/lib/hooks/use-crm-view-grid.js +170 -0
- package/src/lib/hooks/use-crm-view-grid.js.map +1 -0
- package/src/lib/hooks/use-crm-views.d.ts +42 -0
- package/src/lib/hooks/use-crm-views.js +84 -0
- package/src/lib/hooks/use-crm-views.js.map +1 -0
- package/src/lib/hooks/use-deal-stage-api.d.ts +69 -0
- package/src/lib/hooks/use-deal-stage-api.js +78 -0
- package/src/lib/hooks/use-deal-stage-api.js.map +1 -0
- package/src/lib/hooks/use-deals.d.ts +47 -0
- package/src/lib/hooks/use-deals.js +105 -0
- package/src/lib/hooks/use-deals.js.map +1 -0
- package/src/lib/hooks/use-org-leads.d.ts +53 -0
- package/src/lib/hooks/use-org-leads.js +114 -0
- package/src/lib/hooks/use-org-leads.js.map +1 -0
- package/src/lib/hooks/use-org-member-directory.d.ts +36 -0
- package/src/lib/hooks/use-org-member-directory.js +116 -0
- package/src/lib/hooks/use-org-member-directory.js.map +1 -0
- package/src/lib/hooks/use-org-member-options.d.ts +38 -0
- package/src/lib/hooks/use-org-member-options.js +131 -0
- package/src/lib/hooks/use-org-member-options.js.map +1 -0
- package/src/lib/hooks/use-pipeline.d.ts +71 -0
- package/src/lib/hooks/use-pipeline.js +159 -0
- package/src/lib/hooks/use-pipeline.js.map +1 -0
- package/src/lib/model/companies-bulk-writes.d.ts +40 -0
- package/src/lib/model/companies-bulk-writes.js +103 -0
- package/src/lib/model/companies-bulk-writes.js.map +1 -0
- package/src/lib/model/companies-csv.d.ts +36 -0
- package/src/lib/model/companies-csv.js +38 -0
- package/src/lib/model/companies-csv.js.map +1 -0
- package/src/lib/model/companies.d.ts +99 -0
- package/src/lib/model/companies.js +168 -0
- package/src/lib/model/companies.js.map +1 -0
- package/src/lib/model/company-delete-route.d.ts +43 -0
- package/src/lib/model/company-delete-route.js +31 -0
- package/src/lib/model/company-delete-route.js.map +1 -0
- package/src/lib/model/company-delete.d.ts +42 -0
- package/src/lib/model/company-delete.js +52 -0
- package/src/lib/model/company-delete.js.map +1 -0
- package/src/lib/model/contact-duplicates.d.ts +58 -0
- package/src/lib/model/contact-duplicates.js +67 -0
- package/src/lib/model/contact-duplicates.js.map +1 -0
- package/src/lib/model/contact-record.d.ts +113 -0
- package/src/lib/model/contact-record.js +70 -0
- package/src/lib/model/contact-record.js.map +1 -0
- package/src/lib/model/contact-update.d.ts +93 -0
- package/src/lib/model/contact-update.js +50 -0
- package/src/lib/model/contact-update.js.map +1 -0
- package/src/lib/model/contacts-bulk-writes.d.ts +173 -0
- package/src/lib/model/contacts-bulk-writes.js +196 -0
- package/src/lib/model/contacts-bulk-writes.js.map +1 -0
- package/src/lib/model/contacts-csv.d.ts +54 -0
- package/src/lib/model/contacts-csv.js +67 -0
- package/src/lib/model/contacts-csv.js.map +1 -0
- package/src/lib/model/contacts-list-seed.d.ts +51 -0
- package/src/lib/model/contacts-list-seed.js +63 -0
- package/src/lib/model/contacts-list-seed.js.map +1 -0
- package/src/lib/model/crm-activity-report.d.ts +27 -0
- package/src/lib/model/crm-activity-report.js +56 -0
- package/src/lib/model/crm-activity-report.js.map +1 -0
- package/src/lib/model/crm-api.d.ts +49 -0
- package/src/lib/model/crm-api.js +47 -0
- package/src/lib/model/crm-api.js.map +1 -0
- package/src/lib/model/crm-bulk-writes.d.ts +147 -0
- package/src/lib/model/crm-bulk-writes.js +207 -0
- package/src/lib/model/crm-bulk-writes.js.map +1 -0
- package/src/lib/model/crm-company-import.d.ts +154 -0
- package/src/lib/model/crm-company-import.js +331 -0
- package/src/lib/model/crm-company-import.js.map +1 -0
- package/src/lib/model/crm-custom-draft.d.ts +62 -0
- package/src/lib/model/crm-custom-draft.js +67 -0
- package/src/lib/model/crm-custom-draft.js.map +1 -0
- package/src/lib/model/crm-deal-import.d.ts +112 -0
- package/src/lib/model/crm-deal-import.js +263 -0
- package/src/lib/model/crm-deal-import.js.map +1 -0
- package/src/lib/model/crm-import.d.ts +244 -0
- package/src/lib/model/crm-import.js +466 -0
- package/src/lib/model/crm-import.js.map +1 -0
- package/src/lib/model/crm-lead-import.d.ts +105 -0
- package/src/lib/model/crm-lead-import.js +255 -0
- package/src/lib/model/crm-lead-import.js.map +1 -0
- package/src/lib/model/crm-record-routes.d.ts +21 -0
- package/src/lib/model/crm-record-routes.js +70 -0
- package/src/lib/model/crm-record-routes.js.map +1 -0
- package/src/lib/model/crm-routes.d.ts +101 -0
- package/src/lib/model/crm-routes.js +92 -0
- package/src/lib/model/crm-routes.js.map +1 -0
- package/src/lib/model/crm-task-import.d.ts +94 -0
- package/src/lib/model/crm-task-import.js +275 -0
- package/src/lib/model/crm-task-import.js.map +1 -0
- package/src/lib/model/crm-view-param.d.ts +43 -0
- package/src/lib/model/crm-view-param.js +49 -0
- package/src/lib/model/crm-view-param.js.map +1 -0
- package/src/lib/model/deal-board-model.d.ts +241 -0
- package/src/lib/model/deal-board-model.js +439 -0
- package/src/lib/model/deal-board-model.js.map +1 -0
- package/src/lib/model/deal-form-model.d.ts +114 -0
- package/src/lib/model/deal-form-model.js +218 -0
- package/src/lib/model/deal-form-model.js.map +1 -0
- package/src/lib/model/deals-csv.d.ts +32 -0
- package/src/lib/model/deals-csv.js +37 -0
- package/src/lib/model/deals-csv.js.map +1 -0
- package/src/lib/model/import-column-shapes.d.ts +36 -0
- package/src/lib/model/import-column-shapes.js +76 -0
- package/src/lib/model/import-column-shapes.js.map +1 -0
- package/src/lib/model/lead-company-suggestion.d.ts +61 -0
- package/src/lib/model/lead-company-suggestion.js +65 -0
- package/src/lib/model/lead-company-suggestion.js.map +1 -0
- package/src/lib/model/lead-filters.d.ts +29 -0
- package/src/lib/model/lead-filters.js +39 -0
- package/src/lib/model/lead-filters.js.map +1 -0
- package/src/lib/model/lead-surfaces.d.ts +58 -0
- package/src/lib/model/lead-surfaces.js +67 -0
- package/src/lib/model/lead-surfaces.js.map +1 -0
- package/src/lib/model/leads-csv.d.ts +40 -0
- package/src/lib/model/leads-csv.js +40 -0
- package/src/lib/model/leads-csv.js.map +1 -0
- package/src/lib/model/next-activity-api.d.ts +31 -0
- package/src/lib/model/next-activity-api.js +57 -0
- package/src/lib/model/next-activity-api.js.map +1 -0
- package/src/lib/model/next-activity.d.ts +64 -0
- package/src/lib/model/next-activity.js +47 -0
- package/src/lib/model/next-activity.js.map +1 -0
- package/src/lib/model/person-key-web.d.ts +43 -0
- package/src/lib/model/person-key-web.js +52 -0
- package/src/lib/model/person-key-web.js.map +1 -0
- package/src/lib/model/record-facts.d.ts +282 -0
- package/src/lib/model/record-facts.js +434 -0
- package/src/lib/model/record-facts.js.map +1 -0
- package/src/lib/model/task-api.d.ts +28 -0
- package/src/lib/model/task-api.js +57 -0
- package/src/lib/model/task-api.js.map +1 -0
- package/src/lib/model/task-calendar.d.ts +108 -0
- package/src/lib/model/task-calendar.js +139 -0
- package/src/lib/model/task-calendar.js.map +1 -0
- package/src/lib/model/task-routes.d.ts +177 -0
- package/src/lib/model/task-routes.js +197 -0
- package/src/lib/model/task-routes.js.map +1 -0
- package/src/lib/model/task-scope.d.ts +45 -0
- package/src/lib/model/task-scope.js +51 -0
- package/src/lib/model/task-scope.js.map +1 -0
- package/src/lib/model/task-views.d.ts +149 -0
- package/src/lib/model/task-views.js +286 -0
- package/src/lib/model/task-views.js.map +1 -0
- package/src/lib/model/tasks-csv.d.ts +28 -0
- package/src/lib/model/tasks-csv.js +28 -0
- package/src/lib/model/tasks-csv.js.map +1 -0
- package/src/lib/plugin.d.ts +32 -0
- package/src/lib/plugin.js +208 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server/companies-import.d.ts +57 -0
- package/src/lib/server/companies-import.js +242 -0
- package/src/lib/server/companies-import.js.map +1 -0
- package/src/lib/server/company-delete.d.ts +59 -0
- package/src/lib/server/company-delete.js +146 -0
- package/src/lib/server/company-delete.js.map +1 -0
- package/src/lib/server/contact-email-history.d.ts +82 -0
- package/src/lib/server/contact-email-history.js +264 -0
- package/src/lib/server/contact-email-history.js.map +1 -0
- package/src/lib/server/contact-profile.d.ts +41 -0
- package/src/lib/server/contact-profile.js +45 -0
- package/src/lib/server/contact-profile.js.map +1 -0
- package/src/lib/server/contact-update.d.ts +92 -0
- package/src/lib/server/contact-update.js +512 -0
- package/src/lib/server/contact-update.js.map +1 -0
- package/src/lib/server/contacts-import.d.ts +73 -0
- package/src/lib/server/contacts-import.js +263 -0
- package/src/lib/server/contacts-import.js.map +1 -0
- package/src/lib/server/contacts-merge.d.ts +86 -0
- package/src/lib/server/contacts-merge.js +206 -0
- package/src/lib/server/contacts-merge.js.map +1 -0
- package/src/lib/server/deals-import.d.ts +76 -0
- package/src/lib/server/deals-import.js +246 -0
- package/src/lib/server/deals-import.js.map +1 -0
- package/src/lib/server/email-send.d.ts +119 -0
- package/src/lib/server/email-send.js +667 -0
- package/src/lib/server/email-send.js.map +1 -0
- package/src/lib/server/email-template-duplicate.d.ts +19 -0
- package/src/lib/server/email-template-duplicate.js +206 -0
- package/src/lib/server/email-template-duplicate.js.map +1 -0
- package/src/lib/server/erase-person.d.ts +108 -0
- package/src/lib/server/erase-person.js +309 -0
- package/src/lib/server/erase-person.js.map +1 -0
- package/src/lib/server/import-context.d.ts +85 -0
- package/src/lib/server/import-context.js +181 -0
- package/src/lib/server/import-context.js.map +1 -0
- package/src/lib/server/inbound-address.d.ts +61 -0
- package/src/lib/server/inbound-address.js +188 -0
- package/src/lib/server/inbound-address.js.map +1 -0
- package/src/lib/server/lead-convert.d.ts +78 -0
- package/src/lib/server/lead-convert.js +250 -0
- package/src/lib/server/lead-convert.js.map +1 -0
- package/src/lib/server/leads-import.d.ts +84 -0
- package/src/lib/server/leads-import.js +261 -0
- package/src/lib/server/leads-import.js.map +1 -0
- package/src/lib/server/next-activity-routes.d.ts +33 -0
- package/src/lib/server/next-activity-routes.js +110 -0
- package/src/lib/server/next-activity-routes.js.map +1 -0
- package/src/lib/server/org-activity.d.ts +61 -0
- package/src/lib/server/org-activity.js +120 -0
- package/src/lib/server/org-activity.js.map +1 -0
- package/src/lib/server/org-caller.d.ts +110 -0
- package/src/lib/server/org-caller.js +154 -0
- package/src/lib/server/org-caller.js.map +1 -0
- package/src/lib/server/recipe-routes.d.ts +75 -0
- package/src/lib/server/recipe-routes.js +442 -0
- package/src/lib/server/recipe-routes.js.map +1 -0
- package/src/lib/server/record-facts.d.ts +65 -0
- package/src/lib/server/record-facts.js +337 -0
- package/src/lib/server/record-facts.js.map +1 -0
- package/src/lib/server/record-timeline.d.ts +51 -0
- package/src/lib/server/record-timeline.js +215 -0
- package/src/lib/server/record-timeline.js.map +1 -0
- package/src/lib/server/suite-gate.d.ts +42 -0
- package/src/lib/server/suite-gate.js +87 -0
- package/src/lib/server/suite-gate.js.map +1 -0
- package/src/lib/server/task-routes.d.ts +132 -0
- package/src/lib/server/task-routes.js +699 -0
- package/src/lib/server/task-routes.js.map +1 -0
- package/src/lib/server/tasks-import.d.ts +54 -0
- package/src/lib/server/tasks-import.js +157 -0
- package/src/lib/server/tasks-import.js.map +1 -0
- package/src/lib/server-deal-stage.d.ts +88 -0
- package/src/lib/server-deal-stage.js +316 -0
- package/src/lib/server-deal-stage.js.map +1 -0
- package/src/lib/server.d.ts +149 -0
- package/src/lib/server.js +615 -0
- package/src/lib/server.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/server/record-timeline.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n registerPluginRecordTimelineWriter,\n type PluginRecordActivityRequest,\n type PluginRecordEntryContext,\n type PluginRecordTaskRequest,\n type PluginRecordTimelineWriter,\n type PluginRecordWrite,\n} from '@aglyn/aglyn/plugin-manager/plugin-record-timeline'\nimport {\n buildCrmCapturedEmailActivity,\n checkEntitlement,\n consentGroupForHost,\n CRM_ACTIVITY_LOG_FULL_MESSAGE,\n CRM_COLLECTIONS,\n crmActivityLogHasRoom,\n crmCapturedEmailKey,\n crmScopeTokens,\n crmTaskReminderAfterEdit,\n isCrmActivityKind,\n isCrmTaskKind,\n type CrmActivity,\n type CrmActivityLink,\n type CrmTask,\n} from '@aglyn/aglyn/server'\nimport {\n countCrmActivitiesForRecord,\n createCrmEmailActivity,\n crmActivityRef,\n crmCapturedEmailActivityRef,\n firebaseAdmin,\n recomputeCrmNextTaskAt,\n} from '@aglyn/tenant-data-admin'\nimport { createHash } from 'crypto'\nimport { FieldValue } from 'firebase-admin/firestore'\nimport { BUNDLE_ID } from '../constants/bundle-common'\nimport { CRM_SUITE_FEATURE } from './suite-gate'\n\n/**\n * THE CRM'S WRITER ON THE CORE'S RECORD-TIMELINE SEAM (AGL-2981).\n *\n * Another plugin files an activity or a task on a contact, company or deal —\n * an email a sequence sent, the reply it read, the call it asks for — and\n * this writes it as the CRM writes its own:\n *\n * 1. the workspace's plan carries the CRM (`features.crm`), as at every\n * CRM door; a Free workspace keeps no records to file on;\n * 2. the entry carries the scope a record made on that site carries\n * (`crmScopeTokens`), so exactly the people who see the record see it;\n * 3. an EMAIL is filed under the id the capture address files a copy of the\n * same message by (`cap_` + the digest of its `Message-ID`), and written\n * with `create()`: the send, a copy the rep forwarded to the capture\n * address, and a second run of the caller are one row;\n * 4. anything else — a note, a task — is filed under the caller's own key,\n * hashed with the caller's plugin id, and written once the same way;\n * 5. a record at its activity ceiling is refused with the sentence every\n * CRM writer answers with, before anything is written.\n *\n * Each entry names the plugin that filed it (`sourcePluginId`), and a task's\n * `nextTaskAtMs` is recomputed on the records it names, as every server\n * writer of a task does.\n */\n\ntype Firestore = FirebaseFirestore.Firestore\n\nexport interface CrmRecordTimelineDeps {\n firestore(): Firestore\n}\n\n/** gRPC `ALREADY_EXISTS`, which `create()` rejects with when the document is there. */\nconst ALREADY_EXISTS = 6\n\n/** The longest task title the CRM keeps, as its own forms do. */\nconst TASK_TITLE_MAX = 200\n/** The longest note body or task note an entry filed here keeps. */\nconst NOTE_MAX = 2_000\n\nconst refuse = (status: 400 | 403 | 404 | 409, error: string): PluginRecordWrite => ({\n ok: false,\n status,\n error,\n})\n\n/** The record fields of a link, only the ones it names. */\nfunction linkFields(link: PluginRecordEntryContext['link']): CrmActivityLink {\n return {\n ...(link?.contactId ? { contactId: String(link.contactId) } : {}),\n ...(link?.companyId ? { companyId: String(link.companyId) } : {}),\n ...(link?.dealId ? { dealId: String(link.dealId) } : {}),\n }\n}\n\n/** The document id a caller's key files under: its own namespace, never a raw key. */\nfunction keyedId(sourcePluginId: string, key: string): string {\n return `plg_${createHash('sha256').update(`${sourcePluginId}:${key}`).digest('hex').slice(0, 28)}`\n}\n\nexport function createCrmRecordTimelineWriter(deps: CrmRecordTimelineDeps): PluginRecordTimelineWriter {\n /** The org, its plan, the link and the scope an entry is stamped with. */\n async function admit(\n context: PluginRecordEntryContext,\n ): Promise<\n | PluginRecordWrite\n | { firestore: Firestore; orgRef: FirebaseFirestore.DocumentReference; link: CrmActivityLink; visibleTo: string[] }\n > {\n const orgId = String(context.orgId ?? '').trim()\n const hostId = String(context.hostId ?? '').trim()\n const link = linkFields(context.link)\n if (!orgId || !hostId || !String(context.sourcePluginId ?? '').trim()) {\n return refuse(400, 'An entry names its organization, its site and the plugin filing it.')\n }\n if (!link.contactId && !link.companyId && !link.dealId) {\n return refuse(400, 'An entry is filed on a contact, a company or a deal.')\n }\n const firestore = deps.firestore()\n const orgRef = firestore.collection('orgs').doc(orgId)\n const snapshot = await orgRef.get()\n if (!snapshot.exists) return refuse(404, 'That organization no longer exists.')\n const org = (snapshot.data() ?? {}) as Record<string, unknown>\n if (!checkEntitlement(org, CRM_SUITE_FEATURE)) {\n return refuse(403, \"This workspace's plan doesn't include the CRM.\")\n }\n return {\n firestore,\n orgRef,\n link,\n visibleTo: crmScopeTokens(org, consentGroupForHost(org, hostId)),\n }\n }\n\n /** Creates a keyed entry once: `created: false` for one already filed. */\n async function createOnce(\n ref: FirebaseFirestore.DocumentReference,\n data: Record<string, unknown>,\n ): Promise<boolean> {\n try {\n await ref.create({\n ...data,\n createdAt: FieldValue.serverTimestamp(),\n updatedAt: FieldValue.serverTimestamp(),\n })\n return true\n } catch (error) {\n if ((error as { code?: unknown })?.code === ALREADY_EXISTS) return false\n throw error\n }\n }\n\n return {\n async logActivity(request: PluginRecordActivityRequest): Promise<PluginRecordWrite> {\n if (!isCrmActivityKind(request.kind)) return refuse(400, `\"${String(request.kind)}\" isn't an activity.`)\n const admitted = await admit(request)\n if ('ok' in admitted) return admitted\n const { firestore, orgRef, link, visibleTo } = admitted\n const orgId = orgRef.id\n\n let ref: FirebaseFirestore.DocumentReference\n let activity: CrmActivity\n if (request.kind === 'email') {\n const email = request.email\n const key = email ? crmCapturedEmailKey(email.messageId, null) : null\n if (!email || !key) return refuse(400, 'An email is filed by its Message-ID.')\n ref = crmCapturedEmailActivityRef(firestore, orgId, key)\n activity = buildCrmCapturedEmailActivity({\n direction: email.direction === 'inbound' ? 'inbound' : 'outbound',\n subject: email.subject,\n excerpt: request.body,\n from: email.from,\n to: email.to,\n messageId: email.messageId,\n inReplyTo: email.inReplyTo ?? null,\n atMs: request.atMs,\n byUid: String(request.byUid ?? ''),\n byName: request.byName ?? null,\n link,\n hostId: request.hostId,\n visibleTo,\n })\n } else {\n const key = String(request.dedupeKey ?? '').trim()\n if (!key) return refuse(400, 'An entry that is not an email names its own key.')\n ref = crmActivityRef(firestore, orgId, keyedId(request.sourcePluginId, key))\n const byName = String(request.byName ?? '').trim()\n activity = {\n kind: request.kind,\n body: String(request.body ?? '').slice(0, NOTE_MAX),\n atMs: request.atMs,\n byUid: String(request.byUid ?? ''),\n ...(byName ? { byName } : {}),\n ...link,\n hostId: request.hostId,\n visibleTo,\n }\n }\n // Filed before: answered off the one read, ahead of the ceiling's count.\n if ((await ref.get()).exists) return { ok: true, id: ref.id, created: false }\n if (!crmActivityLogHasRoom(await countCrmActivitiesForRecord(orgRef, link))) {\n return refuse(409, CRM_ACTIVITY_LOG_FULL_MESSAGE)\n }\n const stamped = { ...activity, sourcePluginId: request.sourcePluginId }\n const created =\n request.kind === 'email'\n ? (await createCrmEmailActivity(ref, stamped)) === 'created'\n : await createOnce(ref, stamped as unknown as Record<string, unknown>)\n return { ok: true, id: ref.id, created }\n },\n\n async createTask(request: PluginRecordTaskRequest): Promise<PluginRecordWrite> {\n const title = String(request.title ?? '').replace(/\\s+/g, ' ').trim().slice(0, TASK_TITLE_MAX)\n const key = String(request.dedupeKey ?? '').trim()\n if (!title || !key) return refuse(400, 'A task has a title and the caller’s own key.')\n if (!isCrmTaskKind(request.kind)) return refuse(400, `\"${String(request.kind)}\" isn't a task.`)\n if (!Number.isFinite(request.dueAtMs)) return refuse(400, 'A task has a due time.')\n const admitted = await admit(request)\n if ('ok' in admitted) return admitted\n const { firestore, orgRef, link, visibleTo } = admitted\n const ref = orgRef.collection(CRM_COLLECTIONS.tasks).doc(keyedId(request.sourcePluginId, key))\n const notes = String(request.notes ?? '').trim().slice(0, NOTE_MAX)\n const assigneeUid = String(request.assigneeUid ?? '').trim()\n const task: CrmTask = {\n title,\n ...(notes ? { notes } : {}),\n kind: request.kind,\n priority: 'normal',\n status: 'open',\n dueAtMs: request.dueAtMs,\n // The reminder a person's task gets (AGL-2659): the due time.\n remindAtMs: crmTaskReminderAfterEdit({ dueAtMs: request.dueAtMs, previous: null }),\n ...(assigneeUid ? { assigneeUid } : {}),\n createdByUid: String(request.createdByUid ?? ''),\n sourcePluginId: request.sourcePluginId,\n ...link,\n hostId: request.hostId,\n visibleTo,\n }\n const created = await createOnce(ref, task as unknown as Record<string, unknown>)\n if (created) {\n // The records the task names carry `nextTaskAtMs` (AGL-2661); a figure\n // that could not move is the Fields section's recompute's.\n await recomputeCrmNextTaskAt(firestore, orgRef.id, [link]).catch((error: unknown) => {\n console.error('[crm] next activity could not be recomputed', orgRef.id, error)\n })\n }\n return { ok: true, id: ref.id, created }\n },\n }\n}\n\n/** The platform's own dependencies. Specs build their own. */\nexport function defaultCrmRecordTimelineDeps(): CrmRecordTimelineDeps {\n return { firestore: () => firebaseAdmin.app().firestore() }\n}\n\n/** Registers the CRM as the workspace's record system on the timeline seam. */\nexport function registerCrmRecordTimelineWriter(\n deps: CrmRecordTimelineDeps = defaultCrmRecordTimelineDeps(),\n): void {\n registerPluginRecordTimelineWriter(createCrmRecordTimelineWriter(deps), { pluginId: BUNDLE_ID })\n}\n"],"names":["registerPluginRecordTimelineWriter","buildCrmCapturedEmailActivity","checkEntitlement","consentGroupForHost","CRM_ACTIVITY_LOG_FULL_MESSAGE","CRM_COLLECTIONS","crmActivityLogHasRoom","crmCapturedEmailKey","crmScopeTokens","crmTaskReminderAfterEdit","isCrmActivityKind","isCrmTaskKind","countCrmActivitiesForRecord","createCrmEmailActivity","crmActivityRef","crmCapturedEmailActivityRef","firebaseAdmin","recomputeCrmNextTaskAt","createHash","FieldValue","BUNDLE_ID","CRM_SUITE_FEATURE","ALREADY_EXISTS","TASK_TITLE_MAX","NOTE_MAX","refuse","status","error","ok","linkFields","link","contactId","String","companyId","dealId","keyedId","sourcePluginId","key","update","digest","slice","createCrmRecordTimelineWriter","deps","admit","context","snapshot","orgId","trim","hostId","firestore","orgRef","collection","doc","get","exists","org","data","visibleTo","createOnce","ref","create","createdAt","serverTimestamp","updatedAt","code","logActivity","request","kind","admitted","id","activity","email","messageId","direction","subject","excerpt","body","from","to","inReplyTo","atMs","byUid","byName","dedupeKey","created","stamped","createTask","title","replace","Number","isFinite","dueAtMs","tasks","notes","assigneeUid","task","priority","remindAtMs","previous","createdByUid","catch","console","defaultCrmRecordTimelineDeps","app","registerCrmRecordTimelineWriter","pluginId"],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
/** The entitlement the suite is sold under — the REST refusal's `error.code`. */
|
|
18
|
+
export declare const CRM_SUITE_FEATURE = "crm";
|
|
19
|
+
/** The REST refusal's `error.type`, as a console route's `reason`. */
|
|
20
|
+
export declare const CRM_SUITE_REFUSAL_REASON = "plan_required";
|
|
21
|
+
/** What a route answers a workspace whose plan does not carry the suite. */
|
|
22
|
+
export interface CrmSuiteRefusal {
|
|
23
|
+
status: 403;
|
|
24
|
+
body: {
|
|
25
|
+
error: string;
|
|
26
|
+
reason: typeof CRM_SUITE_REFUSAL_REASON;
|
|
27
|
+
code: typeof CRM_SUITE_FEATURE;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The refusal's sentence, for an act named as a phrase that takes "is" —
|
|
32
|
+
* "Importing a CSV file", "A CRM recipe".
|
|
33
|
+
*/
|
|
34
|
+
export declare function crmSuiteRefusalMessage(act: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* `null` when the org's plan carries the suite, else the refusal to send.
|
|
37
|
+
*
|
|
38
|
+
* Resolved through `checkEntitlement`, so a per-org
|
|
39
|
+
* `entitlements.features.crm` grant or revocation, and a paid plan whose
|
|
40
|
+
* subscription has died, answer here exactly as they answer everywhere else.
|
|
41
|
+
*/
|
|
42
|
+
export declare function crmSuiteRefusal(org: unknown, act: string): CrmSuiteRefusal | null;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ /**
|
|
17
|
+
* THE CRM'S PLAN GATE, for the routes the console calls (AGL-2787, AGL-2851).
|
|
18
|
+
*
|
|
19
|
+
* The CRM is included from Starter: `features.crm` is false on Free, and a
|
|
20
|
+
* Free workspace has none of it — no section, no read and no write. Three
|
|
21
|
+
* other doors onto the CRM's records ask the same question: the shell draws
|
|
22
|
+
* every CRM section locked and refuses its body, the `/v1` dispatcher refuses
|
|
23
|
+
* the CRM's resources, and the Firestore rules refuse a client's CRM writes.
|
|
24
|
+
* These routes are the fourth door, and every `crm/*` read and write asks it.
|
|
25
|
+
* A lock drawn on a page is advice to a script holding a member's token, so
|
|
26
|
+
* the same question is asked where the read or the write happens.
|
|
27
|
+
*
|
|
28
|
+
* ## What is never asked
|
|
29
|
+
*
|
|
30
|
+
* Capture — a form, a sign-up, a booking, an order — does not come through
|
|
31
|
+
* these routes, and records what it records on every plan. The compliance
|
|
32
|
+
* doors are every plan's too: `crm/erase-person`, and the contacts and leads
|
|
33
|
+
* files of `/api/crm/export`, because exporting and erasing the people a
|
|
34
|
+
* workspace holds are obligations rather than CRM features.
|
|
35
|
+
*
|
|
36
|
+
* ## After authorization, never before
|
|
37
|
+
*
|
|
38
|
+
* Each route asks once it knows who is calling and has read the org to
|
|
39
|
+
* answer that — the order the shell refuses in. A reader who may not open a
|
|
40
|
+
* surface is not shown its upgrade path, and a caller with no standing in
|
|
41
|
+
* the workspace learns nothing about its plan.
|
|
42
|
+
*
|
|
43
|
+
* ## One refusal shape
|
|
44
|
+
*
|
|
45
|
+
* 403, as the REST refusal is, with its two machine-readable facts in the
|
|
46
|
+
* console routes' flat body: `reason: 'plan_required'` is the REST
|
|
47
|
+
* `error.type` and `code: 'crm'` its `error.code`. Beside them, a sentence
|
|
48
|
+
* the console relays unchanged, as it relays every route refusal. The plan
|
|
49
|
+
* it names comes from the plan tables, so it cannot name a tier that has
|
|
50
|
+
* stopped carrying the suite.
|
|
51
|
+
*
|
|
52
|
+
* ## Staff are refused too
|
|
53
|
+
*
|
|
54
|
+
* The plan is a fact about the workspace, not about the person asking. A
|
|
55
|
+
* support engineer acting inside a Free workspace would otherwise create
|
|
56
|
+
* suite records that the workspace then holds without the suite.
|
|
57
|
+
*/ import { checkEntitlement, planLabelGrantingFeature } from "@aglyn/aglyn/server";
|
|
58
|
+
/** The entitlement the suite is sold under — the REST refusal's `error.code`. */ export const CRM_SUITE_FEATURE = 'crm';
|
|
59
|
+
/** The REST refusal's `error.type`, as a console route's `reason`. */ export const CRM_SUITE_REFUSAL_REASON = 'plan_required';
|
|
60
|
+
/**
|
|
61
|
+
* The refusal's sentence, for an act named as a phrase that takes "is" —
|
|
62
|
+
* "Importing a CSV file", "A CRM recipe".
|
|
63
|
+
*/ export function crmSuiteRefusalMessage(act) {
|
|
64
|
+
const plan = planLabelGrantingFeature(CRM_SUITE_FEATURE);
|
|
65
|
+
return `${act} is part of the CRM, which is not included in your current ` + 'plan. Manage your plan and add-ons from Billing.' + (plan ? ` Included from ${plan}.` : '');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* `null` when the org's plan carries the suite, else the refusal to send.
|
|
69
|
+
*
|
|
70
|
+
* Resolved through `checkEntitlement`, so a per-org
|
|
71
|
+
* `entitlements.features.crm` grant or revocation, and a paid plan whose
|
|
72
|
+
* subscription has died, answer here exactly as they answer everywhere else.
|
|
73
|
+
*/ export function crmSuiteRefusal(org, act) {
|
|
74
|
+
if (checkEntitlement(org, CRM_SUITE_FEATURE)) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
status: 403,
|
|
79
|
+
body: {
|
|
80
|
+
error: crmSuiteRefusalMessage(act),
|
|
81
|
+
reason: CRM_SUITE_REFUSAL_REASON,
|
|
82
|
+
code: CRM_SUITE_FEATURE
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//# sourceMappingURL=suite-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/server/suite-gate.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * THE CRM'S PLAN GATE, for the routes the console calls (AGL-2787, AGL-2851).\n *\n * The CRM is included from Starter: `features.crm` is false on Free, and a\n * Free workspace has none of it — no section, no read and no write. Three\n * other doors onto the CRM's records ask the same question: the shell draws\n * every CRM section locked and refuses its body, the `/v1` dispatcher refuses\n * the CRM's resources, and the Firestore rules refuse a client's CRM writes.\n * These routes are the fourth door, and every `crm/*` read and write asks it.\n * A lock drawn on a page is advice to a script holding a member's token, so\n * the same question is asked where the read or the write happens.\n *\n * ## What is never asked\n *\n * Capture — a form, a sign-up, a booking, an order — does not come through\n * these routes, and records what it records on every plan. The compliance\n * doors are every plan's too: `crm/erase-person`, and the contacts and leads\n * files of `/api/crm/export`, because exporting and erasing the people a\n * workspace holds are obligations rather than CRM features.\n *\n * ## After authorization, never before\n *\n * Each route asks once it knows who is calling and has read the org to\n * answer that — the order the shell refuses in. A reader who may not open a\n * surface is not shown its upgrade path, and a caller with no standing in\n * the workspace learns nothing about its plan.\n *\n * ## One refusal shape\n *\n * 403, as the REST refusal is, with its two machine-readable facts in the\n * console routes' flat body: `reason: 'plan_required'` is the REST\n * `error.type` and `code: 'crm'` its `error.code`. Beside them, a sentence\n * the console relays unchanged, as it relays every route refusal. The plan\n * it names comes from the plan tables, so it cannot name a tier that has\n * stopped carrying the suite.\n *\n * ## Staff are refused too\n *\n * The plan is a fact about the workspace, not about the person asking. A\n * support engineer acting inside a Free workspace would otherwise create\n * suite records that the workspace then holds without the suite.\n */\n\nimport { checkEntitlement, planLabelGrantingFeature } from '@aglyn/aglyn/server'\n\n/** The entitlement the suite is sold under — the REST refusal's `error.code`. */\nexport const CRM_SUITE_FEATURE = 'crm'\n\n/** The REST refusal's `error.type`, as a console route's `reason`. */\nexport const CRM_SUITE_REFUSAL_REASON = 'plan_required'\n\n/** What a route answers a workspace whose plan does not carry the suite. */\nexport interface CrmSuiteRefusal {\n status: 403\n body: {\n error: string\n reason: typeof CRM_SUITE_REFUSAL_REASON\n code: typeof CRM_SUITE_FEATURE\n }\n}\n\n/**\n * The refusal's sentence, for an act named as a phrase that takes \"is\" —\n * \"Importing a CSV file\", \"A CRM recipe\".\n */\nexport function crmSuiteRefusalMessage(act: string): string {\n const plan = planLabelGrantingFeature(CRM_SUITE_FEATURE)\n return (\n `${act} is part of the CRM, which is not included in your current ` +\n 'plan. Manage your plan and add-ons from Billing.' +\n (plan ? ` Included from ${plan}.` : '')\n )\n}\n\n/**\n * `null` when the org's plan carries the suite, else the refusal to send.\n *\n * Resolved through `checkEntitlement`, so a per-org\n * `entitlements.features.crm` grant or revocation, and a paid plan whose\n * subscription has died, answer here exactly as they answer everywhere else.\n */\nexport function crmSuiteRefusal(org: unknown, act: string): CrmSuiteRefusal | null {\n if (checkEntitlement(org as Parameters<typeof checkEntitlement>[0], CRM_SUITE_FEATURE)) {\n return null\n }\n return {\n status: 403,\n body: {\n error: crmSuiteRefusalMessage(act),\n reason: CRM_SUITE_REFUSAL_REASON,\n code: CRM_SUITE_FEATURE,\n },\n }\n}\n"],"names":["checkEntitlement","planLabelGrantingFeature","CRM_SUITE_FEATURE","CRM_SUITE_REFUSAL_REASON","crmSuiteRefusalMessage","act","plan","crmSuiteRefusal","org","status","body","error","reason","code"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCC,GAED,SAASA,gBAAgB,EAAEC,wBAAwB,QAAQ,sBAAqB;AAEhF,+EAA+E,GAC/E,OAAO,MAAMC,oBAAoB,MAAK;AAEtC,oEAAoE,GACpE,OAAO,MAAMC,2BAA2B,gBAAe;AAYvD;;;CAGC,GACD,OAAO,SAASC,uBAAuBC,GAAW;IAChD,MAAMC,OAAOL,yBAAyBC;IACtC,OACE,GAAGG,IAAI,2DAA2D,CAAC,GACnE,qDACCC,CAAAA,OAAO,CAAC,eAAe,EAAEA,KAAK,CAAC,CAAC,GAAG,EAAC;AAEzC;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,gBAAgBC,GAAY,EAAEH,GAAW;IACvD,IAAIL,iBAAiBQ,KAA+CN,oBAAoB;QACtF,OAAO;IACT;IACA,OAAO;QACLO,QAAQ;QACRC,MAAM;YACJC,OAAOP,uBAAuBC;YAC9BO,QAAQT;YACRU,MAAMX;QACR;IACF;AACF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { type AglynOrgMember, type PluginApiHandler, type PluginApiRequest } from '@aglyn/aglyn/server';
|
|
18
|
+
import { type CrmRouteScope } from './org-caller';
|
|
19
|
+
/**
|
|
20
|
+
* The two things a task does that a browser must not do alone (AGL-2599).
|
|
21
|
+
*
|
|
22
|
+
* Every other task write is client-direct against the Firestore rules —
|
|
23
|
+
* reopening, deleting, the list's own reads. These two are routes because
|
|
24
|
+
* each has a side effect that lives outside the document:
|
|
25
|
+
*
|
|
26
|
+
* - SAVING a task assigned to somebody else NOTIFIES them, and a
|
|
27
|
+
* notification is an Admin-SDK write into another person's inbox. Rather
|
|
28
|
+
* than a client-direct write followed by a "please notify" call — two
|
|
29
|
+
* operations that can disagree about whether the task exists — the route
|
|
30
|
+
* persists the task itself and notifies from the same code path, so a
|
|
31
|
+
* notification can never announce a task that failed to save. It also
|
|
32
|
+
* stamps the scope, the provenance and the timestamps, which is one
|
|
33
|
+
* creator computing `visibleTo` rather than two.
|
|
34
|
+
*
|
|
35
|
+
* - COMPLETING a task EMITS the `taskCompleted` host event, which is what a
|
|
36
|
+
* workflow triggers on. A browser cannot run the workflow runner.
|
|
37
|
+
*
|
|
38
|
+
* Both authenticate the way the other console plugin routes do — the ID
|
|
39
|
+
* token in the `Authorization` header — and then ask the same two questions
|
|
40
|
+
* the rules ask of a `crmTasks` write: is this member allowed to write org
|
|
41
|
+
* data (`owner`/`admin`/`editor`, and `data.manage` resolved through their
|
|
42
|
+
* custom role), and can they reach THIS document's scope.
|
|
43
|
+
*
|
|
44
|
+
* ## The organization variant (AGL-2637)
|
|
45
|
+
*
|
|
46
|
+
* `{ orgId, … }` instead of a site: the org-level hub. The caller is
|
|
47
|
+
* authorized by the ORG — an org-wide member holding `data.manage`, the
|
|
48
|
+
* hub's own gate, never a site collaborator — and reaches every task the
|
|
49
|
+
* org holds, so no scope check is made against the document. A NEW task
|
|
50
|
+
* names the site it is filed from beside the org, or names none and is the
|
|
51
|
+
* organization's own: `hostId: null`, the org scope token alone. Completing
|
|
52
|
+
* emits on the task's OWN site, where its automations live; an
|
|
53
|
+
* organization task has none and emits nothing, as an uncaptured deal's
|
|
54
|
+
* stage change emits nothing.
|
|
55
|
+
*
|
|
56
|
+
* The org variant also takes a BATCH — `taskIds` to complete, `tasks` to
|
|
57
|
+
* save — so the org hub's bulk bar makes one request per action rather
|
|
58
|
+
* than one per task. Each task is answered on its own in `results`; the
|
|
59
|
+
* request as a whole is refused only for what refuses every task alike.
|
|
60
|
+
*/
|
|
61
|
+
export type Refusal = {
|
|
62
|
+
ok: false;
|
|
63
|
+
status: number;
|
|
64
|
+
body: {
|
|
65
|
+
error: string;
|
|
66
|
+
reason?: string;
|
|
67
|
+
code?: string;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export interface Writer {
|
|
71
|
+
ok: true;
|
|
72
|
+
uid: string;
|
|
73
|
+
staff: boolean;
|
|
74
|
+
orgId: string;
|
|
75
|
+
org: Record<string, unknown>;
|
|
76
|
+
/** The member document under a site; `null` at the org level, where the reach is the org's. */
|
|
77
|
+
member: Partial<AglynOrgMember> | null;
|
|
78
|
+
level: CrmRouteScope['level'];
|
|
79
|
+
}
|
|
80
|
+
export declare const refuse: (status: number, error: string) => Refusal;
|
|
81
|
+
export interface CrmWriterOptions {
|
|
82
|
+
/**
|
|
83
|
+
* The act a plan without the CRM is refused for, named the way
|
|
84
|
+
* `crmSuiteRefusalMessage` takes it. `null` for a route that asks the plan
|
|
85
|
+
* itself, once it knows what the request writes, so the refusal can name
|
|
86
|
+
* that act — a contact update names the first field it carries. Tasks
|
|
87
|
+
* when unsaid.
|
|
88
|
+
*/
|
|
89
|
+
suiteAct?: string | null;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Who is asking, and whether they may write this CRM at all.
|
|
93
|
+
*
|
|
94
|
+
* Under a site: the org resolved from the site and the rules' own role and
|
|
95
|
+
* permission questions. At the organization level: the org the body names,
|
|
96
|
+
* for an org-wide member with the permission. The scope question — may they
|
|
97
|
+
* reach THIS task — is asked by the caller against the document, because on
|
|
98
|
+
* a create the document does not exist yet and its scope is what the route
|
|
99
|
+
* is about to stamp.
|
|
100
|
+
*/
|
|
101
|
+
export declare function authorizeCrmWriter(req: PluginApiRequest, scope: CrmRouteScope, options?: CrmWriterOptions): Promise<Writer | Refusal>;
|
|
102
|
+
/**
|
|
103
|
+
* The rules' `canReadScoped()`, for a document the route has in hand. An
|
|
104
|
+
* org-level writer was admitted as org-wide, and an org-wide member reads
|
|
105
|
+
* every row.
|
|
106
|
+
*/
|
|
107
|
+
export declare const canReach: (writer: Writer, visibleTo: unknown) => boolean;
|
|
108
|
+
/**
|
|
109
|
+
* `POST crm/task-save` — create or update a task, and tell its assignee.
|
|
110
|
+
*
|
|
111
|
+
* Body: `{ hostId, taskId?, task: CrmTaskFields }` under a site;
|
|
112
|
+
* `{ orgId, hostId?, taskId?, task }` at the organization level; or the
|
|
113
|
+
* org-level batch `{ orgId, tasks: [{ taskId, task }] }`. Answers
|
|
114
|
+
* `{ ok, taskId, notified }`, or `{ ok, results }` for the batch.
|
|
115
|
+
*
|
|
116
|
+
* The NOTIFICATION fires when the saved assignee is somebody other than the
|
|
117
|
+
* person saving AND is not who the task was already assigned to. Assigning
|
|
118
|
+
* a task to yourself is a note to self; re-saving a task's title does not
|
|
119
|
+
* re-announce it to the person who already has it. The assignee must be a
|
|
120
|
+
* member of the org — a uid nobody can find in the roster is refused rather
|
|
121
|
+
* than written, because a notification to a stranger's inbox is the one
|
|
122
|
+
* thing this route must never do.
|
|
123
|
+
*/
|
|
124
|
+
export declare const crmTaskSaveHandler: PluginApiHandler;
|
|
125
|
+
/**
|
|
126
|
+
* `POST crm/task-complete` — mark a task done and fire `taskCompleted`.
|
|
127
|
+
*
|
|
128
|
+
* Body: `{ hostId, taskId }` under a site, `{ orgId, taskId }` at the
|
|
129
|
+
* organization level, or the org-level batch `{ orgId, taskIds }`. Answers
|
|
130
|
+
* `{ ok, completedAtMs, alreadyDone? }`, or `{ ok, results }` for the batch.
|
|
131
|
+
*/
|
|
132
|
+
export declare const crmTaskCompleteHandler: PluginApiHandler;
|