@kelpie/server 0.8.0 → 0.10.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/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ids.d.ts +11 -0
- package/dist/lib/ids.d.ts.map +1 -1
- package/dist/lib/ids.js +11 -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 +15 -1
- package/dist/modules/attachedRecords.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/routes.d.ts +14 -0
- package/dist/modules/companies/routes.d.ts.map +1 -1
- package/dist/modules/companies/routes.js +7 -0
- package/dist/modules/companies/routes.js.map +1 -1
- package/dist/modules/companies/schema.d.ts +20 -0
- package/dist/modules/companies/schema.d.ts.map +1 -1
- package/dist/modules/companies/schema.js +6 -1
- package/dist/modules/companies/schema.js.map +1 -1
- package/dist/modules/companies/service.d.ts +5 -0
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +24 -12
- 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 +10 -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/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 +3 -0
- package/dist/modules/eventCatalogs.d.ts.map +1 -1
- package/dist/modules/eventCatalogs.js +3 -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/index.d.ts +38 -0
- package/dist/modules/lists/index.d.ts.map +1 -1
- package/dist/modules/lists/index.js +27 -0
- package/dist/modules/lists/index.js.map +1 -1
- package/dist/modules/lists/repository.d.ts +26 -0
- package/dist/modules/lists/repository.d.ts.map +1 -1
- package/dist/modules/lists/repository.js +32 -0
- package/dist/modules/lists/repository.js.map +1 -1
- package/dist/modules/lists/routes.d.ts +4 -0
- package/dist/modules/lists/routes.d.ts.map +1 -1
- package/dist/modules/lists/routes.js +8 -0
- package/dist/modules/lists/routes.js.map +1 -1
- package/dist/modules/lists/schema.d.ts +17 -0
- package/dist/modules/lists/schema.d.ts.map +1 -1
- package/dist/modules/lists/schema.js +10 -0
- package/dist/modules/lists/schema.js.map +1 -1
- package/dist/modules/lists/service.d.ts +14 -2
- package/dist/modules/lists/service.d.ts.map +1 -1
- package/dist/modules/lists/service.js +55 -7
- package/dist/modules/lists/service.js.map +1 -1
- 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.map +1 -1
- package/dist/modules/people/repository.js +5 -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 +115 -38
- 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/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 +21 -0
- package/dist/modules/sample-data/fixture.d.ts.map +1 -1
- package/dist/modules/sample-data/fixture.js +40 -0
- package/dist/modules/sample-data/fixture.js.map +1 -1
- package/dist/modules/sample-data/index.d.ts.map +1 -1
- package/dist/modules/sample-data/index.js +1 -0
- package/dist/modules/sample-data/index.js.map +1 -1
- package/dist/modules/sample-data/routes.d.ts.map +1 -1
- package/dist/modules/sample-data/routes.js +1 -0
- package/dist/modules/sample-data/routes.js.map +1 -1
- package/dist/modules/sample-data/service.d.ts +1 -0
- package/dist/modules/sample-data/service.d.ts.map +1 -1
- package/dist/modules/sample-data/service.js +77 -8
- package/dist/modules/sample-data/service.js.map +1 -1
- 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/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 +10 -0
- 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 +3 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +3 -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/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/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 +91 -0
- package/package.json +2 -2
- package/src/index.ts +6 -0
- package/src/lib/ids.ts +11 -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 +29 -2
- package/src/modules/companies/index.ts +3 -1
- package/src/modules/companies/routes.ts +7 -0
- package/src/modules/companies/schema.ts +7 -1
- package/src/modules/companies/service.ts +48 -13
- 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 +10 -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/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 +3 -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/index.ts +71 -0
- package/src/modules/lists/repository.ts +64 -0
- package/src/modules/lists/routes.ts +8 -0
- package/src/modules/lists/schema.ts +10 -0
- package/src/modules/lists/service.ts +110 -9
- 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 +5 -0
- package/src/modules/people/routes.ts +127 -18
- package/src/modules/people/schema.ts +109 -3
- package/src/modules/people/service.ts +186 -40
- package/src/modules/people/tools.ts +5 -1
- package/src/modules/personLinks.ts +278 -0
- 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 +63 -0
- package/src/modules/sample-data/index.ts +1 -0
- package/src/modules/sample-data/routes.ts +1 -0
- package/src/modules/sample-data/service.ts +97 -8
- 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/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 +14 -0
- package/src/modules/workspace/starters.ts +5 -0
- package/src/runtime/events.ts +1 -0
- package/src/schema/index.ts +3 -0
- package/src/testing/database.ts +97 -11
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
import { CONSENT_PURPOSE_STATUSES } from '@kelpie/schemas'
|
|
2
|
+
import type { ConsentPurposeStatus } from '@kelpie/schemas'
|
|
3
|
+
import { and, eq, sql } from 'drizzle-orm'
|
|
4
|
+
|
|
5
|
+
import { toEventActor } from '../../lib/actor.ts'
|
|
6
|
+
import { changedKeys } from '../../lib/changes.ts'
|
|
7
|
+
import {
|
|
8
|
+
FOREIGN_KEY_VIOLATION,
|
|
9
|
+
UNIQUE_VIOLATION,
|
|
10
|
+
postgresErrorCode,
|
|
11
|
+
} from '../../lib/database.ts'
|
|
12
|
+
import type { Database } from '../../lib/database.ts'
|
|
13
|
+
import { AppError } from '../../lib/errors.ts'
|
|
14
|
+
import type { IdFactory } from '../../lib/ids.ts'
|
|
15
|
+
import { mapPage, readListWindow, toPage } from '../../lib/pagination.ts'
|
|
16
|
+
import type { ListQueryParameters, Page } from '../../lib/pagination.ts'
|
|
17
|
+
import type { EntitlementRegistry } from '../../runtime/entitlements.ts'
|
|
18
|
+
import { limitFor } from '../../runtime/entitlements.ts'
|
|
19
|
+
import type { Transaction, TransactionScope } from '../../runtime/transaction.ts'
|
|
20
|
+
import type { Actor } from '../auth/actor.ts'
|
|
21
|
+
import { requireWorkspaceId } from '../auth/actor.ts'
|
|
22
|
+
import { formFields } from '../forms/schema.ts'
|
|
23
|
+
import { lists } from '../lists/schema.ts'
|
|
24
|
+
import { roleAllows } from '../workspace/roles.ts'
|
|
25
|
+
import { CONSENT_PURPOSES_LIMIT } from './capabilities.ts'
|
|
26
|
+
import './events.ts'
|
|
27
|
+
import * as repository from './repository.ts'
|
|
28
|
+
import {
|
|
29
|
+
CONSENT_PURPOSE_SORTS,
|
|
30
|
+
DEFAULT_CONSENT_PURPOSE_SORT,
|
|
31
|
+
} from './repository.ts'
|
|
32
|
+
import type {
|
|
33
|
+
ConsentPurposeFilters,
|
|
34
|
+
ConsentPurposeRecord,
|
|
35
|
+
} from './repository.ts'
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* CRUD for the workspace's consent purposes.
|
|
39
|
+
*
|
|
40
|
+
* Reads are open to any workspace member — every capture site needs to list
|
|
41
|
+
* them to render its purpose picker. Writes need the admin role: a purpose
|
|
42
|
+
* change touches every form, list, and import job that names it, and it is
|
|
43
|
+
* team-wide config rather than a per-user preference.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/** Hard cap per workspace. Bites when the entitlement leaves the count unlimited. */
|
|
47
|
+
export const CONSENT_PURPOSES_HARD_CAP = 50
|
|
48
|
+
|
|
49
|
+
const KEY_PATTERN = /^[a-z][a-z0-9_]*$/u
|
|
50
|
+
const MAX_SLUG_LENGTH = 64
|
|
51
|
+
const MAX_LABEL_LENGTH = 120
|
|
52
|
+
const MIN_LABEL_LENGTH = 1
|
|
53
|
+
const MAX_DESCRIPTION_LENGTH = 2000
|
|
54
|
+
|
|
55
|
+
export interface ConsentPurposesDependencies {
|
|
56
|
+
readonly db: Database
|
|
57
|
+
readonly transaction: TransactionScope
|
|
58
|
+
readonly createId: IdFactory
|
|
59
|
+
readonly now: () => Date
|
|
60
|
+
readonly entitlements: EntitlementRegistry
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** What the API returns: the stored row minus the tenancy column. */
|
|
64
|
+
export type ConsentPurposeView = Omit<ConsentPurposeRecord, 'workspaceId'>
|
|
65
|
+
|
|
66
|
+
export interface CreateConsentPurposeInput {
|
|
67
|
+
readonly slug: string
|
|
68
|
+
readonly label: string
|
|
69
|
+
readonly description: string
|
|
70
|
+
readonly defaultStatus: ConsentPurposeStatus
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** PATCH semantics: `slug` is immutable and refused by the route body. */
|
|
74
|
+
export interface UpdateConsentPurposeInput {
|
|
75
|
+
readonly label?: string | undefined
|
|
76
|
+
readonly description?: string | undefined
|
|
77
|
+
readonly defaultStatus?: ConsentPurposeStatus | undefined
|
|
78
|
+
readonly sortOrder?: number | undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface ConsentPurposesService {
|
|
82
|
+
list(
|
|
83
|
+
actor: Actor,
|
|
84
|
+
filters: ConsentPurposeFilters,
|
|
85
|
+
query: ListQueryParameters,
|
|
86
|
+
): Promise<Page<ConsentPurposeView>>
|
|
87
|
+
get(actor: Actor, id: string): Promise<ConsentPurposeView>
|
|
88
|
+
create(actor: Actor, input: CreateConsentPurposeInput): Promise<ConsentPurposeView>
|
|
89
|
+
update(
|
|
90
|
+
actor: Actor,
|
|
91
|
+
id: string,
|
|
92
|
+
changes: UpdateConsentPurposeInput,
|
|
93
|
+
): Promise<ConsentPurposeView>
|
|
94
|
+
remove(actor: Actor, id: string): Promise<void>
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function toView(record: ConsentPurposeRecord): ConsentPurposeView {
|
|
98
|
+
const { workspaceId: _workspaceId, ...view } = record
|
|
99
|
+
return view
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function fieldError(field: string, message: string): AppError {
|
|
103
|
+
return AppError.validationFailed('That consent purpose is not valid', [{ field, message }])
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function duplicateSlug(): AppError {
|
|
107
|
+
return AppError.conflict('Another consent purpose already uses that slug', [
|
|
108
|
+
{ field: 'slug', message: 'Already in use' },
|
|
109
|
+
])
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function validateSlug(slug: string): void {
|
|
113
|
+
if (slug.length === 0 || slug.length > MAX_SLUG_LENGTH) {
|
|
114
|
+
throw fieldError('slug', `1 to ${String(MAX_SLUG_LENGTH)} characters`)
|
|
115
|
+
}
|
|
116
|
+
if (!KEY_PATTERN.test(slug)) {
|
|
117
|
+
throw fieldError(
|
|
118
|
+
'slug',
|
|
119
|
+
'Lowercase letters, digits and underscores; must start with a letter',
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function validateLabel(label: string): void {
|
|
125
|
+
if (label.length < MIN_LABEL_LENGTH || label.length > MAX_LABEL_LENGTH) {
|
|
126
|
+
throw fieldError(
|
|
127
|
+
'label',
|
|
128
|
+
`${String(MIN_LABEL_LENGTH)} to ${String(MAX_LABEL_LENGTH)} characters`,
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function validateDescription(description: string): void {
|
|
134
|
+
if (description.length > MAX_DESCRIPTION_LENGTH) {
|
|
135
|
+
throw fieldError('description', `At most ${String(MAX_DESCRIPTION_LENGTH)} characters`)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function validateDefaultStatus(status: string): void {
|
|
140
|
+
if (!CONSENT_PURPOSE_STATUSES.includes(status as ConsentPurposeStatus)) {
|
|
141
|
+
throw fieldError('default_status', `Unknown status "${status}"`)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* A purpose still named by a form's consent field or a list's
|
|
147
|
+
* `consent_purpose_id` cannot be deleted. Counted here so the 409 lists both
|
|
148
|
+
* types; the FK on either side would refuse the delete on its own but only
|
|
149
|
+
* name one.
|
|
150
|
+
*/
|
|
151
|
+
async function referencingTypes(
|
|
152
|
+
db: Database | Transaction,
|
|
153
|
+
workspaceId: string,
|
|
154
|
+
id: string,
|
|
155
|
+
): Promise<readonly string[]> {
|
|
156
|
+
const [fieldRow, listRow] = await Promise.all([
|
|
157
|
+
db
|
|
158
|
+
.select({ count: sql<number>`count(*)::int` })
|
|
159
|
+
.from(formFields)
|
|
160
|
+
.where(
|
|
161
|
+
and(
|
|
162
|
+
eq(formFields.workspaceId, workspaceId),
|
|
163
|
+
// The array contains this purpose id. A form field carries a set of
|
|
164
|
+
// purposes; the delete is refused if any field still lists this one.
|
|
165
|
+
sql`${id} = ANY(${formFields.consentPurposeIds})`,
|
|
166
|
+
),
|
|
167
|
+
),
|
|
168
|
+
db
|
|
169
|
+
.select({ count: sql<number>`count(*)::int` })
|
|
170
|
+
.from(lists)
|
|
171
|
+
.where(and(eq(lists.workspaceId, workspaceId), eq(lists.consentPurposeId, id))),
|
|
172
|
+
])
|
|
173
|
+
|
|
174
|
+
const referencing: string[] = []
|
|
175
|
+
if (Number(fieldRow[0]?.count ?? 0) > 0) {
|
|
176
|
+
referencing.push('form_field')
|
|
177
|
+
}
|
|
178
|
+
if (Number(listRow[0]?.count ?? 0) > 0) {
|
|
179
|
+
referencing.push('list')
|
|
180
|
+
}
|
|
181
|
+
return referencing
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function createConsentPurposesService(
|
|
185
|
+
dependencies: ConsentPurposesDependencies,
|
|
186
|
+
): ConsentPurposesService {
|
|
187
|
+
function requireAdminWorkspace(actor: Actor): string {
|
|
188
|
+
const workspaceId = requireWorkspaceId(actor)
|
|
189
|
+
if (actor.role === null || !roleAllows(actor.role, 'admin')) {
|
|
190
|
+
throw new AppError('forbidden', 'This action needs the admin role')
|
|
191
|
+
}
|
|
192
|
+
return workspaceId
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function require(
|
|
196
|
+
workspaceId: string,
|
|
197
|
+
id: string,
|
|
198
|
+
): Promise<ConsentPurposeRecord> {
|
|
199
|
+
const purpose = await repository.findPurpose(dependencies.db, workspaceId, id)
|
|
200
|
+
if (purpose === undefined) {
|
|
201
|
+
throw AppError.notFound('Consent purpose not found')
|
|
202
|
+
}
|
|
203
|
+
return purpose
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function renumber(
|
|
207
|
+
tx: Transaction,
|
|
208
|
+
workspaceId: string,
|
|
209
|
+
order: readonly ConsentPurposeRecord[],
|
|
210
|
+
): Promise<void> {
|
|
211
|
+
for (const [index, purpose] of order.entries()) {
|
|
212
|
+
if (purpose.sortOrder !== index) {
|
|
213
|
+
await repository.updatePurpose(tx, workspaceId, purpose.id, {
|
|
214
|
+
sortOrder: index,
|
|
215
|
+
updatedAt: dependencies.now(),
|
|
216
|
+
})
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function moveToPosition(
|
|
222
|
+
tx: Transaction,
|
|
223
|
+
workspaceId: string,
|
|
224
|
+
purpose: ConsentPurposeRecord,
|
|
225
|
+
position: number,
|
|
226
|
+
): Promise<void> {
|
|
227
|
+
const rows = await repository.purposesForWorkspace(tx, workspaceId)
|
|
228
|
+
const target = rows.find((row) => row.id === purpose.id)
|
|
229
|
+
if (target === undefined) {
|
|
230
|
+
throw AppError.notFound('Consent purpose not found')
|
|
231
|
+
}
|
|
232
|
+
if (position < 0 || position >= rows.length) {
|
|
233
|
+
throw fieldError('sort_order', `Use 0 to ${String(rows.length - 1)}`)
|
|
234
|
+
}
|
|
235
|
+
const reordered = rows.filter((row) => row.id !== purpose.id)
|
|
236
|
+
reordered.splice(position, 0, target)
|
|
237
|
+
await renumber(tx, workspaceId, reordered)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
async list(actor, filters, query) {
|
|
242
|
+
const workspaceId = requireWorkspaceId(actor)
|
|
243
|
+
const window = readListWindow(query, CONSENT_PURPOSE_SORTS, DEFAULT_CONSENT_PURPOSE_SORT)
|
|
244
|
+
const rows = await repository.listPurposes(dependencies.db, workspaceId, filters, window)
|
|
245
|
+
return mapPage(toPage(rows, window, (row) => row.id), toView)
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
async get(actor, id) {
|
|
249
|
+
return toView(await require(requireWorkspaceId(actor), id))
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
async create(actor, input) {
|
|
253
|
+
const workspaceId = requireAdminWorkspace(actor)
|
|
254
|
+
validateSlug(input.slug)
|
|
255
|
+
validateLabel(input.label)
|
|
256
|
+
validateDescription(input.description)
|
|
257
|
+
validateDefaultStatus(input.defaultStatus)
|
|
258
|
+
|
|
259
|
+
const limit = await limitFor(
|
|
260
|
+
dependencies.entitlements,
|
|
261
|
+
workspaceId,
|
|
262
|
+
CONSENT_PURPOSES_LIMIT.name,
|
|
263
|
+
)
|
|
264
|
+
if (limit !== null) {
|
|
265
|
+
const total = await repository.countPurposes(dependencies.db, workspaceId)
|
|
266
|
+
if (total >= limit) {
|
|
267
|
+
throw new AppError(
|
|
268
|
+
'entitlement_required',
|
|
269
|
+
`Your plan allows ${String(limit)} consent purpose${limit === 1 ? '' : 's'}`,
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const id = dependencies.createId('consentPurpose')
|
|
275
|
+
|
|
276
|
+
return dependencies.transaction(
|
|
277
|
+
async ({ tx, events }) => {
|
|
278
|
+
const existing = await repository.purposesForWorkspace(tx, workspaceId)
|
|
279
|
+
if (existing.length >= CONSENT_PURPOSES_HARD_CAP) {
|
|
280
|
+
throw AppError.conflict(
|
|
281
|
+
`A workspace may define at most ${String(CONSENT_PURPOSES_HARD_CAP)} consent purposes`,
|
|
282
|
+
[{ field: 'slug', message: 'Limit reached' }],
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
let created: ConsentPurposeRecord
|
|
287
|
+
try {
|
|
288
|
+
created = await repository.insertPurpose(tx, {
|
|
289
|
+
id,
|
|
290
|
+
workspaceId,
|
|
291
|
+
slug: input.slug,
|
|
292
|
+
label: input.label,
|
|
293
|
+
description: input.description,
|
|
294
|
+
defaultStatus: input.defaultStatus,
|
|
295
|
+
sortOrder: (existing.at(-1)?.sortOrder ?? -1) + 1,
|
|
296
|
+
})
|
|
297
|
+
} catch (error: unknown) {
|
|
298
|
+
if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
|
|
299
|
+
throw duplicateSlug()
|
|
300
|
+
}
|
|
301
|
+
throw error
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
events.emit(
|
|
305
|
+
'consent_purposes.purpose.created',
|
|
306
|
+
{ type: 'consent_purpose', id: created.id },
|
|
307
|
+
{ slug: created.slug },
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return toView(created)
|
|
311
|
+
},
|
|
312
|
+
{ workspaceId, actor: toEventActor(actor) },
|
|
313
|
+
)
|
|
314
|
+
},
|
|
315
|
+
|
|
316
|
+
async update(actor, id, changes) {
|
|
317
|
+
const workspaceId = requireAdminWorkspace(actor)
|
|
318
|
+
const existing = await require(workspaceId, id)
|
|
319
|
+
|
|
320
|
+
if (changes.label !== undefined) {
|
|
321
|
+
validateLabel(changes.label)
|
|
322
|
+
}
|
|
323
|
+
if (changes.description !== undefined) {
|
|
324
|
+
validateDescription(changes.description)
|
|
325
|
+
}
|
|
326
|
+
if (changes.defaultStatus !== undefined) {
|
|
327
|
+
validateDefaultStatus(changes.defaultStatus)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const columns: Partial<repository.ConsentPurposeColumns> = {
|
|
331
|
+
...(changes.label === undefined ? {} : { label: changes.label }),
|
|
332
|
+
...(changes.description === undefined ? {} : { description: changes.description }),
|
|
333
|
+
...(changes.defaultStatus === undefined
|
|
334
|
+
? {}
|
|
335
|
+
: { defaultStatus: changes.defaultStatus }),
|
|
336
|
+
}
|
|
337
|
+
const changed = changedKeys(existing, columns)
|
|
338
|
+
const position = changes.sortOrder
|
|
339
|
+
|
|
340
|
+
if (changed.length === 0 && position === undefined) {
|
|
341
|
+
return toView(existing)
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return dependencies.transaction(
|
|
345
|
+
async ({ tx, events }) => {
|
|
346
|
+
if (position !== undefined) {
|
|
347
|
+
await moveToPosition(tx, workspaceId, existing, position)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
let updated: ConsentPurposeRecord | undefined
|
|
351
|
+
if (changed.length > 0) {
|
|
352
|
+
updated = await repository.updatePurpose(tx, workspaceId, id, {
|
|
353
|
+
...columns,
|
|
354
|
+
updatedAt: dependencies.now(),
|
|
355
|
+
})
|
|
356
|
+
if (updated === undefined) {
|
|
357
|
+
throw AppError.notFound('Consent purpose not found')
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
updated = await repository.findPurpose(tx, workspaceId, id)
|
|
361
|
+
if (updated === undefined) {
|
|
362
|
+
throw AppError.notFound('Consent purpose not found')
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (changed.length > 0 || position !== undefined) {
|
|
367
|
+
const changedPaths = [
|
|
368
|
+
...changed,
|
|
369
|
+
...(position !== undefined && position !== existing.sortOrder ? ['sortOrder'] : []),
|
|
370
|
+
]
|
|
371
|
+
events.emit(
|
|
372
|
+
'consent_purposes.purpose.updated',
|
|
373
|
+
{ type: 'consent_purpose', id },
|
|
374
|
+
{ slug: updated.slug, changed: changedPaths },
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return toView(updated)
|
|
379
|
+
},
|
|
380
|
+
{ workspaceId, actor: toEventActor(actor) },
|
|
381
|
+
)
|
|
382
|
+
},
|
|
383
|
+
|
|
384
|
+
async remove(actor, id) {
|
|
385
|
+
const workspaceId = requireAdminWorkspace(actor)
|
|
386
|
+
const existing = await require(workspaceId, id)
|
|
387
|
+
|
|
388
|
+
await dependencies.transaction(
|
|
389
|
+
async ({ tx, events }) => {
|
|
390
|
+
const referencing = await referencingTypes(tx, workspaceId, id)
|
|
391
|
+
if (referencing.length > 0) {
|
|
392
|
+
throw AppError.conflict(
|
|
393
|
+
'Remove this purpose from every form and list that names it before deleting it',
|
|
394
|
+
referencing.map((type) => ({ field: type, message: 'still references this purpose' })),
|
|
395
|
+
)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
try {
|
|
399
|
+
await repository.deletePurpose(tx, workspaceId, id)
|
|
400
|
+
} catch (error: unknown) {
|
|
401
|
+
if (postgresErrorCode(error) === FOREIGN_KEY_VIOLATION) {
|
|
402
|
+
throw AppError.conflict(
|
|
403
|
+
'Remove this purpose from every form and list that names it before deleting it',
|
|
404
|
+
[{ field: 'id', message: 'still referenced' }],
|
|
405
|
+
)
|
|
406
|
+
}
|
|
407
|
+
throw error
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const survivors = await repository.purposesForWorkspace(tx, workspaceId)
|
|
411
|
+
await renumber(tx, workspaceId, survivors)
|
|
412
|
+
|
|
413
|
+
events.emit(
|
|
414
|
+
'consent_purposes.purpose.deleted',
|
|
415
|
+
{ type: 'consent_purpose', id },
|
|
416
|
+
{ slug: existing.slug },
|
|
417
|
+
)
|
|
418
|
+
},
|
|
419
|
+
{ workspaceId, actor: toEventActor(actor) },
|
|
420
|
+
)
|
|
421
|
+
},
|
|
422
|
+
}
|
|
423
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ConsentPurposeStatus } from '@kelpie/schemas'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The purposes a new workspace starts with. Data, not migrations: a workspace
|
|
5
|
+
* owner may rename, reorder, or delete them, and add any others they need.
|
|
6
|
+
*
|
|
7
|
+
* Both starters default to `unknown` — silence about a person's wishes is not
|
|
8
|
+
* a grant, and every capture site (forms, lists, imports, manual override)
|
|
9
|
+
* writes an explicit `person_consents` row when consent is actually given.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export interface StarterConsentPurpose {
|
|
13
|
+
readonly slug: string
|
|
14
|
+
readonly label: string
|
|
15
|
+
readonly description: string
|
|
16
|
+
readonly defaultStatus: ConsentPurposeStatus
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const STARTER_CONSENT_PURPOSES: readonly StarterConsentPurpose[] = [
|
|
20
|
+
{
|
|
21
|
+
slug: 'contact',
|
|
22
|
+
label: 'Contact',
|
|
23
|
+
description: 'Being contacted by the workspace about our work together.',
|
|
24
|
+
defaultStatus: 'unknown',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
slug: 'marketing',
|
|
28
|
+
label: 'Marketing',
|
|
29
|
+
description: 'Marketing communications — newsletters, product updates, and campaigns.',
|
|
30
|
+
defaultStatus: 'unknown',
|
|
31
|
+
},
|
|
32
|
+
]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import type { McpToolRegistry } from '../../runtime/module.ts'
|
|
4
|
+
import { idArg, listWindowShape, registerCrudTools, termArg } from '../crudTools.ts'
|
|
5
|
+
import {
|
|
6
|
+
createBody,
|
|
7
|
+
consentPurposeResponse,
|
|
8
|
+
toCreateInput,
|
|
9
|
+
toUpdateInput,
|
|
10
|
+
updateBody,
|
|
11
|
+
} from './routes.ts'
|
|
12
|
+
import type { ConsentPurposesService } from './service.ts'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `consent_purposes_*`. Same schemas and mappers as `/v1/consent_purposes`, so
|
|
16
|
+
* the REST surface and the MCP one cannot drift. Agents list purposes before
|
|
17
|
+
* a person consent write so they know which slugs the workspace defines.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const listArgs = z.strictObject({
|
|
21
|
+
...listWindowShape,
|
|
22
|
+
q: termArg,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
export function registerConsentPurposesTools(
|
|
26
|
+
mcp: McpToolRegistry,
|
|
27
|
+
service: ConsentPurposesService,
|
|
28
|
+
): void {
|
|
29
|
+
registerCrudTools(mcp, {
|
|
30
|
+
resource: 'consent_purposes',
|
|
31
|
+
subject: 'consent purpose',
|
|
32
|
+
about:
|
|
33
|
+
'A workspace-defined consent purpose. Read these before writing a person ' +
|
|
34
|
+
'consent or setting a form/list/import purpose_id.',
|
|
35
|
+
service,
|
|
36
|
+
render: consentPurposeResponse,
|
|
37
|
+
listArgs,
|
|
38
|
+
toFilters: (args) => ({ term: args.q }),
|
|
39
|
+
createArgs: createBody,
|
|
40
|
+
toCreateInput,
|
|
41
|
+
updateArgs: updateBody.extend({ id: idArg }),
|
|
42
|
+
toUpdateInput,
|
|
43
|
+
})
|
|
44
|
+
}
|
package/src/modules/core.ts
CHANGED
|
@@ -6,10 +6,13 @@ import { createAgentTasksModule } from './agent-tasks/index.ts'
|
|
|
6
6
|
import { createApiKeysModule } from './api-keys/index.ts'
|
|
7
7
|
import { createAuthModule } from './auth/index.ts'
|
|
8
8
|
import { createCompaniesModule } from './companies/index.ts'
|
|
9
|
+
import { createConsentPurposesModule } from './consent-purposes/index.ts'
|
|
10
|
+
import { createCustomFieldsModule } from './custom-fields/index.ts'
|
|
9
11
|
import { createDashboardModule } from './dashboard/index.ts'
|
|
10
12
|
import { createDealsModule } from './deals/index.ts'
|
|
11
13
|
import { createDecisionsModule } from './decisions/index.ts'
|
|
12
14
|
import { createEmailDomainLinkerModule } from './email-domain-linker/index.ts'
|
|
15
|
+
import { createEnquiriesModule } from './enquiries/index.ts'
|
|
13
16
|
import { createFormsModule } from './forms/index.ts'
|
|
14
17
|
import { createHandbookModule } from './handbook/index.ts'
|
|
15
18
|
import { createHiringModule } from './hiring/index.ts'
|
|
@@ -47,6 +50,12 @@ export const coreModules: readonly KelpieModule[] = [
|
|
|
47
50
|
createAuthModule(coreMigrationsDirectory),
|
|
48
51
|
createWorkspaceModule(coreMigrationsDirectory),
|
|
49
52
|
createApiKeysModule(coreMigrationsDirectory),
|
|
53
|
+
// Structural. Registers before People, Forms, Lists, and Import-Export so
|
|
54
|
+
// its table is defined when their fks and per-person consent join reach it.
|
|
55
|
+
createConsentPurposesModule(coreMigrationsDirectory),
|
|
56
|
+
// Structural. Registers before the six object modules so the validator
|
|
57
|
+
// factory it exports is present when they inject it into their services.
|
|
58
|
+
createCustomFieldsModule(coreMigrationsDirectory),
|
|
50
59
|
createPeopleModule(coreMigrationsDirectory),
|
|
51
60
|
createCompaniesModule(coreMigrationsDirectory),
|
|
52
61
|
createPositionsModule(coreMigrationsDirectory),
|
|
@@ -54,6 +63,7 @@ export const coreModules: readonly KelpieModule[] = [
|
|
|
54
63
|
createNotesModule(coreMigrationsDirectory),
|
|
55
64
|
createPipelinesModule(coreMigrationsDirectory),
|
|
56
65
|
createDealsModule(coreMigrationsDirectory),
|
|
66
|
+
createEnquiriesModule(coreMigrationsDirectory),
|
|
57
67
|
createOpportunitiesModule(coreMigrationsDirectory),
|
|
58
68
|
createPartnershipsModule(coreMigrationsDirectory),
|
|
59
69
|
createRaisesModule(coreMigrationsDirectory),
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { LimitCapability } from '../../runtime/entitlements.ts'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How many custom-field definitions one workspace may have across every object
|
|
5
|
+
* type. Open source answers unlimited; the cloud can gate it later without a
|
|
6
|
+
* core change.
|
|
7
|
+
*
|
|
8
|
+
* The workspace-wide count is what an entitlement caps. A per-(workspace,
|
|
9
|
+
* object_type) ceiling is enforced separately in the service as a hard cap that
|
|
10
|
+
* protects the database from a runaway create loop.
|
|
11
|
+
*/
|
|
12
|
+
export const CUSTOM_FIELDS_LIMIT: LimitCapability = {
|
|
13
|
+
name: 'custom_fields.limit',
|
|
14
|
+
kind: 'limit',
|
|
15
|
+
description:
|
|
16
|
+
'How many custom-field definitions one workspace may have across every object type. Unlimited in open source.',
|
|
17
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
|
|
3
|
+
import type { ModuleEventCatalog } from '../../runtime/module.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Domain events published by the custom-fields module.
|
|
7
|
+
*
|
|
8
|
+
* `target` is the definition. The value-side changes ride each object module's
|
|
9
|
+
* own `.updated` event, with per-key entries in `changed` shaped as
|
|
10
|
+
* `customFields.<key>`. The webhooks bridge does not translate any of these —
|
|
11
|
+
* `custom_fields.field` is not in `RECORD_OBJECT_TYPES`, and there is no
|
|
12
|
+
* `record.*` wire event for a definition CRUD, so the four-event wire catalog
|
|
13
|
+
* stays unchanged.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const customFieldsEvents = {
|
|
17
|
+
'custom_fields.field.created': z.object({ objectType: z.string(), key: z.string() }),
|
|
18
|
+
'custom_fields.field.updated': z.object({
|
|
19
|
+
objectType: z.string(),
|
|
20
|
+
key: z.string(),
|
|
21
|
+
changed: z.array(z.string()).readonly(),
|
|
22
|
+
}),
|
|
23
|
+
'custom_fields.field.deleted': z.object({
|
|
24
|
+
objectType: z.string(),
|
|
25
|
+
key: z.string(),
|
|
26
|
+
strippedRecordCount: z.number().int(),
|
|
27
|
+
}),
|
|
28
|
+
} satisfies ModuleEventCatalog
|
|
29
|
+
|
|
30
|
+
export interface CustomFieldCreatedData {
|
|
31
|
+
readonly objectType: string
|
|
32
|
+
readonly key: string
|
|
33
|
+
}
|
|
34
|
+
export interface CustomFieldUpdatedData {
|
|
35
|
+
readonly objectType: string
|
|
36
|
+
readonly key: string
|
|
37
|
+
readonly changed: readonly string[]
|
|
38
|
+
}
|
|
39
|
+
export interface CustomFieldDeletedData {
|
|
40
|
+
readonly objectType: string
|
|
41
|
+
readonly key: string
|
|
42
|
+
readonly strippedRecordCount: number
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
declare module '../../runtime/events.ts' {
|
|
46
|
+
interface KelpieEventMap {
|
|
47
|
+
'custom_fields.field.created': CustomFieldCreatedData
|
|
48
|
+
'custom_fields.field.updated': CustomFieldUpdatedData
|
|
49
|
+
'custom_fields.field.deleted': CustomFieldDeletedData
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { KelpieModule } from '../../runtime/module.ts'
|
|
2
|
+
import { CUSTOM_FIELDS_LIMIT } from './capabilities.ts'
|
|
3
|
+
import { customFieldsEvents } from './events.ts'
|
|
4
|
+
import { mountCustomFieldsRoutes } from './routes.ts'
|
|
5
|
+
import * as schema from './schema.ts'
|
|
6
|
+
import { createCustomFieldDefinitionsService } from './service.ts'
|
|
7
|
+
import { registerCustomFieldsTools } from './tools.ts'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Custom fields: workspace-defined attributes for the six taggable record
|
|
11
|
+
* types. Structural because records carry values keyed by definition key, so a
|
|
12
|
+
* disabled module would leave the values on records with no way to read them.
|
|
13
|
+
*
|
|
14
|
+
* Requires the six object modules only for schema visibility: the strip-on-
|
|
15
|
+
* delete pass reads their tables through `stripKeyFromRecords`, and drizzle-kit
|
|
16
|
+
* needs the barrel to see them registered before this module's schema loads.
|
|
17
|
+
* Runtime dependency runs the other way — the six modules `requires` this one
|
|
18
|
+
* so the validator is present when they register.
|
|
19
|
+
*
|
|
20
|
+
* Exports the values factory so the six object modules can inject it into
|
|
21
|
+
* their services (`createCustomFieldValues` is the cross-module seam here).
|
|
22
|
+
*/
|
|
23
|
+
export {
|
|
24
|
+
createCustomFieldValues,
|
|
25
|
+
} from './values.ts'
|
|
26
|
+
export type {
|
|
27
|
+
CustomFieldValuesValidator,
|
|
28
|
+
CustomFieldsMerge,
|
|
29
|
+
StoredCustomFieldValue,
|
|
30
|
+
} from './values.ts'
|
|
31
|
+
|
|
32
|
+
export function createCustomFieldsModule(migrationsDirectory: string): KelpieModule {
|
|
33
|
+
return {
|
|
34
|
+
id: 'custom-fields',
|
|
35
|
+
requires: ['workspace'],
|
|
36
|
+
structural: true,
|
|
37
|
+
events: customFieldsEvents,
|
|
38
|
+
|
|
39
|
+
register(context) {
|
|
40
|
+
context.entitlements.declare(CUSTOM_FIELDS_LIMIT)
|
|
41
|
+
|
|
42
|
+
const service = createCustomFieldDefinitionsService({
|
|
43
|
+
db: context.db,
|
|
44
|
+
transaction: context.transaction,
|
|
45
|
+
createId: context.createId,
|
|
46
|
+
now: context.now,
|
|
47
|
+
entitlements: context.entitlements,
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
context.schema(schema, migrationsDirectory)
|
|
51
|
+
|
|
52
|
+
context.routes((router) => {
|
|
53
|
+
mountCustomFieldsRoutes(router, { db: context.db, now: context.now, service })
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
registerCustomFieldsTools(context.mcp, service)
|
|
57
|
+
|
|
58
|
+
return Promise.resolve()
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
}
|