@kelpie/server 0.12.0 → 0.14.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/app.d.ts +13 -0
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +8 -1
- package/dist/app.js.map +1 -1
- package/dist/boot.d.ts +9 -0
- package/dist/boot.d.ts.map +1 -1
- package/dist/boot.js +12 -2
- package/dist/boot.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/apiKeyScopes.d.ts.map +1 -1
- package/dist/lib/apiKeyScopes.js +6 -0
- package/dist/lib/apiKeyScopes.js.map +1 -1
- package/dist/lib/columns.d.ts +6 -0
- package/dist/lib/columns.d.ts.map +1 -1
- package/dist/lib/columns.js +5 -3
- package/dist/lib/columns.js.map +1 -1
- package/dist/lib/config.d.ts +17 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +3 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/egress.d.ts.map +1 -1
- package/dist/lib/egress.js +8 -4
- package/dist/lib/egress.js.map +1 -1
- package/dist/lib/errors.d.ts +3 -3
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +13 -5
- package/dist/lib/errors.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/lib/jobs.d.ts +110 -0
- package/dist/lib/jobs.d.ts.map +1 -0
- package/dist/lib/jobs.js +5 -0
- package/dist/lib/jobs.js.map +1 -0
- package/dist/lib/kelpieConfigFile.d.ts +15 -1
- package/dist/lib/kelpieConfigFile.d.ts.map +1 -1
- package/dist/lib/kelpieConfigFile.js +33 -1
- package/dist/lib/kelpieConfigFile.js.map +1 -1
- package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
- package/dist/modules/agent-tasks/catalog.js +32 -1
- package/dist/modules/agent-tasks/catalog.js.map +1 -1
- package/dist/modules/agent-tasks/index.d.ts.map +1 -1
- package/dist/modules/agent-tasks/index.js +1 -0
- package/dist/modules/agent-tasks/index.js.map +1 -1
- package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
- package/dist/modules/agent-tasks/resolve.js +5 -0
- 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 +22 -8
- package/dist/modules/attachedRecords.d.ts.map +1 -1
- package/dist/modules/attachedRecords.js +42 -5
- package/dist/modules/attachedRecords.js.map +1 -1
- package/dist/modules/auth/index.d.ts.map +1 -1
- package/dist/modules/auth/index.js +1 -0
- package/dist/modules/auth/index.js.map +1 -1
- package/dist/modules/auth/repository.d.ts +14 -0
- package/dist/modules/auth/repository.d.ts.map +1 -1
- package/dist/modules/auth/repository.js +20 -2
- package/dist/modules/auth/repository.js.map +1 -1
- package/dist/modules/auth/routes.d.ts.map +1 -1
- package/dist/modules/auth/routes.js +30 -0
- package/dist/modules/auth/routes.js.map +1 -1
- package/dist/modules/auth/service.d.ts +28 -0
- package/dist/modules/auth/service.d.ts.map +1 -1
- package/dist/modules/auth/service.js +72 -4
- package/dist/modules/auth/service.js.map +1 -1
- package/dist/modules/companies/repository.d.ts.map +1 -1
- package/dist/modules/companies/repository.js +1 -1
- package/dist/modules/companies/repository.js.map +1 -1
- package/dist/modules/companies/routes.d.ts +2 -4
- package/dist/modules/companies/routes.d.ts.map +1 -1
- package/dist/modules/companies/routes.js +6 -11
- package/dist/modules/companies/routes.js.map +1 -1
- package/dist/modules/companies/schema.d.ts +13 -28
- package/dist/modules/companies/schema.d.ts.map +1 -1
- package/dist/modules/companies/schema.js +2 -2
- package/dist/modules/companies/schema.js.map +1 -1
- package/dist/modules/companies/service.d.ts +2 -3
- package/dist/modules/companies/service.d.ts.map +1 -1
- package/dist/modules/companies/service.js +4 -7
- package/dist/modules/companies/service.js.map +1 -1
- package/dist/modules/core.d.ts.map +1 -1
- package/dist/modules/core.js +2 -0
- package/dist/modules/core.js.map +1 -1
- package/dist/modules/custom-fields/repository.d.ts.map +1 -1
- package/dist/modules/custom-fields/repository.js +2 -0
- package/dist/modules/custom-fields/repository.js.map +1 -1
- package/dist/modules/custom-fields/routes.d.ts +1 -0
- package/dist/modules/custom-fields/routes.d.ts.map +1 -1
- package/dist/modules/dashboard/index.d.ts.map +1 -1
- package/dist/modules/dashboard/index.js +1 -0
- package/dist/modules/dashboard/index.js.map +1 -1
- package/dist/modules/dashboard/repository.d.ts +13 -0
- package/dist/modules/dashboard/repository.d.ts.map +1 -1
- package/dist/modules/dashboard/repository.js +36 -0
- package/dist/modules/dashboard/repository.js.map +1 -1
- package/dist/modules/dashboard/routes.d.ts.map +1 -1
- package/dist/modules/dashboard/routes.js +13 -0
- package/dist/modules/dashboard/routes.js.map +1 -1
- package/dist/modules/dashboard/service.d.ts +11 -0
- package/dist/modules/dashboard/service.d.ts.map +1 -1
- package/dist/modules/dashboard/service.js +24 -1
- package/dist/modules/dashboard/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 +2 -0
- package/dist/modules/decisions/routes.d.ts.map +1 -1
- package/dist/modules/events/attendances.d.ts +35 -0
- package/dist/modules/events/attendances.d.ts.map +1 -0
- package/dist/modules/events/attendances.js +157 -0
- package/dist/modules/events/attendances.js.map +1 -0
- package/dist/modules/events/catalog.d.ts +35 -0
- package/dist/modules/events/catalog.d.ts.map +1 -0
- package/dist/modules/events/catalog.js +11 -0
- package/dist/modules/events/catalog.js.map +1 -0
- package/dist/modules/events/index.d.ts +10 -0
- package/dist/modules/events/index.d.ts.map +1 -0
- package/dist/modules/events/index.js +47 -0
- package/dist/modules/events/index.js.map +1 -0
- package/dist/modules/events/repository.d.ts +67 -0
- package/dist/modules/events/repository.d.ts.map +1 -0
- package/dist/modules/events/repository.js +212 -0
- package/dist/modules/events/repository.js.map +1 -0
- package/dist/modules/events/routes.d.ts +136 -0
- package/dist/modules/events/routes.d.ts.map +1 -0
- package/dist/modules/events/routes.js +280 -0
- package/dist/modules/events/routes.js.map +1 -0
- package/dist/modules/events/schema.d.ts +626 -0
- package/dist/modules/events/schema.d.ts.map +1 -0
- package/dist/modules/events/schema.js +93 -0
- package/dist/modules/events/schema.js.map +1 -0
- package/dist/modules/events/service.d.ts +68 -0
- package/dist/modules/events/service.d.ts.map +1 -0
- package/dist/modules/events/service.js +262 -0
- package/dist/modules/events/service.js.map +1 -0
- package/dist/modules/events/tools.d.ts +8 -0
- package/dist/modules/events/tools.d.ts.map +1 -0
- package/dist/modules/events/tools.js +80 -0
- package/dist/modules/events/tools.js.map +1 -0
- package/dist/modules/forms/applySubmissionFields.d.ts.map +1 -1
- package/dist/modules/forms/applySubmissionFields.js +7 -5
- package/dist/modules/forms/applySubmissionFields.js.map +1 -1
- package/dist/modules/forms/fillAddresses.d.ts +4 -0
- package/dist/modules/forms/fillAddresses.d.ts.map +1 -0
- package/dist/modules/forms/fillAddresses.js +93 -0
- package/dist/modules/forms/fillAddresses.js.map +1 -0
- package/dist/modules/forms/repository.d.ts +2 -2
- package/dist/modules/forms/repository.d.ts.map +1 -1
- package/dist/modules/forms/repository.js.map +1 -1
- package/dist/modules/forms/routes.d.ts +2 -0
- package/dist/modules/forms/routes.d.ts.map +1 -1
- package/dist/modules/forms/routes.js +2 -2
- package/dist/modules/forms/routes.js.map +1 -1
- package/dist/modules/forms/schema.js +2 -2
- package/dist/modules/forms/schema.js.map +1 -1
- package/dist/modules/forms/service.js +2 -2
- package/dist/modules/forms/service.js.map +1 -1
- package/dist/modules/forms/submission.d.ts +1 -0
- package/dist/modules/forms/submission.d.ts.map +1 -1
- package/dist/modules/forms/submission.js +27 -4
- package/dist/modules/forms/submission.js.map +1 -1
- package/dist/modules/hiring/roles.d.ts.map +1 -1
- package/dist/modules/hiring/roles.js +2 -1
- package/dist/modules/hiring/roles.js.map +1 -1
- package/dist/modules/import-export/addresses.d.ts +22 -0
- package/dist/modules/import-export/addresses.d.ts.map +1 -0
- package/dist/modules/import-export/addresses.js +83 -0
- package/dist/modules/import-export/addresses.js.map +1 -0
- package/dist/modules/import-export/drafts.d.ts +3 -4
- package/dist/modules/import-export/drafts.d.ts.map +1 -1
- package/dist/modules/import-export/drafts.js +4 -5
- package/dist/modules/import-export/drafts.js.map +1 -1
- package/dist/modules/import-export/exportRows.d.ts.map +1 -1
- package/dist/modules/import-export/exportRows.js +3 -3
- package/dist/modules/import-export/exportRows.js.map +1 -1
- package/dist/modules/import-export/plan.d.ts.map +1 -1
- package/dist/modules/import-export/plan.js +17 -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 +52 -7
- package/dist/modules/import-export/presets.js.map +1 -1
- package/dist/modules/import-export/repository.d.ts +3 -4
- package/dist/modules/import-export/repository.d.ts.map +1 -1
- package/dist/modules/import-export/repository.js +2 -3
- package/dist/modules/import-export/repository.js.map +1 -1
- package/dist/modules/import-export/writes.d.ts.map +1 -1
- package/dist/modules/import-export/writes.js +8 -4
- package/dist/modules/import-export/writes.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/notes/routes.d.ts +2 -0
- package/dist/modules/notes/routes.d.ts.map +1 -1
- package/dist/modules/people/repository.d.ts.map +1 -1
- package/dist/modules/people/repository.js +1 -1
- package/dist/modules/people/repository.js.map +1 -1
- package/dist/modules/people/routes.d.ts +2 -2
- package/dist/modules/people/routes.js +6 -6
- package/dist/modules/people/routes.js.map +1 -1
- package/dist/modules/people/schema.d.ts +17 -14
- package/dist/modules/people/schema.d.ts.map +1 -1
- package/dist/modules/people/schema.js +6 -4
- package/dist/modules/people/schema.js.map +1 -1
- package/dist/modules/people/service.d.ts +2 -2
- package/dist/modules/people/service.d.ts.map +1 -1
- package/dist/modules/people/service.js +5 -4
- package/dist/modules/people/service.js.map +1 -1
- package/dist/modules/plans/repository.d.ts +2 -2
- package/dist/modules/plans/repository.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/plans/routes.js +4 -4
- package/dist/modules/plans/routes.js.map +1 -1
- package/dist/modules/plans/schema.d.ts +2 -2
- package/dist/modules/plans/schema.d.ts.map +1 -1
- package/dist/modules/plans/schema.js +3 -3
- package/dist/modules/plans/schema.js.map +1 -1
- package/dist/modules/plans/service.d.ts +2 -2
- package/dist/modules/plans/service.d.ts.map +1 -1
- package/dist/modules/plans/service.js.map +1 -1
- package/dist/modules/plans/tools.js +2 -2
- package/dist/modules/plans/tools.js.map +1 -1
- package/dist/modules/recordTargets.d.ts.map +1 -1
- package/dist/modules/recordTargets.js +11 -0
- package/dist/modules/recordTargets.js.map +1 -1
- package/dist/modules/references.d.ts.map +1 -1
- package/dist/modules/references.js +2 -0
- package/dist/modules/references.js.map +1 -1
- package/dist/modules/sample-data/fixture.d.ts +26 -4
- package/dist/modules/sample-data/fixture.d.ts.map +1 -1
- package/dist/modules/sample-data/fixture.js +157 -23
- package/dist/modules/sample-data/fixture.js.map +1 -1
- package/dist/modules/sample-data/index.d.ts +5 -2
- package/dist/modules/sample-data/index.d.ts.map +1 -1
- package/dist/modules/sample-data/index.js +7 -2
- 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 +2 -0
- package/dist/modules/sample-data/routes.js.map +1 -1
- package/dist/modules/sample-data/service.d.ts +11 -3
- package/dist/modules/sample-data/service.d.ts.map +1 -1
- package/dist/modules/sample-data/service.js +452 -363
- package/dist/modules/sample-data/service.js.map +1 -1
- package/dist/modules/sample-data/tools.d.ts.map +1 -1
- package/dist/modules/sample-data/tools.js +4 -3
- package/dist/modules/sample-data/tools.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 +22 -0
- package/dist/modules/search/repository.js.map +1 -1
- package/dist/modules/search/service.d.ts +2 -2
- package/dist/modules/search/service.d.ts.map +1 -1
- package/dist/modules/search/service.js +4 -3
- package/dist/modules/search/service.js.map +1 -1
- package/dist/modules/smtp-email/index.d.ts +12 -4
- package/dist/modules/smtp-email/index.d.ts.map +1 -1
- package/dist/modules/smtp-email/index.js +25 -5
- package/dist/modules/smtp-email/index.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 +12 -0
- package/dist/modules/workspace/repository.js.map +1 -1
- package/dist/modules/workspace/routes.d.ts.map +1 -1
- package/dist/modules/workspace/routes.js +13 -0
- package/dist/modules/workspace/routes.js.map +1 -1
- package/dist/modules/workspace/service.d.ts +10 -0
- package/dist/modules/workspace/service.d.ts.map +1 -1
- package/dist/modules/workspace/service.js +34 -10
- package/dist/modules/workspace/service.js.map +1 -1
- package/dist/modules/workspace/starters.d.ts +17 -2
- package/dist/modules/workspace/starters.d.ts.map +1 -1
- package/dist/modules/workspace/starters.js +141 -14
- package/dist/modules/workspace/starters.js.map +1 -1
- package/dist/modules/workspace/workspaceAccessMiddleware.d.ts.map +1 -1
- package/dist/modules/workspace/workspaceAccessMiddleware.js +3 -4
- package/dist/modules/workspace/workspaceAccessMiddleware.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 +2 -0
- package/dist/runtime/events.js.map +1 -1
- package/dist/runtime/jobs.d.ts +63 -0
- package/dist/runtime/jobs.d.ts.map +1 -0
- package/dist/runtime/jobs.js +231 -0
- package/dist/runtime/jobs.js.map +1 -0
- package/dist/runtime/module.d.ts +20 -0
- package/dist/runtime/module.d.ts.map +1 -1
- package/dist/runtime/registry.d.ts +8 -0
- package/dist/runtime/registry.d.ts.map +1 -1
- package/dist/runtime/registry.js +117 -7
- package/dist/runtime/registry.js.map +1 -1
- package/dist/runtime/transaction.d.ts +19 -0
- package/dist/runtime/transaction.d.ts.map +1 -1
- package/dist/runtime/transaction.js +7 -0
- package/dist/runtime/transaction.js.map +1 -1
- package/dist/schema/index.d.ts +1 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/testing/app.d.ts +15 -0
- package/dist/testing/app.d.ts.map +1 -1
- package/dist/testing/app.js +7 -1
- package/dist/testing/app.js.map +1 -1
- package/dist/testing/client.d.ts.map +1 -1
- package/dist/testing/client.js +9 -1
- package/dist/testing/client.js.map +1 -1
- package/dist/testing/database.d.ts +7 -0
- package/dist/testing/database.d.ts.map +1 -1
- package/dist/testing/database.js +26 -2
- package/dist/testing/database.js.map +1 -1
- package/dist/testing/services.d.ts +7 -0
- package/dist/testing/services.d.ts.map +1 -1
- package/dist/testing/services.js +8 -1
- package/dist/testing/services.js.map +1 -1
- package/dist/worker.d.ts +15 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +19 -0
- package/dist/worker.js.map +1 -0
- package/migrations/0044_events.sql +79 -0
- package/migrations/0045_addresses.sql +66 -0
- package/migrations/0046_drop_company_website.sql +66 -0
- package/migrations/meta/_journal.json +21 -0
- package/package.json +4 -3
- package/src/app.ts +25 -1
- package/src/boot.ts +21 -2
- package/src/index.ts +17 -0
- package/src/lib/apiKeyScopes.ts +6 -0
- package/src/lib/columns.ts +12 -3
- package/src/lib/config.ts +21 -0
- package/src/lib/egress.ts +8 -4
- package/src/lib/errors.ts +16 -9
- package/src/lib/ids.ts +11 -0
- package/src/lib/jobs.ts +126 -0
- package/src/lib/kelpieConfigFile.ts +69 -1
- package/src/modules/agent-tasks/catalog.ts +33 -1
- package/src/modules/agent-tasks/index.ts +1 -0
- package/src/modules/agent-tasks/resolve.ts +11 -0
- package/src/modules/attachedRecords.ts +85 -13
- package/src/modules/auth/index.ts +1 -0
- package/src/modules/auth/repository.ts +34 -3
- package/src/modules/auth/routes.ts +44 -1
- package/src/modules/auth/service.ts +118 -4
- package/src/modules/companies/repository.ts +1 -0
- package/src/modules/companies/routes.ts +6 -11
- package/src/modules/companies/schema.ts +3 -3
- package/src/modules/companies/service.ts +6 -10
- package/src/modules/core.ts +2 -0
- package/src/modules/custom-fields/repository.ts +2 -0
- package/src/modules/dashboard/index.ts +1 -0
- package/src/modules/dashboard/repository.ts +64 -0
- package/src/modules/dashboard/routes.ts +15 -0
- package/src/modules/dashboard/service.ts +48 -0
- package/src/modules/decisions/repository.ts +2 -0
- package/src/modules/events/attendances.ts +245 -0
- package/src/modules/events/catalog.ts +36 -0
- package/src/modules/events/index.ts +54 -0
- package/src/modules/events/repository.ts +396 -0
- package/src/modules/events/routes.ts +405 -0
- package/src/modules/events/schema.ts +148 -0
- package/src/modules/events/service.ts +443 -0
- package/src/modules/events/tools.ts +118 -0
- package/src/modules/forms/applySubmissionFields.ts +7 -5
- package/src/modules/forms/fillAddresses.ts +185 -0
- package/src/modules/forms/repository.ts +3 -3
- package/src/modules/forms/routes.ts +2 -2
- package/src/modules/forms/schema.ts +2 -2
- package/src/modules/forms/service.ts +2 -2
- package/src/modules/forms/submission.ts +34 -4
- package/src/modules/hiring/roles.ts +2 -1
- package/src/modules/import-export/addresses.ts +150 -0
- package/src/modules/import-export/drafts.ts +7 -9
- package/src/modules/import-export/exportRows.ts +3 -3
- package/src/modules/import-export/plan.ts +30 -2
- package/src/modules/import-export/presets.ts +55 -7
- package/src/modules/import-export/repository.ts +5 -7
- package/src/modules/import-export/writes.ts +8 -4
- package/src/modules/people/repository.ts +1 -0
- package/src/modules/people/routes.ts +6 -6
- package/src/modules/people/schema.ts +7 -5
- package/src/modules/people/service.ts +7 -5
- package/src/modules/plans/repository.ts +2 -2
- package/src/modules/plans/routes.ts +6 -6
- package/src/modules/plans/schema.ts +4 -4
- package/src/modules/plans/service.ts +3 -3
- package/src/modules/plans/tools.ts +2 -2
- package/src/modules/recordTargets.ts +14 -0
- package/src/modules/references.ts +2 -0
- package/src/modules/sample-data/fixture.ts +208 -27
- package/src/modules/sample-data/index.ts +7 -2
- package/src/modules/sample-data/routes.ts +2 -0
- package/src/modules/sample-data/service.ts +166 -49
- package/src/modules/sample-data/tools.ts +4 -3
- package/src/modules/search/index.ts +2 -1
- package/src/modules/search/repository.ts +32 -1
- package/src/modules/search/service.ts +6 -4
- package/src/modules/smtp-email/index.ts +32 -10
- package/src/modules/workspace/repository.ts +18 -0
- package/src/modules/workspace/routes.ts +16 -0
- package/src/modules/workspace/service.ts +59 -14
- package/src/modules/workspace/starters.ts +275 -14
- package/src/modules/workspace/workspaceAccessMiddleware.ts +3 -4
- package/src/runtime/events.ts +2 -0
- package/src/runtime/jobs.ts +358 -0
- package/src/runtime/module.ts +20 -0
- package/src/runtime/registry.ts +146 -8
- package/src/runtime/transaction.ts +43 -0
- package/src/schema/index.ts +1 -0
- package/src/testing/app.ts +22 -1
- package/src/testing/client.ts +11 -1
- package/src/testing/database.ts +35 -2
- package/src/testing/services.ts +15 -1
- package/src/worker.ts +20 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COMPANY_ADDRESS_KINDS,
|
|
3
|
+
PERSON_ADDRESS_KINDS,
|
|
4
|
+
normaliseCountry,
|
|
5
|
+
} from '@kelpie/schemas'
|
|
6
|
+
import type { CompanyAddress, PersonAddress } from '@kelpie/schemas'
|
|
7
|
+
|
|
8
|
+
import { fillBlank } from './mapping.ts'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Compose one address from `*.address.*` form answers and fill-blank it onto
|
|
12
|
+
* the stored list. Default kind is mailing on a Person and hq on a Company.
|
|
13
|
+
* An existing address of that kind keeps any part it already has.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const ADDRESS_PART_FIELDS = ['line1', 'line2', 'city', 'region', 'postal_code', 'country'] as const
|
|
17
|
+
|
|
18
|
+
type AddressPartField = (typeof ADDRESS_PART_FIELDS)[number]
|
|
19
|
+
|
|
20
|
+
function readPart(
|
|
21
|
+
standard: Readonly<Record<string, string>>,
|
|
22
|
+
field: AddressPartField,
|
|
23
|
+
): string | undefined {
|
|
24
|
+
const raw = standard[`address.${field}`]
|
|
25
|
+
|
|
26
|
+
if (raw === undefined) {
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const trimmed = raw.trim()
|
|
31
|
+
|
|
32
|
+
return trimmed.length === 0 ? undefined : trimmed
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function hasAddressAnswers(standard: Readonly<Record<string, string>>): boolean {
|
|
36
|
+
if (standard['address.kind'] !== undefined && standard['address.kind'].trim().length > 0) {
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return ADDRESS_PART_FIELDS.some((field) => readPart(standard, field) !== undefined)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function resolveCountry(raw: string | undefined): string | null | undefined {
|
|
44
|
+
if (raw === undefined) {
|
|
45
|
+
return undefined
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return normaliseCountry(raw)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function fillPart(stored: string | null, inbound: string | undefined): string | null {
|
|
52
|
+
const filled = fillBlank(stored, inbound)
|
|
53
|
+
|
|
54
|
+
return filled === undefined ? stored : filled
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function mergeAddress<Kind extends string>(
|
|
58
|
+
stored: { readonly line1: string | null; readonly line2: string | null; readonly city: string | null; readonly region: string | null; readonly postalCode: string | null; readonly country: string | null } | undefined,
|
|
59
|
+
inbound: {
|
|
60
|
+
readonly line1: string | undefined
|
|
61
|
+
readonly line2: string | undefined
|
|
62
|
+
readonly city: string | undefined
|
|
63
|
+
readonly region: string | undefined
|
|
64
|
+
readonly postalCode: string | undefined
|
|
65
|
+
readonly country: string | null | undefined
|
|
66
|
+
},
|
|
67
|
+
kind: Kind,
|
|
68
|
+
primary: boolean,
|
|
69
|
+
): {
|
|
70
|
+
readonly kind: Kind
|
|
71
|
+
readonly line1: string | null
|
|
72
|
+
readonly line2: string | null
|
|
73
|
+
readonly city: string | null
|
|
74
|
+
readonly region: string | null
|
|
75
|
+
readonly postalCode: string | null
|
|
76
|
+
readonly country: string | null
|
|
77
|
+
readonly primary: boolean
|
|
78
|
+
} {
|
|
79
|
+
const empty = {
|
|
80
|
+
line1: null,
|
|
81
|
+
line2: null,
|
|
82
|
+
city: null,
|
|
83
|
+
region: null,
|
|
84
|
+
postalCode: null,
|
|
85
|
+
country: null,
|
|
86
|
+
}
|
|
87
|
+
const base = stored ?? empty
|
|
88
|
+
|
|
89
|
+
return {
|
|
90
|
+
kind,
|
|
91
|
+
line1: fillPart(base.line1, inbound.line1),
|
|
92
|
+
line2: fillPart(base.line2, inbound.line2),
|
|
93
|
+
city: fillPart(base.city, inbound.city),
|
|
94
|
+
region: fillPart(base.region, inbound.region),
|
|
95
|
+
postalCode: fillPart(base.postalCode, inbound.postalCode),
|
|
96
|
+
country: inbound.country === undefined ? base.country : fillPart(base.country, inbound.country ?? undefined),
|
|
97
|
+
primary,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function hasLocation(address: {
|
|
102
|
+
readonly line1: string | null
|
|
103
|
+
readonly line2: string | null
|
|
104
|
+
readonly city: string | null
|
|
105
|
+
readonly region: string | null
|
|
106
|
+
readonly postalCode: string | null
|
|
107
|
+
readonly country: string | null
|
|
108
|
+
}): boolean {
|
|
109
|
+
return (
|
|
110
|
+
address.line1 !== null ||
|
|
111
|
+
address.line2 !== null ||
|
|
112
|
+
address.city !== null ||
|
|
113
|
+
address.region !== null ||
|
|
114
|
+
address.postalCode !== null ||
|
|
115
|
+
address.country !== null
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function fillTypedAddress<Kind extends string>(
|
|
120
|
+
stored: readonly {
|
|
121
|
+
readonly kind: Kind
|
|
122
|
+
readonly line1: string | null
|
|
123
|
+
readonly line2: string | null
|
|
124
|
+
readonly city: string | null
|
|
125
|
+
readonly region: string | null
|
|
126
|
+
readonly postalCode: string | null
|
|
127
|
+
readonly country: string | null
|
|
128
|
+
readonly primary: boolean
|
|
129
|
+
}[],
|
|
130
|
+
standard: Readonly<Record<string, string>>,
|
|
131
|
+
kinds: readonly Kind[],
|
|
132
|
+
defaultKind: Kind,
|
|
133
|
+
): readonly {
|
|
134
|
+
readonly kind: Kind
|
|
135
|
+
readonly line1: string | null
|
|
136
|
+
readonly line2: string | null
|
|
137
|
+
readonly city: string | null
|
|
138
|
+
readonly region: string | null
|
|
139
|
+
readonly postalCode: string | null
|
|
140
|
+
readonly country: string | null
|
|
141
|
+
readonly primary: boolean
|
|
142
|
+
}[] | undefined {
|
|
143
|
+
if (!hasAddressAnswers(standard)) {
|
|
144
|
+
return undefined
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const requested = (standard['address.kind'] ?? '').trim()
|
|
148
|
+
const kind = kinds.includes(requested as Kind) ? (requested as Kind) : defaultKind
|
|
149
|
+
const inbound = {
|
|
150
|
+
line1: readPart(standard, 'line1'),
|
|
151
|
+
line2: readPart(standard, 'line2'),
|
|
152
|
+
city: readPart(standard, 'city'),
|
|
153
|
+
region: readPart(standard, 'region'),
|
|
154
|
+
postalCode: readPart(standard, 'postal_code'),
|
|
155
|
+
country: resolveCountry(readPart(standard, 'country')),
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const existing = stored.find((address) => address.kind === kind)
|
|
159
|
+
const merged = mergeAddress(existing, inbound, kind, existing?.primary ?? stored.length === 0)
|
|
160
|
+
|
|
161
|
+
if (!hasLocation(merged)) {
|
|
162
|
+
return undefined
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (existing === undefined) {
|
|
166
|
+
const next = stored.map((address) => (merged.primary ? { ...address, primary: false } : address))
|
|
167
|
+
return [...next, merged]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return stored.map((address) => (address.kind === kind ? merged : address))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function fillPersonAddresses(
|
|
174
|
+
stored: readonly PersonAddress[],
|
|
175
|
+
standard: Readonly<Record<string, string>>,
|
|
176
|
+
): readonly PersonAddress[] | undefined {
|
|
177
|
+
return fillTypedAddress(stored, standard, PERSON_ADDRESS_KINDS, 'mailing')
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function fillCompanyAddresses(
|
|
181
|
+
stored: readonly CompanyAddress[],
|
|
182
|
+
standard: Readonly<Record<string, string>>,
|
|
183
|
+
): readonly CompanyAddress[] | undefined {
|
|
184
|
+
return fillTypedAddress(stored, standard, COMPANY_ADDRESS_KINDS, 'hq')
|
|
185
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { and, asc, eq, ilike, inArray, or } from 'drizzle-orm'
|
|
2
2
|
import type { SQL } from 'drizzle-orm'
|
|
3
3
|
import type { AnyPgColumn } from 'drizzle-orm/pg-core'
|
|
4
|
-
import type { FormSubmissionLinkTarget,
|
|
4
|
+
import type { FormSubmissionLinkTarget, FormAttachTargetType } from '@kelpie/schemas'
|
|
5
5
|
|
|
6
6
|
import { keysetCondition, orderByWindow, textSort, timestampSort } from '../../lib/pagination.ts'
|
|
7
7
|
import type { ListWindow, SortableFields } from '../../lib/pagination.ts'
|
|
@@ -332,7 +332,7 @@ export async function replaceFormLists(
|
|
|
332
332
|
|
|
333
333
|
/** One form's configured attach targets, ordered so a resent identical set is not a write. */
|
|
334
334
|
export interface FormAttachTargetRow {
|
|
335
|
-
readonly targetType:
|
|
335
|
+
readonly targetType: FormAttachTargetType
|
|
336
336
|
readonly targetId: string
|
|
337
337
|
}
|
|
338
338
|
|
|
@@ -347,7 +347,7 @@ export async function listAttachTargets(
|
|
|
347
347
|
.orderBy(asc(formAttachTargets.targetType), asc(formAttachTargets.targetId))
|
|
348
348
|
|
|
349
349
|
return rows.map((row) => ({
|
|
350
|
-
targetType: row.targetType as
|
|
350
|
+
targetType: row.targetType as FormAttachTargetType,
|
|
351
351
|
targetId: row.targetId,
|
|
352
352
|
}))
|
|
353
353
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context, Hono } from 'hono'
|
|
2
2
|
import { z } from 'zod'
|
|
3
|
-
import {
|
|
3
|
+
import { FORM_ATTACH_TARGET_TYPES, FORM_SUBMISSION_LINK_TARGETS } from '@kelpie/schemas'
|
|
4
4
|
import type { FormAttachTarget, FormSubmissionLinkTarget } from '@kelpie/schemas'
|
|
5
5
|
|
|
6
6
|
import { AppError } from '../../lib/errors.ts'
|
|
@@ -59,7 +59,7 @@ const fieldBody = z.strictObject({
|
|
|
59
59
|
})
|
|
60
60
|
|
|
61
61
|
const attachTargetBody = z.strictObject({
|
|
62
|
-
target_type: z.enum(
|
|
62
|
+
target_type: z.enum(FORM_ATTACH_TARGET_TYPES),
|
|
63
63
|
target_id: z.string().min(1),
|
|
64
64
|
})
|
|
65
65
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
FORM_ATTACH_TARGET_TYPES,
|
|
2
3
|
FORM_FIELD_TYPES,
|
|
3
4
|
FORM_STATUSES,
|
|
4
|
-
PIPELINE_KINDS,
|
|
5
5
|
} from '@kelpie/schemas'
|
|
6
6
|
import type { FormOptionValueType, FormSubmissionActionEntry } from '@kelpie/schemas'
|
|
7
7
|
import { boolean, index, integer, jsonb, pgTable, primaryKey, text } from 'drizzle-orm/pg-core'
|
|
@@ -187,7 +187,7 @@ export const formAttachTargets = pgTable(
|
|
|
187
187
|
table.targetType,
|
|
188
188
|
table.targetId,
|
|
189
189
|
),
|
|
190
|
-
checkOneOf('form_attach_targets_target_type_check', table.targetType,
|
|
190
|
+
checkOneOf('form_attach_targets_target_type_check', table.targetType, FORM_ATTACH_TARGET_TYPES),
|
|
191
191
|
],
|
|
192
192
|
)
|
|
193
193
|
|
|
@@ -4,7 +4,7 @@ import type {
|
|
|
4
4
|
FormSubmissionLinkTarget,
|
|
5
5
|
PipelineKind,
|
|
6
6
|
} from '@kelpie/schemas'
|
|
7
|
-
import {
|
|
7
|
+
import { FORM_ATTACH_TARGET_TYPES } from '@kelpie/schemas'
|
|
8
8
|
|
|
9
9
|
import { changedKeys } from '../../lib/changes.ts'
|
|
10
10
|
import type { Database } from '../../lib/database.ts'
|
|
@@ -422,7 +422,7 @@ export function createFormsService(dependencies: FormsDependencies): FormsServic
|
|
|
422
422
|
|
|
423
423
|
const problems: { field: string; message: string }[] = []
|
|
424
424
|
|
|
425
|
-
for (const kind of
|
|
425
|
+
for (const kind of FORM_ATTACH_TARGET_TYPES) {
|
|
426
426
|
const ofKind = targets.filter((target) => target.targetType === kind)
|
|
427
427
|
|
|
428
428
|
if (ofKind.length === 0) {
|
|
@@ -17,6 +17,8 @@ import * as dealRepository from '../deals/repository.ts'
|
|
|
17
17
|
import '../deals/events.ts'
|
|
18
18
|
import * as enquiryRepository from '../enquiries/repository.ts'
|
|
19
19
|
import '../enquiries/events.ts'
|
|
20
|
+
import '../events/catalog.ts'
|
|
21
|
+
import * as eventRepository from '../events/repository.ts'
|
|
20
22
|
import '../lists/events.ts'
|
|
21
23
|
import * as listsRepository from '../lists/repository.ts'
|
|
22
24
|
import * as opportunityRepository from '../opportunities/repository.ts'
|
|
@@ -1196,18 +1198,46 @@ export function createFormSubmitService(dependencies: SubmissionDependencies): F
|
|
|
1196
1198
|
events,
|
|
1197
1199
|
actionLog,
|
|
1198
1200
|
`attach:${target.targetType}:${target.targetId}`,
|
|
1199
|
-
async (inner) => {
|
|
1201
|
+
async (inner, emit) => {
|
|
1202
|
+
const targetType = target.targetType
|
|
1203
|
+
const targetId = target.targetId
|
|
1204
|
+
|
|
1200
1205
|
// Racing a target delete would fail the FK-less insert with the
|
|
1201
1206
|
// same effect as an existence check: log an error, continue.
|
|
1202
|
-
if (!(await targetExists(inner, workspaceId,
|
|
1203
|
-
throw AppError.notFound(`${
|
|
1207
|
+
if (!(await targetExists(inner, workspaceId, targetType, targetId))) {
|
|
1208
|
+
throw AppError.notFound(`${targetType} ${targetId} not found`)
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
if (targetType === 'event') {
|
|
1212
|
+
const { record, inserted } = await eventRepository.insertAttendanceIfAbsent(
|
|
1213
|
+
inner,
|
|
1214
|
+
{
|
|
1215
|
+
id: dependencies.createId('attendance'),
|
|
1216
|
+
workspaceId,
|
|
1217
|
+
eventId: targetId,
|
|
1218
|
+
personId: person.record.id,
|
|
1219
|
+
status: 'registered',
|
|
1220
|
+
source: 'form',
|
|
1221
|
+
createdAt: now,
|
|
1222
|
+
updatedAt: now,
|
|
1223
|
+
},
|
|
1224
|
+
)
|
|
1225
|
+
|
|
1226
|
+
if (inserted) {
|
|
1227
|
+
emit('events.attendance.created', { type: 'attendance', id: record.id }, {})
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
return {
|
|
1231
|
+
status: 'ok',
|
|
1232
|
+
detail: inserted ? 'registered' : 'already registered',
|
|
1233
|
+
}
|
|
1204
1234
|
}
|
|
1205
1235
|
|
|
1206
1236
|
const inserted = await personLinks.linkPersonIfAbsent(
|
|
1207
1237
|
inner,
|
|
1208
1238
|
dependencies.createId,
|
|
1209
1239
|
workspaceId,
|
|
1210
|
-
|
|
1240
|
+
{ targetType, targetId },
|
|
1211
1241
|
person.record.id,
|
|
1212
1242
|
)
|
|
1213
1243
|
|
|
@@ -13,7 +13,7 @@ import { toEventActor } from '../../lib/actor.ts'
|
|
|
13
13
|
import type { Actor } from '../auth/actor.ts'
|
|
14
14
|
import { requireWorkspaceId } from '../auth/actor.ts'
|
|
15
15
|
import './events.ts'
|
|
16
|
-
import { deleteRecordsAttachedTo } from '../attachedRecords.ts'
|
|
16
|
+
import { deleteEventAssociationsForTarget, deleteRecordsAttachedTo } from '../attachedRecords.ts'
|
|
17
17
|
import * as repository from './repository.ts'
|
|
18
18
|
import { DEFAULT_ROLE_SORT, ROLE_SORTS } from './repository.ts'
|
|
19
19
|
import type { RoleFilters, RoleRecord } from './repository.ts'
|
|
@@ -162,6 +162,7 @@ export function createRolesService(dependencies: RolesDependencies): RolesServic
|
|
|
162
162
|
})
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
await deleteEventAssociationsForTarget(tx, workspaceId, 'role', id)
|
|
165
166
|
await repository.deleteRole(tx, workspaceId, id)
|
|
166
167
|
|
|
167
168
|
events.emit('hiring.role.deleted', { type: 'role', id }, {})
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ADDRESS_PARTS,
|
|
3
|
+
addressColumnKey,
|
|
4
|
+
COMPANY_ADDRESS_KINDS,
|
|
5
|
+
PERSON_ADDRESS_KINDS,
|
|
6
|
+
} from '@kelpie/schemas'
|
|
7
|
+
import type {
|
|
8
|
+
AddressPart,
|
|
9
|
+
CompanyAddress,
|
|
10
|
+
CompanyAddressKind,
|
|
11
|
+
PersonAddress,
|
|
12
|
+
PersonAddressKind,
|
|
13
|
+
PostalAddress,
|
|
14
|
+
} from '@kelpie/schemas'
|
|
15
|
+
import { normaliseCountry } from '@kelpie/schemas'
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Flattened CSV address columns → jsonb addresses, and the reverse for export.
|
|
19
|
+
*
|
|
20
|
+
* One group per kind. A group with any non-empty part becomes an address of
|
|
21
|
+
* that kind. The first non-empty kind in the object's kind order is primary.
|
|
22
|
+
* An unknown country is a warning and leaves `country` null rather than
|
|
23
|
+
* failing the row.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export interface AddressImportWarning {
|
|
27
|
+
readonly field: string
|
|
28
|
+
readonly message: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface AddressImportResult<Kind extends string> {
|
|
32
|
+
readonly addresses: readonly PostalAddress<Kind>[] | undefined
|
|
33
|
+
readonly warnings: readonly AddressImportWarning[]
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const CAMEL_PART: Readonly<Record<AddressPart, 'line1' | 'line2' | 'city' | 'region' | 'postalCode' | 'country'>> =
|
|
37
|
+
{
|
|
38
|
+
line1: 'line1',
|
|
39
|
+
line2: 'line2',
|
|
40
|
+
city: 'city',
|
|
41
|
+
region: 'region',
|
|
42
|
+
postal_code: 'postalCode',
|
|
43
|
+
country: 'country',
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function cell(mapped: Readonly<Record<string, string>>, key: string): string | undefined {
|
|
47
|
+
const value = (mapped[key] ?? '').trim()
|
|
48
|
+
|
|
49
|
+
return value.length === 0 ? undefined : value
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function addressesFromMapped<Kind extends string>(
|
|
53
|
+
mapped: Readonly<Record<string, string>>,
|
|
54
|
+
kinds: readonly Kind[],
|
|
55
|
+
): AddressImportResult<Kind> {
|
|
56
|
+
const warnings: AddressImportWarning[] = []
|
|
57
|
+
const addresses: PostalAddress<Kind>[] = []
|
|
58
|
+
|
|
59
|
+
for (const kind of kinds) {
|
|
60
|
+
const parts: {
|
|
61
|
+
line1: string | null
|
|
62
|
+
line2: string | null
|
|
63
|
+
city: string | null
|
|
64
|
+
region: string | null
|
|
65
|
+
postalCode: string | null
|
|
66
|
+
country: string | null
|
|
67
|
+
} = {
|
|
68
|
+
line1: cell(mapped, addressColumnKey(kind, 'line1')) ?? null,
|
|
69
|
+
line2: cell(mapped, addressColumnKey(kind, 'line2')) ?? null,
|
|
70
|
+
city: cell(mapped, addressColumnKey(kind, 'city')) ?? null,
|
|
71
|
+
region: cell(mapped, addressColumnKey(kind, 'region')) ?? null,
|
|
72
|
+
postalCode: cell(mapped, addressColumnKey(kind, 'postal_code')) ?? null,
|
|
73
|
+
country: null,
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const countryRaw = cell(mapped, addressColumnKey(kind, 'country'))
|
|
77
|
+
|
|
78
|
+
if (countryRaw !== undefined) {
|
|
79
|
+
const code = normaliseCountry(countryRaw)
|
|
80
|
+
|
|
81
|
+
if (code === null) {
|
|
82
|
+
warnings.push({
|
|
83
|
+
field: addressColumnKey(kind, 'country'),
|
|
84
|
+
message: `"${countryRaw}" is not a country Kelpie knows. Country left blank`,
|
|
85
|
+
})
|
|
86
|
+
} else {
|
|
87
|
+
parts.country = code
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const hasPart = Object.values(parts).some((value) => value !== null)
|
|
92
|
+
|
|
93
|
+
if (!hasPart) {
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
addresses.push({
|
|
98
|
+
kind,
|
|
99
|
+
...parts,
|
|
100
|
+
primary: false,
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (addresses.length === 0) {
|
|
105
|
+
return { addresses: undefined, warnings }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
addresses: addresses.map((address, index) => ({ ...address, primary: index === 0 })),
|
|
110
|
+
warnings,
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function personAddressesFromMapped(
|
|
115
|
+
mapped: Readonly<Record<string, string>>,
|
|
116
|
+
): AddressImportResult<PersonAddressKind> {
|
|
117
|
+
return addressesFromMapped(mapped, PERSON_ADDRESS_KINDS)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function companyAddressesFromMapped(
|
|
121
|
+
mapped: Readonly<Record<string, string>>,
|
|
122
|
+
): AddressImportResult<CompanyAddressKind> {
|
|
123
|
+
return addressesFromMapped(mapped, COMPANY_ADDRESS_KINDS)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function partValue(address: PostalAddress | undefined, part: AddressPart): string {
|
|
127
|
+
if (address === undefined) {
|
|
128
|
+
return ''
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const value = address[CAMEL_PART[part]]
|
|
132
|
+
|
|
133
|
+
return value ?? ''
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function personAddressCells(addresses: readonly PersonAddress[]): readonly string[] {
|
|
137
|
+
return PERSON_ADDRESS_KINDS.flatMap((kind) => {
|
|
138
|
+
const address = addresses.find((entry) => entry.kind === kind)
|
|
139
|
+
|
|
140
|
+
return ADDRESS_PARTS.map((part) => partValue(address, part))
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function companyAddressCells(addresses: readonly CompanyAddress[]): readonly string[] {
|
|
145
|
+
return COMPANY_ADDRESS_KINDS.flatMap((kind) => {
|
|
146
|
+
const address = addresses.find((entry) => entry.kind === kind)
|
|
147
|
+
|
|
148
|
+
return ADDRESS_PARTS.map((part) => partValue(address, part))
|
|
149
|
+
})
|
|
150
|
+
}
|
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
composeName,
|
|
10
10
|
} from '@kelpie/schemas'
|
|
11
11
|
|
|
12
|
-
import type { CustomFieldWireValue } from '@kelpie/schemas'
|
|
12
|
+
import type { CompanyAddress, CustomFieldWireValue, PersonAddress } from '@kelpie/schemas'
|
|
13
13
|
|
|
14
14
|
import { normaliseDomain, normaliseEmail } from '../../lib/normalisation.ts'
|
|
15
|
+
import { companyAddressesFromMapped, personAddressesFromMapped } from './addresses.ts'
|
|
15
16
|
import { moneyToCents, splitList } from './mapping.ts'
|
|
16
17
|
import { canonicalEnum } from './validation.ts'
|
|
17
18
|
|
|
@@ -36,8 +37,7 @@ export interface CompanyDraft {
|
|
|
36
37
|
readonly description?: string
|
|
37
38
|
readonly stage?: string
|
|
38
39
|
readonly sizeBand?: string
|
|
39
|
-
readonly
|
|
40
|
-
readonly website?: string
|
|
40
|
+
readonly addresses?: readonly CompanyAddress[]
|
|
41
41
|
readonly accountType?: string
|
|
42
42
|
readonly icpFit?: string
|
|
43
43
|
readonly summary?: string
|
|
@@ -54,7 +54,7 @@ export interface PersonDraft {
|
|
|
54
54
|
readonly email?: string
|
|
55
55
|
readonly phones?: readonly string[]
|
|
56
56
|
readonly timezone?: string
|
|
57
|
-
readonly
|
|
57
|
+
readonly addresses?: readonly PersonAddress[]
|
|
58
58
|
readonly preferredChannel?: string
|
|
59
59
|
readonly influence?: string
|
|
60
60
|
readonly relationship?: string
|
|
@@ -211,8 +211,7 @@ export function companyDraft(
|
|
|
211
211
|
description: text(mapped, 'description'),
|
|
212
212
|
stage: enumeration(mapped, 'stage', COMPANY_STAGES),
|
|
213
213
|
sizeBand: enumeration(mapped, 'size_band', SIZE_BANDS),
|
|
214
|
-
|
|
215
|
-
website: text(mapped, 'website'),
|
|
214
|
+
addresses: companyAddressesFromMapped(mapped).addresses,
|
|
216
215
|
accountType: enumeration(mapped, 'account_type', ACCOUNT_TYPES),
|
|
217
216
|
icpFit: enumeration(mapped, 'icp_fit', ICP_FITS),
|
|
218
217
|
summary: text(mapped, 'summary'),
|
|
@@ -246,7 +245,7 @@ export function personDraft(
|
|
|
246
245
|
email: email === undefined ? undefined : (normaliseEmail(email) ?? undefined),
|
|
247
246
|
phones: list(mapped, 'phones'),
|
|
248
247
|
timezone: text(mapped, 'timezone'),
|
|
249
|
-
|
|
248
|
+
addresses: personAddressesFromMapped(mapped).addresses,
|
|
250
249
|
preferredChannel: enumeration(mapped, 'preferred_channel', PREFERRED_CHANNELS),
|
|
251
250
|
influence: enumeration(mapped, 'influence', INFLUENCE_LEVELS),
|
|
252
251
|
relationship: enumeration(mapped, 'relationship', RELATIONSHIP_LEVELS),
|
|
@@ -274,8 +273,7 @@ export function affiliationCompanyDraft(mapped: Readonly<Record<string, string>>
|
|
|
274
273
|
description: undefined,
|
|
275
274
|
stage: undefined,
|
|
276
275
|
sizeBand: undefined,
|
|
277
|
-
|
|
278
|
-
website: undefined,
|
|
276
|
+
addresses: undefined,
|
|
279
277
|
accountType: undefined,
|
|
280
278
|
icpFit: undefined,
|
|
281
279
|
summary: undefined,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OBJECT_COLUMNS, customFieldObjectTypeForExport } from '@kelpie/schemas'
|
|
2
2
|
import type { CsvColumn, CustomFieldValue, ExportObject } from '@kelpie/schemas'
|
|
3
3
|
|
|
4
|
+
import { companyAddressCells, personAddressCells } from './addresses.ts'
|
|
4
5
|
import type { CustomFieldDefinitionRecord } from '../custom-fields/repository.ts'
|
|
5
6
|
import { customFieldCells, customFieldDefinitionCells, customFieldHeaderKeys } from './customFieldCsv.ts'
|
|
6
7
|
import { centsToMoney } from './mapping.ts'
|
|
@@ -101,8 +102,7 @@ export function companyCells(
|
|
|
101
102
|
row.description,
|
|
102
103
|
row.summary,
|
|
103
104
|
joinList(row.tags),
|
|
104
|
-
row.
|
|
105
|
-
row.hq ?? '',
|
|
105
|
+
...companyAddressCells(row.addresses),
|
|
106
106
|
],
|
|
107
107
|
row.customFields,
|
|
108
108
|
definitions,
|
|
@@ -122,7 +122,7 @@ export function personCells(
|
|
|
122
122
|
row.suffix ?? '',
|
|
123
123
|
row.email ?? '',
|
|
124
124
|
row.timezone ?? '',
|
|
125
|
-
row.
|
|
125
|
+
...personAddressCells(row.addresses),
|
|
126
126
|
row.preferredChannel,
|
|
127
127
|
row.influence,
|
|
128
128
|
row.relationship,
|
|
@@ -11,6 +11,7 @@ import { pipelineKindForImport } from '@kelpie/schemas'
|
|
|
11
11
|
|
|
12
12
|
import { normaliseDomain, normaliseEmail } from '../../lib/normalisation.ts'
|
|
13
13
|
import type { CustomFieldDefinitionRecord } from '../custom-fields/repository.ts'
|
|
14
|
+
import { companyAddressesFromMapped, personAddressesFromMapped } from './addresses.ts'
|
|
14
15
|
import {
|
|
15
16
|
customFieldWireValues,
|
|
16
17
|
extractCustomFieldRaw,
|
|
@@ -628,6 +629,29 @@ function withAffiliation(
|
|
|
628
629
|
return { ...plan, write, ...(warnings.length > 0 ? { warnings } : {}) }
|
|
629
630
|
}
|
|
630
631
|
|
|
632
|
+
function withAddressWarnings(
|
|
633
|
+
context: PlanContext,
|
|
634
|
+
mapped: Readonly<Record<string, string>>,
|
|
635
|
+
plan: RowPlan,
|
|
636
|
+
): RowPlan {
|
|
637
|
+
if (plan.action !== 'create' && plan.action !== 'update') {
|
|
638
|
+
return plan
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const extra =
|
|
642
|
+
context.object === 'people'
|
|
643
|
+
? personAddressesFromMapped(mapped).warnings
|
|
644
|
+
: context.object === 'companies'
|
|
645
|
+
? companyAddressesFromMapped(mapped).warnings
|
|
646
|
+
: []
|
|
647
|
+
|
|
648
|
+
if (extra.length === 0) {
|
|
649
|
+
return plan
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
return { ...plan, warnings: [...(plan.warnings ?? []), ...extra] }
|
|
653
|
+
}
|
|
654
|
+
|
|
631
655
|
/**
|
|
632
656
|
* @param mapped The row's cells by Kelpie column, from `mapRow`.
|
|
633
657
|
* @returns What this row would do. `create` when its key matches nothing;
|
|
@@ -663,7 +687,7 @@ export function planRow(context: PlanContext, mapped: Readonly<Record<string, st
|
|
|
663
687
|
const targetId = context.lookups.existing.get(key)
|
|
664
688
|
|
|
665
689
|
if (targetId === undefined) {
|
|
666
|
-
return withAffiliation(context, mapped, { action: 'create', key, write })
|
|
690
|
+
return withAddressWarnings(context, mapped, withAffiliation(context, mapped, { action: 'create', key, write }))
|
|
667
691
|
}
|
|
668
692
|
|
|
669
693
|
// An empty string is the placeholder an in-file match carries: the record it
|
|
@@ -674,7 +698,11 @@ export function planRow(context: PlanContext, mapped: Readonly<Record<string, st
|
|
|
674
698
|
// wants an existing person's position updated runs the job in `update` mode,
|
|
675
699
|
// which is where the rename-in-place lives.
|
|
676
700
|
return context.conflictMode === 'update'
|
|
677
|
-
?
|
|
701
|
+
? withAddressWarnings(
|
|
702
|
+
context,
|
|
703
|
+
mapped,
|
|
704
|
+
withAffiliation(context, mapped, { action: 'update', key, targetId: resolved, write }),
|
|
705
|
+
)
|
|
678
706
|
: { action: 'skip', key, targetId: resolved }
|
|
679
707
|
}
|
|
680
708
|
|