@kelpie/server 0.7.0 → 0.9.0
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/dist/lib/consumerEmailDomains.d.ts +2 -0
- package/dist/lib/consumerEmailDomains.d.ts.map +1 -0
- package/dist/lib/consumerEmailDomains.js +62 -0
- package/dist/lib/consumerEmailDomains.js.map +1 -0
- package/dist/lib/email.d.ts +7 -0
- package/dist/lib/email.d.ts.map +1 -1
- package/dist/lib/email.js.map +1 -1
- package/dist/lib/emailContent.d.ts +33 -0
- package/dist/lib/emailContent.d.ts.map +1 -0
- package/dist/lib/emailContent.js +54 -0
- package/dist/lib/emailContent.js.map +1 -0
- package/dist/lib/emailDomainAutoLink.d.ts +27 -0
- package/dist/lib/emailDomainAutoLink.d.ts.map +1 -0
- package/dist/lib/emailDomainAutoLink.js +119 -0
- package/dist/lib/emailDomainAutoLink.js.map +1 -0
- package/dist/lib/ids.d.ts +13 -0
- package/dist/lib/ids.d.ts.map +1 -1
- package/dist/lib/ids.js +13 -0
- package/dist/lib/ids.js.map +1 -1
- package/dist/modules/activities/repository.d.ts.map +1 -1
- package/dist/modules/activities/repository.js +19 -20
- package/dist/modules/activities/repository.js.map +1 -1
- package/dist/modules/activities/wording.d.ts +12 -0
- package/dist/modules/activities/wording.d.ts.map +1 -1
- package/dist/modules/activities/wording.js +16 -0
- package/dist/modules/activities/wording.js.map +1 -1
- package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
- package/dist/modules/agent-tasks/catalog.js +62 -0
- package/dist/modules/agent-tasks/catalog.js.map +1 -1
- package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
- package/dist/modules/agent-tasks/resolve.js +42 -9
- package/dist/modules/agent-tasks/resolve.js.map +1 -1
- package/dist/modules/agent-tasks/routes.d.ts +2 -0
- package/dist/modules/agent-tasks/routes.d.ts.map +1 -1
- package/dist/modules/attachedRecords.d.ts +6 -1
- package/dist/modules/attachedRecords.d.ts.map +1 -1
- package/dist/modules/attachedRecords.js +18 -2
- package/dist/modules/attachedRecords.js.map +1 -1
- package/dist/modules/auth/preferences.d.ts +11 -1
- package/dist/modules/auth/preferences.d.ts.map +1 -1
- package/dist/modules/auth/preferences.js +11 -0
- package/dist/modules/auth/preferences.js.map +1 -1
- package/dist/modules/auth/routes.d.ts.map +1 -1
- package/dist/modules/auth/routes.js +18 -0
- package/dist/modules/auth/routes.js.map +1 -1
- package/dist/modules/auth/schema.d.ts +20 -0
- package/dist/modules/auth/schema.d.ts.map +1 -1
- package/dist/modules/auth/schema.js +11 -1
- package/dist/modules/auth/schema.js.map +1 -1
- package/dist/modules/auth/service.d.ts.map +1 -1
- package/dist/modules/auth/service.js +27 -3
- package/dist/modules/auth/service.js.map +1 -1
- package/dist/modules/companies/index.d.ts.map +1 -1
- package/dist/modules/companies/index.js +3 -1
- package/dist/modules/companies/index.js.map +1 -1
- package/dist/modules/companies/repository.d.ts +2 -0
- package/dist/modules/companies/repository.d.ts.map +1 -1
- package/dist/modules/companies/repository.js +1 -0
- package/dist/modules/companies/repository.js.map +1 -1
- package/dist/modules/companies/routes.d.ts +16 -0
- package/dist/modules/companies/routes.d.ts.map +1 -1
- package/dist/modules/companies/routes.js +18 -0
- package/dist/modules/companies/routes.js.map +1 -1
- package/dist/modules/companies/schema.d.ts +37 -0
- package/dist/modules/companies/schema.d.ts.map +1 -1
- package/dist/modules/companies/schema.js +10 -1
- package/dist/modules/companies/schema.js.map +1 -1
- package/dist/modules/companies/service.d.ts +6 -0
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +45 -11
- package/dist/modules/companies/service.js.map +1 -1
- package/dist/modules/consent-purposes/capabilities.d.ts +7 -0
- package/dist/modules/consent-purposes/capabilities.d.ts.map +1 -0
- package/dist/modules/consent-purposes/capabilities.js +10 -0
- package/dist/modules/consent-purposes/capabilities.js.map +1 -0
- package/dist/modules/consent-purposes/events.d.ts +38 -0
- package/dist/modules/consent-purposes/events.d.ts.map +1 -0
- package/dist/modules/consent-purposes/events.js +17 -0
- package/dist/modules/consent-purposes/events.js.map +1 -0
- package/dist/modules/consent-purposes/index.d.ts +13 -0
- package/dist/modules/consent-purposes/index.d.ts.map +1 -0
- package/dist/modules/consent-purposes/index.js +41 -0
- package/dist/modules/consent-purposes/index.js.map +1 -0
- package/dist/modules/consent-purposes/repository.d.ts +21 -0
- package/dist/modules/consent-purposes/repository.d.ts.map +1 -0
- package/dist/modules/consent-purposes/repository.js +98 -0
- package/dist/modules/consent-purposes/repository.js.map +1 -0
- package/dist/modules/consent-purposes/routes.d.ts +39 -0
- package/dist/modules/consent-purposes/routes.d.ts.map +1 -0
- package/dist/modules/consent-purposes/routes.js +79 -0
- package/dist/modules/consent-purposes/routes.js.map +1 -0
- package/dist/modules/consent-purposes/schema.d.ts +175 -0
- package/dist/modules/consent-purposes/schema.d.ts.map +1 -0
- package/dist/modules/consent-purposes/schema.js +35 -0
- package/dist/modules/consent-purposes/schema.js.map +1 -0
- package/dist/modules/consent-purposes/service.d.ts +50 -0
- package/dist/modules/consent-purposes/service.d.ts.map +1 -0
- package/dist/modules/consent-purposes/service.js +263 -0
- package/dist/modules/consent-purposes/service.js.map +1 -0
- package/dist/modules/consent-purposes/starters.d.ts +17 -0
- package/dist/modules/consent-purposes/starters.d.ts.map +1 -0
- package/dist/modules/consent-purposes/starters.js +15 -0
- package/dist/modules/consent-purposes/starters.js.map +1 -0
- package/dist/modules/consent-purposes/tools.d.ts +4 -0
- package/dist/modules/consent-purposes/tools.d.ts.map +1 -0
- package/dist/modules/consent-purposes/tools.js +29 -0
- package/dist/modules/consent-purposes/tools.js.map +1 -0
- package/dist/modules/core.d.ts.map +1 -1
- package/dist/modules/core.js +21 -0
- package/dist/modules/core.js.map +1 -1
- package/dist/modules/custom-fields/capabilities.d.ts +12 -0
- package/dist/modules/custom-fields/capabilities.d.ts.map +1 -0
- package/dist/modules/custom-fields/capabilities.js +15 -0
- package/dist/modules/custom-fields/capabilities.js.map +1 -0
- package/dist/modules/custom-fields/events.d.ts +49 -0
- package/dist/modules/custom-fields/events.d.ts.map +1 -0
- package/dist/modules/custom-fields/events.js +25 -0
- package/dist/modules/custom-fields/events.js.map +1 -0
- package/dist/modules/custom-fields/index.d.ts +19 -0
- package/dist/modules/custom-fields/index.d.ts.map +1 -0
- package/dist/modules/custom-fields/index.js +46 -0
- package/dist/modules/custom-fields/index.js.map +1 -0
- package/dist/modules/custom-fields/repository.d.ts +37 -0
- package/dist/modules/custom-fields/repository.d.ts.map +1 -0
- package/dist/modules/custom-fields/repository.js +144 -0
- package/dist/modules/custom-fields/repository.js.map +1 -0
- package/dist/modules/custom-fields/routes.d.ts +44 -0
- package/dist/modules/custom-fields/routes.d.ts.map +1 -0
- package/dist/modules/custom-fields/routes.js +103 -0
- package/dist/modules/custom-fields/routes.js.map +1 -0
- package/dist/modules/custom-fields/schema.d.ts +215 -0
- package/dist/modules/custom-fields/schema.d.ts.map +1 -0
- package/dist/modules/custom-fields/schema.js +43 -0
- package/dist/modules/custom-fields/schema.js.map +1 -0
- package/dist/modules/custom-fields/service.d.ts +57 -0
- package/dist/modules/custom-fields/service.d.ts.map +1 -0
- package/dist/modules/custom-fields/service.js +273 -0
- package/dist/modules/custom-fields/service.js.map +1 -0
- package/dist/modules/custom-fields/tools.d.ts +4 -0
- package/dist/modules/custom-fields/tools.d.ts.map +1 -0
- package/dist/modules/custom-fields/tools.js +38 -0
- package/dist/modules/custom-fields/tools.js.map +1 -0
- package/dist/modules/custom-fields/values.d.ts +49 -0
- package/dist/modules/custom-fields/values.d.ts.map +1 -0
- package/dist/modules/custom-fields/values.js +249 -0
- package/dist/modules/custom-fields/values.js.map +1 -0
- package/dist/modules/custom-fields/wire.d.ts +12 -0
- package/dist/modules/custom-fields/wire.d.ts.map +1 -0
- package/dist/modules/custom-fields/wire.js +30 -0
- package/dist/modules/custom-fields/wire.js.map +1 -0
- package/dist/modules/dashboard/repository.d.ts.map +1 -1
- package/dist/modules/dashboard/repository.js +4 -3
- package/dist/modules/dashboard/repository.js.map +1 -1
- package/dist/modules/deals/index.d.ts +2 -1
- package/dist/modules/deals/index.d.ts.map +1 -1
- package/dist/modules/deals/index.js +5 -2
- package/dist/modules/deals/index.js.map +1 -1
- package/dist/modules/deals/repository.d.ts +0 -16
- package/dist/modules/deals/repository.d.ts.map +1 -1
- package/dist/modules/deals/repository.js +6 -76
- package/dist/modules/deals/repository.js.map +1 -1
- package/dist/modules/deals/routes.d.ts +14 -0
- package/dist/modules/deals/routes.d.ts.map +1 -1
- package/dist/modules/deals/routes.js +7 -0
- package/dist/modules/deals/routes.js.map +1 -1
- package/dist/modules/deals/schema.d.ts +20 -42
- package/dist/modules/deals/schema.d.ts.map +1 -1
- package/dist/modules/deals/schema.js +6 -11
- package/dist/modules/deals/schema.js.map +1 -1
- package/dist/modules/deals/service.d.ts +13 -2
- package/dist/modules/deals/service.d.ts.map +1 -1
- package/dist/modules/deals/service.js +43 -20
- package/dist/modules/deals/service.js.map +1 -1
- package/dist/modules/decisions/repository.d.ts.map +1 -1
- package/dist/modules/decisions/repository.js +2 -0
- package/dist/modules/decisions/repository.js.map +1 -1
- package/dist/modules/decisions/routes.d.ts +1 -0
- package/dist/modules/decisions/routes.d.ts.map +1 -1
- package/dist/modules/email-domain-linker/index.d.ts +12 -0
- package/dist/modules/email-domain-linker/index.d.ts.map +1 -0
- package/dist/modules/email-domain-linker/index.js +34 -0
- package/dist/modules/email-domain-linker/index.js.map +1 -0
- package/dist/modules/email-domain-linker/routes.d.ts +14 -0
- package/dist/modules/email-domain-linker/routes.d.ts.map +1 -0
- package/dist/modules/email-domain-linker/routes.js +15 -0
- package/dist/modules/email-domain-linker/routes.js.map +1 -0
- package/dist/modules/email-domain-linker/service.d.ts +37 -0
- package/dist/modules/email-domain-linker/service.d.ts.map +1 -0
- package/dist/modules/email-domain-linker/service.js +63 -0
- package/dist/modules/email-domain-linker/service.js.map +1 -0
- package/dist/modules/enquiries/events.d.ts +44 -0
- package/dist/modules/enquiries/events.d.ts.map +1 -0
- package/dist/modules/enquiries/events.js +19 -0
- package/dist/modules/enquiries/events.js.map +1 -0
- package/dist/modules/enquiries/index.d.ts +13 -0
- package/dist/modules/enquiries/index.d.ts.map +1 -0
- package/dist/modules/enquiries/index.js +44 -0
- package/dist/modules/enquiries/index.js.map +1 -0
- package/dist/modules/enquiries/repository.d.ts +30 -0
- package/dist/modules/enquiries/repository.d.ts.map +1 -0
- package/dist/modules/enquiries/repository.js +94 -0
- package/dist/modules/enquiries/repository.js.map +1 -0
- package/dist/modules/enquiries/routes.d.ts +52 -0
- package/dist/modules/enquiries/routes.d.ts.map +1 -0
- package/dist/modules/enquiries/routes.js +127 -0
- package/dist/modules/enquiries/routes.js.map +1 -0
- package/dist/modules/enquiries/schema.d.ts +290 -0
- package/dist/modules/enquiries/schema.d.ts.map +1 -0
- package/dist/modules/enquiries/schema.js +52 -0
- package/dist/modules/enquiries/schema.js.map +1 -0
- package/dist/modules/enquiries/service.d.ts +85 -0
- package/dist/modules/enquiries/service.d.ts.map +1 -0
- package/dist/modules/enquiries/service.js +370 -0
- package/dist/modules/enquiries/service.js.map +1 -0
- package/dist/modules/enquiries/tools.d.ts +4 -0
- package/dist/modules/enquiries/tools.d.ts.map +1 -0
- package/dist/modules/enquiries/tools.js +50 -0
- package/dist/modules/enquiries/tools.js.map +1 -0
- package/dist/modules/eventCatalogs.d.ts +4 -0
- package/dist/modules/eventCatalogs.d.ts.map +1 -1
- package/dist/modules/eventCatalogs.js +4 -0
- package/dist/modules/eventCatalogs.js.map +1 -1
- package/dist/modules/forms/embed.d.ts +20 -6
- package/dist/modules/forms/embed.d.ts.map +1 -1
- package/dist/modules/forms/embed.js +359 -43
- package/dist/modules/forms/embed.js.map +1 -1
- package/dist/modules/forms/events.d.ts +20 -7
- package/dist/modules/forms/events.d.ts.map +1 -1
- package/dist/modules/forms/events.js +20 -2
- package/dist/modules/forms/events.js.map +1 -1
- package/dist/modules/forms/fields.d.ts +14 -1
- package/dist/modules/forms/fields.d.ts.map +1 -1
- package/dist/modules/forms/fields.js +87 -3
- package/dist/modules/forms/fields.js.map +1 -1
- package/dist/modules/forms/index.d.ts.map +1 -1
- package/dist/modules/forms/index.js +12 -1
- package/dist/modules/forms/index.js.map +1 -1
- package/dist/modules/forms/mapping.d.ts +62 -5
- package/dist/modules/forms/mapping.d.ts.map +1 -1
- package/dist/modules/forms/mapping.js +139 -5
- package/dist/modules/forms/mapping.js.map +1 -1
- package/dist/modules/forms/publicRoutes.d.ts.map +1 -1
- package/dist/modules/forms/publicRoutes.js +29 -1
- package/dist/modules/forms/publicRoutes.js.map +1 -1
- package/dist/modules/forms/repository.d.ts +31 -0
- package/dist/modules/forms/repository.d.ts.map +1 -1
- package/dist/modules/forms/repository.js +90 -1
- package/dist/modules/forms/repository.js.map +1 -1
- package/dist/modules/forms/routes.d.ts +83 -1
- package/dist/modules/forms/routes.d.ts.map +1 -1
- package/dist/modules/forms/routes.js +185 -2
- package/dist/modules/forms/routes.js.map +1 -1
- package/dist/modules/forms/schema.d.ts +672 -1
- package/dist/modules/forms/schema.d.ts.map +1 -1
- package/dist/modules/forms/schema.js +146 -3
- package/dist/modules/forms/schema.js.map +1 -1
- package/dist/modules/forms/service.d.ts +54 -1
- package/dist/modules/forms/service.d.ts.map +1 -1
- package/dist/modules/forms/service.js +338 -28
- package/dist/modules/forms/service.js.map +1 -1
- package/dist/modules/forms/submission.d.ts +15 -0
- package/dist/modules/forms/submission.d.ts.map +1 -1
- package/dist/modules/forms/submission.js +418 -40
- package/dist/modules/forms/submission.js.map +1 -1
- package/dist/modules/import-export/drafts.d.ts +10 -0
- package/dist/modules/import-export/drafts.d.ts.map +1 -1
- package/dist/modules/import-export/drafts.js +16 -2
- package/dist/modules/import-export/drafts.js.map +1 -1
- package/dist/modules/import-export/exportRows.d.ts +7 -4
- package/dist/modules/import-export/exportRows.d.ts.map +1 -1
- package/dist/modules/import-export/exportRows.js +20 -5
- package/dist/modules/import-export/exportRows.js.map +1 -1
- package/dist/modules/import-export/plan.d.ts +12 -1
- package/dist/modules/import-export/plan.d.ts.map +1 -1
- package/dist/modules/import-export/plan.js +29 -2
- package/dist/modules/import-export/plan.js.map +1 -1
- package/dist/modules/import-export/presets.d.ts.map +1 -1
- package/dist/modules/import-export/presets.js +10 -0
- package/dist/modules/import-export/presets.js.map +1 -1
- package/dist/modules/import-export/repository.d.ts +11 -1
- package/dist/modules/import-export/repository.d.ts.map +1 -1
- package/dist/modules/import-export/repository.js +42 -9
- package/dist/modules/import-export/repository.js.map +1 -1
- package/dist/modules/import-export/routes.d.ts.map +1 -1
- package/dist/modules/import-export/routes.js +4 -0
- package/dist/modules/import-export/routes.js.map +1 -1
- package/dist/modules/import-export/schema.d.ts +17 -0
- package/dist/modules/import-export/schema.d.ts.map +1 -1
- package/dist/modules/import-export/schema.js +11 -0
- package/dist/modules/import-export/schema.js.map +1 -1
- package/dist/modules/import-export/service.d.ts +6 -0
- package/dist/modules/import-export/service.d.ts.map +1 -1
- package/dist/modules/import-export/service.js +14 -2
- package/dist/modules/import-export/service.js.map +1 -1
- package/dist/modules/import-export/streams.d.ts.map +1 -1
- package/dist/modules/import-export/streams.js +3 -3
- package/dist/modules/import-export/streams.js.map +1 -1
- package/dist/modules/import-export/tools.d.ts.map +1 -1
- package/dist/modules/import-export/tools.js +8 -0
- package/dist/modules/import-export/tools.js.map +1 -1
- package/dist/modules/import-export/validation.d.ts.map +1 -1
- package/dist/modules/import-export/validation.js +22 -1
- package/dist/modules/import-export/validation.js.map +1 -1
- package/dist/modules/import-export/writes.d.ts.map +1 -1
- package/dist/modules/import-export/writes.js +37 -4
- package/dist/modules/import-export/writes.js.map +1 -1
- package/dist/modules/lists/events.d.ts +42 -0
- package/dist/modules/lists/events.d.ts.map +1 -0
- package/dist/modules/lists/events.js +16 -0
- package/dist/modules/lists/events.js.map +1 -0
- package/dist/modules/lists/index.d.ts +10 -0
- package/dist/modules/lists/index.d.ts.map +1 -0
- package/dist/modules/lists/index.js +35 -0
- package/dist/modules/lists/index.js.map +1 -0
- package/dist/modules/lists/repository.d.ts +80 -0
- package/dist/modules/lists/repository.d.ts.map +1 -0
- package/dist/modules/lists/repository.js +178 -0
- package/dist/modules/lists/repository.js.map +1 -0
- package/dist/modules/lists/routes.d.ts +55 -0
- package/dist/modules/lists/routes.d.ts.map +1 -0
- package/dist/modules/lists/routes.js +168 -0
- package/dist/modules/lists/routes.js.map +1 -0
- package/dist/modules/lists/schema.d.ts +281 -0
- package/dist/modules/lists/schema.d.ts.map +1 -0
- package/dist/modules/lists/schema.js +83 -0
- package/dist/modules/lists/schema.js.map +1 -0
- package/dist/modules/lists/service.d.ts +82 -0
- package/dist/modules/lists/service.d.ts.map +1 -0
- package/dist/modules/lists/service.js +262 -0
- package/dist/modules/lists/service.js.map +1 -0
- package/dist/modules/lists/tools.d.ts +4 -0
- package/dist/modules/lists/tools.d.ts.map +1 -0
- package/dist/modules/lists/tools.js +86 -0
- package/dist/modules/lists/tools.js.map +1 -0
- package/dist/modules/mcp/index.d.ts.map +1 -1
- package/dist/modules/mcp/index.js +5 -0
- package/dist/modules/mcp/index.js.map +1 -1
- package/dist/modules/notes/routes.d.ts +1 -0
- package/dist/modules/notes/routes.d.ts.map +1 -1
- package/dist/modules/opportunities/index.d.ts.map +1 -1
- package/dist/modules/opportunities/index.js +3 -1
- package/dist/modules/opportunities/index.js.map +1 -1
- package/dist/modules/opportunities/repository.d.ts +2 -0
- package/dist/modules/opportunities/repository.d.ts.map +1 -1
- package/dist/modules/opportunities/repository.js +4 -0
- package/dist/modules/opportunities/repository.js.map +1 -1
- package/dist/modules/opportunities/routes.d.ts +16 -0
- package/dist/modules/opportunities/routes.d.ts.map +1 -1
- package/dist/modules/opportunities/routes.js +13 -0
- package/dist/modules/opportunities/routes.js.map +1 -1
- package/dist/modules/opportunities/schema.d.ts +20 -0
- package/dist/modules/opportunities/schema.d.ts.map +1 -1
- package/dist/modules/opportunities/schema.js +6 -1
- package/dist/modules/opportunities/schema.js.map +1 -1
- package/dist/modules/opportunities/service.d.ts +20 -3
- package/dist/modules/opportunities/service.d.ts.map +1 -1
- package/dist/modules/opportunities/service.js +99 -18
- package/dist/modules/opportunities/service.js.map +1 -1
- package/dist/modules/opportunities/tools.d.ts.map +1 -1
- package/dist/modules/opportunities/tools.js +2 -0
- package/dist/modules/opportunities/tools.js.map +1 -1
- package/dist/modules/partnerships/index.d.ts.map +1 -1
- package/dist/modules/partnerships/index.js +3 -1
- package/dist/modules/partnerships/index.js.map +1 -1
- package/dist/modules/partnerships/repository.d.ts +0 -17
- package/dist/modules/partnerships/repository.d.ts.map +1 -1
- package/dist/modules/partnerships/repository.js +6 -82
- package/dist/modules/partnerships/repository.js.map +1 -1
- package/dist/modules/partnerships/routes.d.ts +14 -0
- package/dist/modules/partnerships/routes.d.ts.map +1 -1
- package/dist/modules/partnerships/routes.js +7 -0
- package/dist/modules/partnerships/routes.js.map +1 -1
- package/dist/modules/partnerships/schema.d.ts +20 -41
- package/dist/modules/partnerships/schema.d.ts.map +1 -1
- package/dist/modules/partnerships/schema.js +6 -10
- package/dist/modules/partnerships/schema.js.map +1 -1
- package/dist/modules/partnerships/service.d.ts +11 -1
- package/dist/modules/partnerships/service.d.ts.map +1 -1
- package/dist/modules/partnerships/service.js +43 -20
- package/dist/modules/partnerships/service.js.map +1 -1
- package/dist/modules/people/consentHydration.d.ts +26 -0
- package/dist/modules/people/consentHydration.d.ts.map +1 -0
- package/dist/modules/people/consentHydration.js +100 -0
- package/dist/modules/people/consentHydration.js.map +1 -0
- package/dist/modules/people/index.d.ts.map +1 -1
- package/dist/modules/people/index.js +3 -1
- package/dist/modules/people/index.js.map +1 -1
- package/dist/modules/people/personConsentWrites.d.ts +40 -0
- package/dist/modules/people/personConsentWrites.d.ts.map +1 -0
- package/dist/modules/people/personConsentWrites.js +98 -0
- package/dist/modules/people/personConsentWrites.js.map +1 -0
- package/dist/modules/people/repository.d.ts +11 -0
- package/dist/modules/people/repository.d.ts.map +1 -1
- package/dist/modules/people/repository.js +21 -1
- package/dist/modules/people/repository.js.map +1 -1
- package/dist/modules/people/routes.d.ts +57 -4
- package/dist/modules/people/routes.d.ts.map +1 -1
- package/dist/modules/people/routes.js +104 -5
- package/dist/modules/people/routes.js.map +1 -1
- package/dist/modules/people/schema.d.ts +366 -1
- package/dist/modules/people/schema.d.ts.map +1 -1
- package/dist/modules/people/schema.js +92 -2
- package/dist/modules/people/schema.js.map +1 -1
- package/dist/modules/people/service.d.ts +30 -1
- package/dist/modules/people/service.d.ts.map +1 -1
- package/dist/modules/people/service.js +131 -36
- package/dist/modules/people/service.js.map +1 -1
- package/dist/modules/people/tools.d.ts.map +1 -1
- package/dist/modules/people/tools.js +4 -1
- package/dist/modules/people/tools.js.map +1 -1
- package/dist/modules/personLinks.d.ts +79 -0
- package/dist/modules/personLinks.d.ts.map +1 -0
- package/dist/modules/personLinks.js +155 -0
- package/dist/modules/personLinks.js.map +1 -0
- package/dist/modules/pipelines/routes.d.ts +1 -0
- package/dist/modules/pipelines/routes.d.ts.map +1 -1
- package/dist/modules/plans/routes.d.ts +1 -0
- package/dist/modules/plans/routes.d.ts.map +1 -1
- package/dist/modules/positions/routes.d.ts.map +1 -1
- package/dist/modules/positions/routes.js +4 -2
- package/dist/modules/positions/routes.js.map +1 -1
- package/dist/modules/raises/index.d.ts.map +1 -1
- package/dist/modules/raises/index.js +3 -1
- package/dist/modules/raises/index.js.map +1 -1
- package/dist/modules/raises/repository.d.ts +0 -17
- package/dist/modules/raises/repository.d.ts.map +1 -1
- package/dist/modules/raises/repository.js +6 -77
- package/dist/modules/raises/repository.js.map +1 -1
- package/dist/modules/raises/routes.d.ts +14 -0
- package/dist/modules/raises/routes.d.ts.map +1 -1
- package/dist/modules/raises/routes.js +7 -0
- package/dist/modules/raises/routes.js.map +1 -1
- package/dist/modules/raises/schema.d.ts +20 -41
- package/dist/modules/raises/schema.d.ts.map +1 -1
- package/dist/modules/raises/schema.js +6 -10
- package/dist/modules/raises/schema.js.map +1 -1
- package/dist/modules/raises/service.d.ts +11 -1
- package/dist/modules/raises/service.d.ts.map +1 -1
- package/dist/modules/raises/service.js +41 -18
- package/dist/modules/raises/service.js.map +1 -1
- package/dist/modules/recordTargets.d.ts.map +1 -1
- package/dist/modules/recordTargets.js +2 -0
- package/dist/modules/recordTargets.js.map +1 -1
- package/dist/modules/references.d.ts +10 -0
- package/dist/modules/references.d.ts.map +1 -1
- package/dist/modules/references.js +27 -4
- package/dist/modules/references.js.map +1 -1
- package/dist/modules/sample-data/fixture.d.ts +160 -0
- package/dist/modules/sample-data/fixture.d.ts.map +1 -0
- package/dist/modules/sample-data/fixture.js +501 -0
- package/dist/modules/sample-data/fixture.js.map +1 -0
- package/dist/modules/sample-data/index.d.ts +11 -0
- package/dist/modules/sample-data/index.d.ts.map +1 -0
- package/dist/modules/sample-data/index.js +44 -0
- package/dist/modules/sample-data/index.js.map +1 -0
- package/dist/modules/sample-data/routes.d.ts +15 -0
- package/dist/modules/sample-data/routes.d.ts.map +1 -0
- package/dist/modules/sample-data/routes.js +25 -0
- package/dist/modules/sample-data/routes.js.map +1 -0
- package/dist/modules/sample-data/service.d.ts +39 -0
- package/dist/modules/sample-data/service.d.ts.map +1 -0
- package/dist/modules/sample-data/service.js +481 -0
- package/dist/modules/sample-data/service.js.map +1 -0
- package/dist/modules/sample-data/tools.d.ts +4 -0
- package/dist/modules/sample-data/tools.d.ts.map +1 -0
- package/dist/modules/sample-data/tools.js +22 -0
- package/dist/modules/sample-data/tools.js.map +1 -0
- package/dist/modules/search/index.d.ts +1 -1
- package/dist/modules/search/index.d.ts.map +1 -1
- package/dist/modules/search/index.js +2 -1
- package/dist/modules/search/index.js.map +1 -1
- package/dist/modules/search/repository.d.ts +1 -0
- package/dist/modules/search/repository.d.ts.map +1 -1
- package/dist/modules/search/repository.js +23 -0
- package/dist/modules/search/repository.js.map +1 -1
- package/dist/modules/search/service.d.ts +3 -3
- package/dist/modules/search/service.d.ts.map +1 -1
- package/dist/modules/search/service.js +5 -4
- package/dist/modules/search/service.js.map +1 -1
- package/dist/modules/smtp-email/index.d.ts +1 -0
- package/dist/modules/smtp-email/index.d.ts.map +1 -1
- package/dist/modules/smtp-email/index.js +1 -0
- package/dist/modules/smtp-email/index.js.map +1 -1
- package/dist/modules/stagedRecords.d.ts +3 -3
- package/dist/modules/stagedRecords.d.ts.map +1 -1
- package/dist/modules/stagedRecords.js +9 -0
- package/dist/modules/stagedRecords.js.map +1 -1
- package/dist/modules/webhooks/payloads.d.ts.map +1 -1
- package/dist/modules/webhooks/payloads.js +15 -2
- package/dist/modules/webhooks/payloads.js.map +1 -1
- package/dist/modules/workspace/repository.d.ts +2 -0
- package/dist/modules/workspace/repository.d.ts.map +1 -1
- package/dist/modules/workspace/repository.js +7 -0
- package/dist/modules/workspace/repository.js.map +1 -1
- package/dist/modules/workspace/service.d.ts.map +1 -1
- package/dist/modules/workspace/service.js +20 -1
- package/dist/modules/workspace/service.js.map +1 -1
- package/dist/modules/workspace/starters.d.ts.map +1 -1
- package/dist/modules/workspace/starters.js +5 -0
- package/dist/modules/workspace/starters.js.map +1 -1
- package/dist/runtime/events.d.ts +1 -1
- package/dist/runtime/events.d.ts.map +1 -1
- package/dist/runtime/events.js +1 -0
- package/dist/runtime/events.js.map +1 -1
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +4 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/testing/database.d.ts +5 -1
- package/dist/testing/database.d.ts.map +1 -1
- package/dist/testing/database.js +81 -10
- package/dist/testing/database.js.map +1 -1
- package/migrations/0021_certain_maggott.sql +30 -0
- package/migrations/0022_stormy_manta.sql +1 -0
- package/migrations/0023_funny_maddog.sql +1 -0
- package/migrations/0024_third_king_cobra.sql +46 -0
- package/migrations/0025_worthless_chimera.sql +3 -0
- package/migrations/0026_late_aqueduct.sql +46 -0
- package/migrations/0027_brainy_silver_sable.sql +3 -0
- package/migrations/0028_freezing_scrambler.sql +19 -0
- package/migrations/0029_custom_fields.sql +26 -0
- package/migrations/0030_enquiries.sql +79 -0
- package/migrations/0031_consent.sql +45 -0
- package/migrations/0032_form_field_statement.sql +1 -0
- package/migrations/0033_form_field_consent_purpose_ids.sql +5 -0
- package/migrations/0034_drop_form_field_consent_purpose_id.sql +1 -0
- package/migrations/0035_form_field_consent_purpose_labels.sql +1 -0
- package/migrations/0036_form_field_notice_type.sql +2 -0
- package/migrations/meta/0021_snapshot.json +5389 -0
- package/migrations/meta/0022_snapshot.json +5396 -0
- package/migrations/meta/0023_snapshot.json +5403 -0
- package/migrations/meta/0024_snapshot.json +5516 -0
- package/migrations/meta/0025_snapshot.json +5336 -0
- package/migrations/meta/0026_snapshot.json +5710 -0
- package/migrations/meta/0027_snapshot.json +5716 -0
- package/migrations/meta/0028_snapshot.json +5740 -0
- package/migrations/meta/0029_snapshot.json +5935 -0
- package/migrations/meta/0030_snapshot.json +6245 -0
- package/migrations/meta/0031_snapshot.json +6572 -0
- package/migrations/meta/0032_snapshot.json +6578 -0
- package/migrations/meta/0033_snapshot.json +6572 -0
- package/migrations/meta/0034_snapshot.json +6566 -0
- package/migrations/meta/0035_snapshot.json +6573 -0
- package/migrations/meta/0036_snapshot.json +6573 -0
- package/migrations/meta/_journal.json +112 -0
- package/package.json +3 -2
- package/src/lib/consumerEmailDomains.ts +62 -0
- package/src/lib/email.ts +7 -0
- package/src/lib/emailContent.ts +91 -0
- package/src/lib/emailDomainAutoLink.ts +165 -0
- package/src/lib/ids.ts +13 -0
- package/src/modules/activities/repository.ts +22 -23
- package/src/modules/activities/wording.ts +18 -0
- package/src/modules/agent-tasks/catalog.ts +63 -0
- package/src/modules/agent-tasks/resolve.ts +64 -24
- package/src/modules/attachedRecords.ts +37 -3
- package/src/modules/auth/preferences.ts +13 -1
- package/src/modules/auth/routes.ts +22 -0
- package/src/modules/auth/schema.ts +12 -2
- package/src/modules/auth/service.ts +37 -3
- package/src/modules/companies/index.ts +3 -1
- package/src/modules/companies/repository.ts +3 -0
- package/src/modules/companies/routes.ts +20 -0
- package/src/modules/companies/schema.ts +11 -1
- package/src/modules/companies/service.ts +72 -12
- package/src/modules/consent-purposes/capabilities.ts +12 -0
- package/src/modules/consent-purposes/events.ts +38 -0
- package/src/modules/consent-purposes/index.ts +48 -0
- package/src/modules/consent-purposes/repository.ts +163 -0
- package/src/modules/consent-purposes/routes.ts +122 -0
- package/src/modules/consent-purposes/schema.ts +46 -0
- package/src/modules/consent-purposes/service.ts +423 -0
- package/src/modules/consent-purposes/starters.ts +32 -0
- package/src/modules/consent-purposes/tools.ts +44 -0
- package/src/modules/core.ts +21 -0
- package/src/modules/custom-fields/capabilities.ts +17 -0
- package/src/modules/custom-fields/events.ts +51 -0
- package/src/modules/custom-fields/index.ts +61 -0
- package/src/modules/custom-fields/repository.ts +225 -0
- package/src/modules/custom-fields/routes.ts +155 -0
- package/src/modules/custom-fields/schema.ts +61 -0
- package/src/modules/custom-fields/service.ts +439 -0
- package/src/modules/custom-fields/tools.ts +53 -0
- package/src/modules/custom-fields/values.ts +352 -0
- package/src/modules/custom-fields/wire.ts +32 -0
- package/src/modules/dashboard/repository.ts +4 -3
- package/src/modules/deals/index.ts +5 -2
- package/src/modules/deals/repository.ts +6 -106
- package/src/modules/deals/routes.ts +7 -0
- package/src/modules/deals/schema.ts +7 -15
- package/src/modules/deals/service.ts +92 -23
- package/src/modules/decisions/repository.ts +2 -0
- package/src/modules/email-domain-linker/index.ts +40 -0
- package/src/modules/email-domain-linker/routes.ts +40 -0
- package/src/modules/email-domain-linker/service.ts +122 -0
- package/src/modules/enquiries/events.ts +45 -0
- package/src/modules/enquiries/index.ts +50 -0
- package/src/modules/enquiries/repository.ts +164 -0
- package/src/modules/enquiries/routes.ts +172 -0
- package/src/modules/enquiries/schema.ts +59 -0
- package/src/modules/enquiries/service.ts +644 -0
- package/src/modules/enquiries/tools.ts +66 -0
- package/src/modules/eventCatalogs.ts +4 -0
- package/src/modules/forms/embed.ts +391 -44
- package/src/modules/forms/events.ts +30 -2
- package/src/modules/forms/fields.ts +102 -2
- package/src/modules/forms/index.ts +12 -1
- package/src/modules/forms/mapping.ts +183 -6
- package/src/modules/forms/publicRoutes.ts +43 -1
- package/src/modules/forms/repository.ts +162 -1
- package/src/modules/forms/routes.ts +212 -2
- package/src/modules/forms/schema.ts +166 -4
- package/src/modules/forms/service.ts +565 -41
- package/src/modules/forms/submission.ts +718 -44
- package/src/modules/import-export/drafts.ts +20 -1
- package/src/modules/import-export/exportRows.ts +21 -5
- package/src/modules/import-export/plan.ts +47 -2
- package/src/modules/import-export/presets.ts +10 -0
- package/src/modules/import-export/repository.ts +73 -8
- package/src/modules/import-export/routes.ts +4 -0
- package/src/modules/import-export/schema.ts +11 -0
- package/src/modules/import-export/service.ts +28 -2
- package/src/modules/import-export/streams.ts +3 -1
- package/src/modules/import-export/tools.ts +10 -0
- package/src/modules/import-export/validation.ts +28 -0
- package/src/modules/import-export/writes.ts +70 -5
- package/src/modules/lists/events.ts +41 -0
- package/src/modules/lists/index.ts +41 -0
- package/src/modules/lists/repository.ts +343 -0
- package/src/modules/lists/routes.ts +255 -0
- package/src/modules/lists/schema.ts +95 -0
- package/src/modules/lists/service.ts +505 -0
- package/src/modules/lists/tools.ts +128 -0
- package/src/modules/mcp/index.ts +5 -0
- package/src/modules/opportunities/index.ts +3 -1
- package/src/modules/opportunities/repository.ts +11 -0
- package/src/modules/opportunities/routes.ts +13 -0
- package/src/modules/opportunities/schema.ts +7 -1
- package/src/modules/opportunities/service.ts +188 -22
- package/src/modules/opportunities/tools.ts +2 -0
- package/src/modules/partnerships/index.ts +3 -1
- package/src/modules/partnerships/repository.ts +6 -117
- package/src/modules/partnerships/routes.ts +7 -0
- package/src/modules/partnerships/schema.ts +7 -14
- package/src/modules/partnerships/service.ts +93 -22
- package/src/modules/people/consentHydration.ts +167 -0
- package/src/modules/people/index.ts +3 -1
- package/src/modules/people/personConsentWrites.ts +177 -0
- package/src/modules/people/repository.ts +31 -0
- package/src/modules/people/routes.ts +127 -18
- package/src/modules/people/schema.ts +109 -3
- package/src/modules/people/service.ts +205 -39
- package/src/modules/people/tools.ts +5 -1
- package/src/modules/personLinks.ts +278 -0
- package/src/modules/positions/routes.ts +4 -2
- package/src/modules/raises/index.ts +3 -1
- package/src/modules/raises/repository.ts +6 -107
- package/src/modules/raises/routes.ts +7 -0
- package/src/modules/raises/schema.ts +7 -14
- package/src/modules/raises/service.ts +91 -20
- package/src/modules/recordTargets.ts +2 -0
- package/src/modules/references.ts +43 -4
- package/src/modules/sample-data/fixture.ts +690 -0
- package/src/modules/sample-data/index.ts +51 -0
- package/src/modules/sample-data/routes.ts +50 -0
- package/src/modules/sample-data/service.ts +679 -0
- package/src/modules/sample-data/tools.ts +32 -0
- package/src/modules/search/index.ts +2 -1
- package/src/modules/search/repository.ts +33 -1
- package/src/modules/search/service.ts +7 -5
- package/src/modules/smtp-email/index.ts +8 -1
- package/src/modules/stagedRecords.ts +18 -3
- package/src/modules/webhooks/payloads.ts +20 -2
- package/src/modules/workspace/repository.ts +12 -0
- package/src/modules/workspace/service.ts +27 -1
- package/src/modules/workspace/starters.ts +5 -0
- package/src/runtime/events.ts +1 -0
- package/src/schema/index.ts +4 -0
- package/src/testing/database.ts +97 -11
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
PREFERRED_CHANNELS,
|
|
7
7
|
RELATIONSHIP_LEVELS,
|
|
8
8
|
SIZE_BANDS,
|
|
9
|
+
composeName,
|
|
9
10
|
} from '@kelpie/schemas'
|
|
10
11
|
|
|
11
12
|
import { normaliseDomain, normaliseEmail } from '../../lib/normalisation.ts'
|
|
@@ -43,6 +44,10 @@ export interface CompanyDraft {
|
|
|
43
44
|
|
|
44
45
|
export interface PersonDraft {
|
|
45
46
|
readonly name?: string
|
|
47
|
+
readonly salutation?: string
|
|
48
|
+
readonly firstName?: string
|
|
49
|
+
readonly lastName?: string
|
|
50
|
+
readonly suffix?: string
|
|
46
51
|
readonly email?: string
|
|
47
52
|
readonly phones?: readonly string[]
|
|
48
53
|
readonly timezone?: string
|
|
@@ -157,11 +162,25 @@ export function companyDraft(mapped: Readonly<Record<string, string>>): CompanyD
|
|
|
157
162
|
})
|
|
158
163
|
}
|
|
159
164
|
|
|
165
|
+
/**
|
|
166
|
+
* `name` falls back to the first and last name cells, because most CRMs export
|
|
167
|
+
* those two and no full name at all. Composed only when the row's own `name` is
|
|
168
|
+
* blank, and never the other way round: a `name` cell is never split to fill
|
|
169
|
+
* `first_name`, since a guessed part is stored exactly like one somebody typed.
|
|
170
|
+
*/
|
|
160
171
|
export function personDraft(mapped: Readonly<Record<string, string>>): PersonDraft {
|
|
161
172
|
const email = text(mapped, 'email')
|
|
173
|
+
const firstName = text(mapped, 'first_name')
|
|
174
|
+
const lastName = text(mapped, 'last_name')
|
|
175
|
+
const suffix = text(mapped, 'suffix')
|
|
176
|
+
const composed = composeName({ firstName, lastName, suffix })
|
|
162
177
|
|
|
163
178
|
return present<PersonDraft>({
|
|
164
|
-
name: text(mapped, 'name'),
|
|
179
|
+
name: text(mapped, 'name') ?? (composed.length > 0 ? composed : undefined),
|
|
180
|
+
salutation: text(mapped, 'salutation'),
|
|
181
|
+
firstName,
|
|
182
|
+
lastName,
|
|
183
|
+
suffix,
|
|
165
184
|
email: email === undefined ? undefined : (normaliseEmail(email) ?? undefined),
|
|
166
185
|
phones: list(mapped, 'phones'),
|
|
167
186
|
timezone: text(mapped, 'timezone'),
|
|
@@ -30,13 +30,23 @@ function joinList(values: readonly string[]): string {
|
|
|
30
30
|
* The header row of an export and of a template.
|
|
31
31
|
*
|
|
32
32
|
* `importOnly` columns are left out: a People import may map `company_domain`,
|
|
33
|
-
* `company_name` and `
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
33
|
+
* `company_name`, `title`, `consent_status`, and `consent_at` to drive extra
|
|
34
|
+
* writes, but none is a field on the person row. A template also leaves out
|
|
35
|
+
* `exportOnly` columns (`do_not_contact`, `consents`), which the export writes
|
|
36
|
+
* for readability but a caller round-trips through the per-purpose columns and
|
|
37
|
+
* `consent_purpose_id` on the job.
|
|
37
38
|
*/
|
|
38
39
|
export function headersFor(object: ImportObject): readonly string[] {
|
|
39
|
-
return OBJECT_COLUMNS[object]
|
|
40
|
+
return OBJECT_COLUMNS[object]
|
|
41
|
+
.filter((column) => column.importOnly !== true)
|
|
42
|
+
.map((column) => column.key)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The template's headers — the round-trippable ones for a caller to fill in. */
|
|
46
|
+
export function templateHeadersFor(object: ImportObject): readonly string[] {
|
|
47
|
+
return OBJECT_COLUMNS[object]
|
|
48
|
+
.filter((column) => column.importOnly !== true && column.exportOnly !== true)
|
|
49
|
+
.map((column) => column.key)
|
|
40
50
|
}
|
|
41
51
|
|
|
42
52
|
export function companyCells(row: ExportCompanyRow): readonly string[] {
|
|
@@ -59,6 +69,10 @@ export function companyCells(row: ExportCompanyRow): readonly string[] {
|
|
|
59
69
|
export function personCells(row: ExportPersonRow): readonly string[] {
|
|
60
70
|
return [
|
|
61
71
|
row.name,
|
|
72
|
+
row.salutation ?? '',
|
|
73
|
+
row.firstName ?? '',
|
|
74
|
+
row.lastName ?? '',
|
|
75
|
+
row.suffix ?? '',
|
|
62
76
|
row.email ?? '',
|
|
63
77
|
row.timezone ?? '',
|
|
64
78
|
row.location ?? '',
|
|
@@ -68,6 +82,8 @@ export function personCells(row: ExportPersonRow): readonly string[] {
|
|
|
68
82
|
row.summary,
|
|
69
83
|
joinList(row.tags),
|
|
70
84
|
joinList(row.phones),
|
|
85
|
+
row.doNotContact ? 'true' : 'false',
|
|
86
|
+
row.consents,
|
|
71
87
|
]
|
|
72
88
|
}
|
|
73
89
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
ConsentStatus,
|
|
2
3
|
ImportConflictMode,
|
|
3
4
|
ImportCounts,
|
|
4
5
|
ImportObject,
|
|
@@ -44,6 +45,8 @@ export interface PlanContext {
|
|
|
44
45
|
readonly conflictMode: ImportConflictMode
|
|
45
46
|
/** What a People row does with an absent company. Ignored by the other objects. */
|
|
46
47
|
readonly onMissingCompany: OnMissingCompany
|
|
48
|
+
/** The consent purpose the job grants for each row's consent_status. Null when not set. */
|
|
49
|
+
readonly consentPurposeId: string | null
|
|
47
50
|
readonly lookups: ImportLookups
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -55,6 +58,14 @@ export type PlannedAffiliation =
|
|
|
55
58
|
| { readonly kind: 'link'; readonly companyId: string; readonly title: string }
|
|
56
59
|
| { readonly kind: 'create'; readonly company: CompanyDraft; readonly title: string }
|
|
57
60
|
|
|
61
|
+
/** A consent write that rides with a People row when the job has a purpose. */
|
|
62
|
+
export interface ImportConsentGrant {
|
|
63
|
+
readonly purposeId: string
|
|
64
|
+
readonly status: ConsentStatus
|
|
65
|
+
/** ISO date from the `consent_at` column; null when the column is unmapped or blank. */
|
|
66
|
+
readonly notedAt: string | null
|
|
67
|
+
}
|
|
68
|
+
|
|
58
69
|
/** The values a write applies, once every reference in the row has been resolved. */
|
|
59
70
|
export type ImportWrite =
|
|
60
71
|
| { readonly object: 'companies'; readonly draft: CompanyDraft }
|
|
@@ -63,6 +74,8 @@ export type ImportWrite =
|
|
|
63
74
|
readonly draft: PersonDraft
|
|
64
75
|
/** A position to upsert alongside the person, when the row named a company and a title. */
|
|
65
76
|
readonly affiliation?: PlannedAffiliation
|
|
77
|
+
/** Consent to grant against the job's purpose. Absent when consent_status is blank. */
|
|
78
|
+
readonly consent?: ImportConsentGrant
|
|
66
79
|
}
|
|
67
80
|
| {
|
|
68
81
|
readonly object: 'positions'
|
|
@@ -249,8 +262,18 @@ function resolveWrite(context: PlanContext, mapped: Readonly<Record<string, stri
|
|
|
249
262
|
switch (context.object) {
|
|
250
263
|
case 'companies':
|
|
251
264
|
return { object: 'companies', draft: companyDraft(mapped) }
|
|
252
|
-
case 'people':
|
|
253
|
-
|
|
265
|
+
case 'people': {
|
|
266
|
+
const write: {
|
|
267
|
+
object: 'people'
|
|
268
|
+
draft: PersonDraft
|
|
269
|
+
consent?: ImportConsentGrant
|
|
270
|
+
} = { object: 'people', draft: personDraft(mapped) }
|
|
271
|
+
const consent = readConsentGrant(context, mapped)
|
|
272
|
+
if (consent !== undefined) {
|
|
273
|
+
write.consent = consent
|
|
274
|
+
}
|
|
275
|
+
return write
|
|
276
|
+
}
|
|
254
277
|
case 'positions':
|
|
255
278
|
return planPosition(context, mapped)
|
|
256
279
|
case 'deals':
|
|
@@ -258,6 +281,28 @@ function resolveWrite(context: PlanContext, mapped: Readonly<Record<string, stri
|
|
|
258
281
|
}
|
|
259
282
|
}
|
|
260
283
|
|
|
284
|
+
/**
|
|
285
|
+
* The consent grant a People row carries. Absent unless the job has a purpose
|
|
286
|
+
* set on it AND the row has a non-blank `consent_status`. `validateRow` has
|
|
287
|
+
* already refused an unknown status by the time this runs, so the coercion
|
|
288
|
+
* below is safe.
|
|
289
|
+
*/
|
|
290
|
+
function readConsentGrant(
|
|
291
|
+
context: PlanContext,
|
|
292
|
+
mapped: Readonly<Record<string, string>>,
|
|
293
|
+
): ImportConsentGrant | undefined {
|
|
294
|
+
if (context.consentPurposeId === null) return undefined
|
|
295
|
+
const rawStatus = (mapped.consent_status ?? '').trim().toLowerCase()
|
|
296
|
+
if (rawStatus.length === 0) return undefined
|
|
297
|
+
if (rawStatus !== 'granted' && rawStatus !== 'withdrawn') return undefined
|
|
298
|
+
const rawAt = (mapped.consent_at ?? '').trim()
|
|
299
|
+
return {
|
|
300
|
+
purposeId: context.consentPurposeId,
|
|
301
|
+
status: rawStatus as ConsentStatus,
|
|
302
|
+
notedAt: rawAt.length === 0 ? null : rawAt,
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
261
306
|
/**
|
|
262
307
|
* The company affiliation a People row asks for, if any, and any note about it.
|
|
263
308
|
*
|
|
@@ -27,7 +27,12 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
27
27
|
description: 'Description',
|
|
28
28
|
},
|
|
29
29
|
people: {
|
|
30
|
+
// Both, because a HubSpot contact export carries the parts and often no
|
|
31
|
+
// full name at all. A preset header the file does not have falls through
|
|
32
|
+
// to the exact-key match below, so mapping all three costs a file nothing.
|
|
30
33
|
name: 'Full Name',
|
|
34
|
+
first_name: 'First Name',
|
|
35
|
+
last_name: 'Last Name',
|
|
31
36
|
email: 'Email',
|
|
32
37
|
phones: 'Phone Number',
|
|
33
38
|
location: 'City',
|
|
@@ -59,10 +64,15 @@ export const SOURCE_PRESETS: Readonly<Record<ImportSource, SourcePreset>> = {
|
|
|
59
64
|
},
|
|
60
65
|
people: {
|
|
61
66
|
name: 'Full Name',
|
|
67
|
+
salutation: 'Salutation',
|
|
68
|
+
first_name: 'First Name',
|
|
69
|
+
last_name: 'Last Name',
|
|
62
70
|
email: 'Email',
|
|
63
71
|
phones: 'Phone',
|
|
64
72
|
location: 'Mailing City',
|
|
65
73
|
company_name: 'Account Name',
|
|
74
|
+
// Salesforce's Contact.Title is the job title, and a job title is a
|
|
75
|
+
// Position. It is not this object's `suffix`, which stays unmapped.
|
|
66
76
|
title: 'Title',
|
|
67
77
|
},
|
|
68
78
|
positions: {
|
|
@@ -3,8 +3,9 @@ import { and, asc, eq, gt, inArray, sql } from 'drizzle-orm'
|
|
|
3
3
|
import type { Queryable } from '../../runtime/transaction.ts'
|
|
4
4
|
import { users } from '../auth/schema.ts'
|
|
5
5
|
import { companies } from '../companies/schema.ts'
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { consentPurposes } from '../consent-purposes/schema.ts'
|
|
7
|
+
import { deals } from '../deals/schema.ts'
|
|
8
|
+
import { people, personConsents, personLinks } from '../people/schema.ts'
|
|
8
9
|
import { pipelineStages } from '../pipelines/schema.ts'
|
|
9
10
|
import { positions } from '../positions/schema.ts'
|
|
10
11
|
import { workspaceMembers } from '../workspace/schema.ts'
|
|
@@ -487,6 +488,10 @@ export function readCompanies(
|
|
|
487
488
|
export interface ExportPersonRow {
|
|
488
489
|
readonly id: string
|
|
489
490
|
readonly name: string
|
|
491
|
+
readonly salutation: string | null
|
|
492
|
+
readonly firstName: string | null
|
|
493
|
+
readonly lastName: string | null
|
|
494
|
+
readonly suffix: string | null
|
|
490
495
|
readonly email: string | null
|
|
491
496
|
readonly timezone: string | null
|
|
492
497
|
readonly location: string | null
|
|
@@ -496,17 +501,27 @@ export interface ExportPersonRow {
|
|
|
496
501
|
readonly summary: string
|
|
497
502
|
readonly tags: readonly string[]
|
|
498
503
|
readonly phones: readonly string[]
|
|
504
|
+
readonly doNotContact: boolean
|
|
505
|
+
/**
|
|
506
|
+
* `<purpose_slug>:<status>` pairs joined with '; ', in purpose sort order.
|
|
507
|
+
* Purposes at their default (no explicit `person_consents` row) are omitted.
|
|
508
|
+
*/
|
|
509
|
+
readonly consents: string
|
|
499
510
|
}
|
|
500
511
|
|
|
501
|
-
export function readPeople(
|
|
512
|
+
export async function readPeople(
|
|
502
513
|
db: Queryable,
|
|
503
514
|
workspaceId: string,
|
|
504
515
|
after: string,
|
|
505
516
|
): Promise<ExportPersonRow[]> {
|
|
506
|
-
|
|
517
|
+
const rows = await db
|
|
507
518
|
.select({
|
|
508
519
|
id: people.id,
|
|
509
520
|
name: people.name,
|
|
521
|
+
salutation: people.salutation,
|
|
522
|
+
firstName: people.firstName,
|
|
523
|
+
lastName: people.lastName,
|
|
524
|
+
suffix: people.suffix,
|
|
510
525
|
email: people.email,
|
|
511
526
|
timezone: people.timezone,
|
|
512
527
|
location: people.location,
|
|
@@ -516,11 +531,54 @@ export function readPeople(
|
|
|
516
531
|
summary: people.summary,
|
|
517
532
|
tags: people.tags,
|
|
518
533
|
phones: people.phones,
|
|
534
|
+
doNotContact: people.doNotContact,
|
|
519
535
|
})
|
|
520
536
|
.from(people)
|
|
521
537
|
.where(and(eq(people.workspaceId, workspaceId), gt(people.id, after)))
|
|
522
538
|
.orderBy(asc(people.id))
|
|
523
539
|
.limit(EXPORT_PAGE)
|
|
540
|
+
|
|
541
|
+
if (rows.length === 0) return []
|
|
542
|
+
const consentsByPerson = await readConsentsForExport(
|
|
543
|
+
db,
|
|
544
|
+
workspaceId,
|
|
545
|
+
rows.map((row) => row.id),
|
|
546
|
+
)
|
|
547
|
+
return rows.map((row) => ({
|
|
548
|
+
...row,
|
|
549
|
+
consents: consentsByPerson.get(row.id) ?? '',
|
|
550
|
+
}))
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
async function readConsentsForExport(
|
|
554
|
+
db: Queryable,
|
|
555
|
+
workspaceId: string,
|
|
556
|
+
personIds: readonly string[],
|
|
557
|
+
): Promise<ReadonlyMap<string, string>> {
|
|
558
|
+
const rows = await db
|
|
559
|
+
.select({
|
|
560
|
+
personId: personConsents.personId,
|
|
561
|
+
slug: consentPurposes.slug,
|
|
562
|
+
status: personConsents.status,
|
|
563
|
+
sortOrder: consentPurposes.sortOrder,
|
|
564
|
+
})
|
|
565
|
+
.from(personConsents)
|
|
566
|
+
.innerJoin(consentPurposes, eq(consentPurposes.id, personConsents.purposeId))
|
|
567
|
+
.where(
|
|
568
|
+
and(
|
|
569
|
+
eq(personConsents.workspaceId, workspaceId),
|
|
570
|
+
inArray(personConsents.personId, [...personIds]),
|
|
571
|
+
),
|
|
572
|
+
)
|
|
573
|
+
.orderBy(asc(consentPurposes.sortOrder), asc(consentPurposes.slug))
|
|
574
|
+
|
|
575
|
+
const out = new Map<string, string[]>()
|
|
576
|
+
for (const row of rows) {
|
|
577
|
+
const list = out.get(row.personId) ?? []
|
|
578
|
+
list.push(`${row.slug}:${row.status}`)
|
|
579
|
+
out.set(row.personId, list)
|
|
580
|
+
}
|
|
581
|
+
return new Map(Array.from(out, ([personId, list]) => [personId, list.join('; ')]))
|
|
524
582
|
}
|
|
525
583
|
|
|
526
584
|
export interface ExportPositionRow {
|
|
@@ -604,6 +662,7 @@ export function readDeals(
|
|
|
604
662
|
/** The addresses of the people on each of a page of deals, in one query. */
|
|
605
663
|
export async function readDealPersonEmails(
|
|
606
664
|
db: Queryable,
|
|
665
|
+
workspaceId: string,
|
|
607
666
|
dealIds: readonly string[],
|
|
608
667
|
): Promise<ReadonlyMap<string, readonly string[]>> {
|
|
609
668
|
if (dealIds.length === 0) {
|
|
@@ -611,10 +670,16 @@ export async function readDealPersonEmails(
|
|
|
611
670
|
}
|
|
612
671
|
|
|
613
672
|
const rows = await db
|
|
614
|
-
.select({ dealId:
|
|
615
|
-
.from(
|
|
616
|
-
.innerJoin(people, eq(people.id,
|
|
617
|
-
.where(
|
|
673
|
+
.select({ dealId: personLinks.targetId, email: people.email })
|
|
674
|
+
.from(personLinks)
|
|
675
|
+
.innerJoin(people, eq(people.id, personLinks.personId))
|
|
676
|
+
.where(
|
|
677
|
+
and(
|
|
678
|
+
eq(personLinks.workspaceId, workspaceId),
|
|
679
|
+
eq(personLinks.targetType, 'deal'),
|
|
680
|
+
inArray(personLinks.targetId, [...dealIds]),
|
|
681
|
+
),
|
|
682
|
+
)
|
|
618
683
|
.orderBy(asc(people.email))
|
|
619
684
|
|
|
620
685
|
const byDeal = new Map<string, string[]>()
|
|
@@ -46,6 +46,8 @@ const createJobForm = z.object({
|
|
|
46
46
|
on_missing_company: z.enum(ON_MISSING_COMPANY).default('skip'),
|
|
47
47
|
match_key: z.string().min(1).optional(),
|
|
48
48
|
column_map: z.string().optional(),
|
|
49
|
+
/** People imports only — mirrors on_missing_company's per-object gate. */
|
|
50
|
+
consent_purpose_id: z.string().min(1).optional(),
|
|
49
51
|
dry_run: z.enum(['true', 'false']).default('true'),
|
|
50
52
|
})
|
|
51
53
|
|
|
@@ -63,6 +65,7 @@ export function importJobResponse(job: ImportJobView): Record<string, unknown> {
|
|
|
63
65
|
on_missing_company: job.onMissingCompany,
|
|
64
66
|
match_key: job.matchKey,
|
|
65
67
|
column_map: job.columnMap,
|
|
68
|
+
consent_purpose_id: job.consentPurposeId,
|
|
66
69
|
source_headers: job.sourceHeaders,
|
|
67
70
|
file_name: job.fileName,
|
|
68
71
|
counts: job.counts,
|
|
@@ -237,6 +240,7 @@ export function mountImportExportRoutes(
|
|
|
237
240
|
onMissingCompany: parsed.data.on_missing_company,
|
|
238
241
|
matchKeyId: parsed.data.match_key ?? defaultMatchKeyId(parsed.data.object),
|
|
239
242
|
columnMap: readColumnMap(parsed.data.column_map),
|
|
243
|
+
consentPurposeId: parsed.data.consent_purpose_id ?? null,
|
|
240
244
|
fileName: file.name.length === 0 ? null : file.name,
|
|
241
245
|
csv: await file.text(),
|
|
242
246
|
})
|
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
import { index, integer, jsonb, pgTable, primaryKey, text } from 'drizzle-orm/pg-core'
|
|
16
16
|
|
|
17
17
|
import { checkOneOf, createdAt, primaryId, updatedAt } from '../../lib/columns.ts'
|
|
18
|
+
import { consentPurposes } from '../consent-purposes/schema.ts'
|
|
18
19
|
import { workspaces } from '../workspace/schema.ts'
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -78,6 +79,16 @@ export const importJobs = pgTable(
|
|
|
78
79
|
onMissingCompany: text('on_missing_company').notNull().default('skip'),
|
|
79
80
|
matchKey: text('match_key').notNull(),
|
|
80
81
|
columnMap: jsonb('column_map').$type<ImportColumnMap>().notNull().default({}),
|
|
82
|
+
/**
|
|
83
|
+
* The consent purpose a People import grants for each row that carries a
|
|
84
|
+
* `consent_status`. Required whenever the map names `consent_status` or
|
|
85
|
+
* `consent_at`; null on every other object and on People jobs that skip
|
|
86
|
+
* consent columns. `set null` on delete so a purpose can be removed
|
|
87
|
+
* without invalidating an old job.
|
|
88
|
+
*/
|
|
89
|
+
consentPurposeId: text('consent_purpose_id').references(() => consentPurposes.id, {
|
|
90
|
+
onDelete: 'set null',
|
|
91
|
+
}),
|
|
81
92
|
sourceHeaders: jsonb('source_headers').$type<readonly string[]>().notNull().default([]),
|
|
82
93
|
counts: jsonb('counts').$type<ImportCounts>().notNull(),
|
|
83
94
|
/** The first `IMPORT_REPORTED_ERRORS` failing rows. `counts.error` is the true number. */
|
|
@@ -99,7 +99,7 @@ function emitImportedRecordUpdated(
|
|
|
99
99
|
}
|
|
100
100
|
import { CsvFormatError, csvLine, fileDigest, parseCsv } from './csv.ts'
|
|
101
101
|
import type { CsvRow, ParsedCsv } from './csv.ts'
|
|
102
|
-
import {
|
|
102
|
+
import { templateHeadersFor } from './exportRows.ts'
|
|
103
103
|
import { buildMatchKey, mapRow, splitList } from './mapping.ts'
|
|
104
104
|
import { applyWrite } from './writes.ts'
|
|
105
105
|
import { countPlans, planRow, planRows } from './plan.ts'
|
|
@@ -146,6 +146,7 @@ export interface ImportJobView {
|
|
|
146
146
|
readonly onMissingCompany: OnMissingCompany
|
|
147
147
|
readonly matchKey: string
|
|
148
148
|
readonly columnMap: ImportColumnMap
|
|
149
|
+
readonly consentPurposeId: string | null
|
|
149
150
|
readonly sourceHeaders: readonly string[]
|
|
150
151
|
readonly fileName: string | null
|
|
151
152
|
readonly counts: ImportCounts
|
|
@@ -164,6 +165,11 @@ export interface CreateImportJobInput {
|
|
|
164
165
|
readonly matchKeyId: string
|
|
165
166
|
/** Absent means "derive one from the source preset and the file's own headers". */
|
|
166
167
|
readonly columnMap: ImportColumnMap | undefined
|
|
168
|
+
/**
|
|
169
|
+
* People imports only. Required whenever the mapping names `consent_status`
|
|
170
|
+
* or `consent_at`, refused with `422` for any other object.
|
|
171
|
+
*/
|
|
172
|
+
readonly consentPurposeId: string | null
|
|
167
173
|
readonly fileName: string | null
|
|
168
174
|
readonly csv: string
|
|
169
175
|
}
|
|
@@ -460,6 +466,7 @@ export function createImportExportService(
|
|
|
460
466
|
matchKey: requireMatchKey(job.object as ImportObject, job.matchKey),
|
|
461
467
|
conflictMode: job.conflictMode as ImportConflictMode,
|
|
462
468
|
onMissingCompany: job.onMissingCompany as OnMissingCompany,
|
|
469
|
+
consentPurposeId: job.consentPurposeId,
|
|
463
470
|
lookups,
|
|
464
471
|
}
|
|
465
472
|
}
|
|
@@ -837,6 +844,24 @@ export function createImportExportService(
|
|
|
837
844
|
|
|
838
845
|
requireUsableColumnMap(input.object, matchKey, columnMap, parsed.headers)
|
|
839
846
|
|
|
847
|
+
// Consent is a People-only feature. A purpose on any other object is
|
|
848
|
+
// refused up front; mapping the consent columns without one is refused
|
|
849
|
+
// too — the writer would have no purpose to grant against.
|
|
850
|
+
const mapsConsentColumn =
|
|
851
|
+
columnMap.consent_status !== null || columnMap.consent_at !== null
|
|
852
|
+
if (input.consentPurposeId !== null && input.object !== 'people') {
|
|
853
|
+
throw AppError.validationFailed(
|
|
854
|
+
'consent_purpose_id is only accepted on people imports',
|
|
855
|
+
[{ field: 'consent_purpose_id', message: 'People imports only' }],
|
|
856
|
+
)
|
|
857
|
+
}
|
|
858
|
+
if (input.object === 'people' && mapsConsentColumn && input.consentPurposeId === null) {
|
|
859
|
+
throw AppError.validationFailed(
|
|
860
|
+
'Mapping consent_status or consent_at needs a consent_purpose_id on the job',
|
|
861
|
+
[{ field: 'consent_purpose_id', message: 'Required when consent columns are mapped' }],
|
|
862
|
+
)
|
|
863
|
+
}
|
|
864
|
+
|
|
840
865
|
const id = dependencies.createId('importJob')
|
|
841
866
|
const now = dependencies.now()
|
|
842
867
|
|
|
@@ -853,6 +878,7 @@ export function createImportExportService(
|
|
|
853
878
|
onMissingCompany: input.onMissingCompany,
|
|
854
879
|
matchKey: matchKey.id,
|
|
855
880
|
columnMap,
|
|
881
|
+
consentPurposeId: input.consentPurposeId,
|
|
856
882
|
sourceHeaders: parsed.headers,
|
|
857
883
|
counts: { ...EMPTY_COUNTS, total: parsed.rows.length },
|
|
858
884
|
errors: [],
|
|
@@ -970,7 +996,7 @@ export function createImportExportService(
|
|
|
970
996
|
},
|
|
971
997
|
|
|
972
998
|
templateCsv(object) {
|
|
973
|
-
return csvLine(
|
|
999
|
+
return csvLine(templateHeadersFor(object))
|
|
974
1000
|
},
|
|
975
1001
|
}
|
|
976
1002
|
}
|
|
@@ -52,10 +52,12 @@ async function* pageThrough<TRow extends { readonly id: string }>(
|
|
|
52
52
|
/** The rows of one page, all their people in one query rather than one per deal. */
|
|
53
53
|
async function dealPage(
|
|
54
54
|
db: Database,
|
|
55
|
+
workspaceId: string,
|
|
55
56
|
rows: readonly repository.ExportDealRow[],
|
|
56
57
|
): Promise<readonly (readonly string[])[]> {
|
|
57
58
|
const emails = await repository.readDealPersonEmails(
|
|
58
59
|
db,
|
|
60
|
+
workspaceId,
|
|
59
61
|
rows.map((row) => row.id),
|
|
60
62
|
)
|
|
61
63
|
|
|
@@ -91,7 +93,7 @@ export async function* streamExport(
|
|
|
91
93
|
case 'deals':
|
|
92
94
|
yield* pageThrough({
|
|
93
95
|
read: (after) => repository.readDeals(db, workspaceId, after),
|
|
94
|
-
cells: (rows) => dealPage(db, rows),
|
|
96
|
+
cells: (rows) => dealPage(db, workspaceId, rows),
|
|
95
97
|
})
|
|
96
98
|
return
|
|
97
99
|
}
|
|
@@ -69,6 +69,15 @@ const previewArgs = z.strictObject({
|
|
|
69
69
|
),
|
|
70
70
|
match_key: z.string().min(1).optional().describe('Which field decides that match.'),
|
|
71
71
|
column_map: columnMapArg.optional(),
|
|
72
|
+
consent_purpose_id: z
|
|
73
|
+
.string()
|
|
74
|
+
.min(1)
|
|
75
|
+
.nullable()
|
|
76
|
+
.default(null)
|
|
77
|
+
.describe(
|
|
78
|
+
'People imports only: the consent purpose a row grants for each `consent_status`. ' +
|
|
79
|
+
'Required whenever consent_status or consent_at is mapped.',
|
|
80
|
+
),
|
|
72
81
|
file_name: z.string().min(1).nullable().default(null).describe('Recorded on the job, for the log.'),
|
|
73
82
|
})
|
|
74
83
|
|
|
@@ -135,6 +144,7 @@ export function registerImportExportTools(mcp: McpToolRegistry, service: ImportE
|
|
|
135
144
|
onMissingCompany: args.on_missing_company,
|
|
136
145
|
matchKeyId: args.match_key ?? defaultMatchKeyId(args.object),
|
|
137
146
|
columnMap: args.column_map,
|
|
147
|
+
consentPurposeId: args.consent_purpose_id,
|
|
138
148
|
fileName: args.file_name,
|
|
139
149
|
csv: args.csv,
|
|
140
150
|
}),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACCOUNT_TYPES,
|
|
3
3
|
COMPANY_STAGES,
|
|
4
|
+
CONSENT_STATUSES,
|
|
4
5
|
ICP_FITS,
|
|
5
6
|
INFLUENCE_LEVELS,
|
|
6
7
|
PREFERRED_CHANNELS,
|
|
@@ -90,7 +91,28 @@ function checkCompany(errors: StoredRowError[], mapped: Readonly<Record<string,
|
|
|
90
91
|
checkEnum(errors, 'icp_fit', ICP_FITS, mapped.icp_fit)
|
|
91
92
|
}
|
|
92
93
|
|
|
94
|
+
/**
|
|
95
|
+
* A People row names its person one way or the other.
|
|
96
|
+
*
|
|
97
|
+
* `name` is not a `required` column, because the requirement is really about a
|
|
98
|
+
* pair of them: the row carries a full `name`, or the `first_name` /
|
|
99
|
+
* `last_name` cells for one to be composed from. Most CRMs export the parts and
|
|
100
|
+
* no full name, and refusing every row of such a file over a column it was
|
|
101
|
+
* never going to have is the migration nobody finishes.
|
|
102
|
+
*/
|
|
103
|
+
function checkPersonName(errors: StoredRowError[], mapped: Readonly<Record<string, string>>): void {
|
|
104
|
+
const named = ['name', 'first_name', 'last_name'].some(
|
|
105
|
+
(column) => (mapped[column] ?? '').trim().length > 0,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if (!named) {
|
|
109
|
+
errors.push({ field: 'name', message: 'Missing a name, first_name or last_name' })
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
93
113
|
function checkPerson(errors: StoredRowError[], mapped: Readonly<Record<string, string>>): void {
|
|
114
|
+
checkPersonName(errors, mapped)
|
|
115
|
+
|
|
94
116
|
const email = (mapped.email ?? '').trim()
|
|
95
117
|
|
|
96
118
|
if (email.length > 0 && !EMAIL_SHAPE.test(email)) {
|
|
@@ -100,6 +122,12 @@ function checkPerson(errors: StoredRowError[], mapped: Readonly<Record<string, s
|
|
|
100
122
|
checkEnum(errors, 'preferred_channel', PREFERRED_CHANNELS, mapped.preferred_channel)
|
|
101
123
|
checkEnum(errors, 'influence', INFLUENCE_LEVELS, mapped.influence)
|
|
102
124
|
checkEnum(errors, 'relationship', RELATIONSHIP_LEVELS, mapped.relationship)
|
|
125
|
+
checkEnum(errors, 'consent_status', CONSENT_STATUSES, mapped.consent_status)
|
|
126
|
+
|
|
127
|
+
const consentAt = (mapped.consent_at ?? '').trim()
|
|
128
|
+
if (consentAt.length > 0 && !isoDateSchema.safeParse(consentAt).success) {
|
|
129
|
+
errors.push({ field: 'consent_at', message: `"${consentAt}" is not a date. Use YYYY-MM-DD` })
|
|
130
|
+
}
|
|
103
131
|
}
|
|
104
132
|
|
|
105
133
|
function checkPosition(errors: StoredRowError[], mapped: Readonly<Record<string, string>>): void {
|