@kelpie/server 0.1.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/LICENSE +661 -0
- package/README.md +57 -0
- package/dist/app.d.ts +36 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +98 -0
- package/dist/app.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/actor.d.ts +71 -0
- package/dist/lib/actor.d.ts.map +1 -0
- package/dist/lib/actor.js +48 -0
- package/dist/lib/actor.js.map +1 -0
- package/dist/lib/changes.d.ts +17 -0
- package/dist/lib/changes.d.ts.map +1 -0
- package/dist/lib/changes.js +35 -0
- package/dist/lib/changes.js.map +1 -0
- package/dist/lib/columns.d.ts +152 -0
- package/dist/lib/columns.d.ts.map +1 -0
- package/dist/lib/columns.js +126 -0
- package/dist/lib/columns.js.map +1 -0
- package/dist/lib/config.d.ts +36 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +52 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/database.d.ts +57 -0
- package/dist/lib/database.d.ts.map +1 -0
- package/dist/lib/database.js +91 -0
- package/dist/lib/database.js.map +1 -0
- package/dist/lib/dates.d.ts +11 -0
- package/dist/lib/dates.d.ts.map +1 -0
- package/dist/lib/dates.js +17 -0
- package/dist/lib/dates.js.map +1 -0
- package/dist/lib/email.d.ts +42 -0
- package/dist/lib/email.d.ts.map +1 -0
- package/dist/lib/email.js +38 -0
- package/dist/lib/email.js.map +1 -0
- package/dist/lib/errors.d.ts +76 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +102 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/http.d.ts +59 -0
- package/dist/lib/http.d.ts.map +1 -0
- package/dist/lib/http.js +89 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/ids.d.ts +55 -0
- package/dist/lib/ids.d.ts.map +1 -0
- package/dist/lib/ids.js +56 -0
- package/dist/lib/ids.js.map +1 -0
- package/dist/lib/logger.d.ts +22 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +43 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/moduleConfig.d.ts +14 -0
- package/dist/lib/moduleConfig.d.ts.map +1 -0
- package/dist/lib/moduleConfig.js +56 -0
- package/dist/lib/moduleConfig.js.map +1 -0
- package/dist/lib/normalisation.d.ts +19 -0
- package/dist/lib/normalisation.d.ts.map +1 -0
- package/dist/lib/normalisation.js +32 -0
- package/dist/lib/normalisation.js.map +1 -0
- package/dist/lib/pagination.d.ts +104 -0
- package/dist/lib/pagination.d.ts.map +1 -0
- package/dist/lib/pagination.js +189 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/passwords.d.ts +32 -0
- package/dist/lib/passwords.d.ts.map +1 -0
- package/dist/lib/passwords.js +51 -0
- package/dist/lib/passwords.js.map +1 -0
- package/dist/lib/search.d.ts +11 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +25 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/secrets.d.ts +40 -0
- package/dist/lib/secrets.d.ts.map +1 -0
- package/dist/lib/secrets.js +152 -0
- package/dist/lib/secrets.js.map +1 -0
- package/dist/lib/timezones.d.ts +38 -0
- package/dist/lib/timezones.d.ts.map +1 -0
- package/dist/lib/timezones.js +55 -0
- package/dist/lib/timezones.js.map +1 -0
- package/dist/lib/tokens.d.ts +10 -0
- package/dist/lib/tokens.d.ts.map +1 -0
- package/dist/lib/tokens.js +31 -0
- package/dist/lib/tokens.js.map +1 -0
- package/dist/lib/url.d.ts +25 -0
- package/dist/lib/url.d.ts.map +1 -0
- package/dist/lib/url.js +41 -0
- package/dist/lib/url.js.map +1 -0
- package/dist/modules/activities/index.d.ts +18 -0
- package/dist/modules/activities/index.d.ts.map +1 -0
- package/dist/modules/activities/index.js +34 -0
- package/dist/modules/activities/index.js.map +1 -0
- package/dist/modules/activities/recorder.d.ts +53 -0
- package/dist/modules/activities/recorder.d.ts.map +1 -0
- package/dist/modules/activities/recorder.js +36 -0
- package/dist/modules/activities/recorder.js.map +1 -0
- package/dist/modules/activities/repository.d.ts +52 -0
- package/dist/modules/activities/repository.d.ts.map +1 -0
- package/dist/modules/activities/repository.js +127 -0
- package/dist/modules/activities/repository.js.map +1 -0
- package/dist/modules/activities/routes.d.ts +17 -0
- package/dist/modules/activities/routes.d.ts.map +1 -0
- package/dist/modules/activities/routes.js +45 -0
- package/dist/modules/activities/routes.js.map +1 -0
- package/dist/modules/activities/schema.d.ts +188 -0
- package/dist/modules/activities/schema.d.ts.map +1 -0
- package/dist/modules/activities/schema.js +34 -0
- package/dist/modules/activities/schema.js.map +1 -0
- package/dist/modules/activities/service.d.ts +32 -0
- package/dist/modules/activities/service.d.ts.map +1 -0
- package/dist/modules/activities/service.js +28 -0
- package/dist/modules/activities/service.js.map +1 -0
- package/dist/modules/activities/tools.d.ts +4 -0
- package/dist/modules/activities/tools.d.ts.map +1 -0
- package/dist/modules/activities/tools.js +26 -0
- package/dist/modules/activities/tools.js.map +1 -0
- package/dist/modules/activities/wording.d.ts +79 -0
- package/dist/modules/activities/wording.d.ts.map +1 -0
- package/dist/modules/activities/wording.js +134 -0
- package/dist/modules/activities/wording.js.map +1 -0
- package/dist/modules/agent-tasks/catalog.d.ts +16 -0
- package/dist/modules/agent-tasks/catalog.d.ts.map +1 -0
- package/dist/modules/agent-tasks/catalog.js +694 -0
- package/dist/modules/agent-tasks/catalog.js.map +1 -0
- package/dist/modules/agent-tasks/dispatch.d.ts +61 -0
- package/dist/modules/agent-tasks/dispatch.d.ts.map +1 -0
- package/dist/modules/agent-tasks/dispatch.js +139 -0
- package/dist/modules/agent-tasks/dispatch.js.map +1 -0
- package/dist/modules/agent-tasks/index.d.ts +17 -0
- package/dist/modules/agent-tasks/index.d.ts.map +1 -0
- package/dist/modules/agent-tasks/index.js +54 -0
- package/dist/modules/agent-tasks/index.js.map +1 -0
- package/dist/modules/agent-tasks/prompt.d.ts +41 -0
- package/dist/modules/agent-tasks/prompt.d.ts.map +1 -0
- package/dist/modules/agent-tasks/prompt.js +78 -0
- package/dist/modules/agent-tasks/prompt.js.map +1 -0
- package/dist/modules/agent-tasks/repository.d.ts +32 -0
- package/dist/modules/agent-tasks/repository.d.ts.map +1 -0
- package/dist/modules/agent-tasks/repository.js +83 -0
- package/dist/modules/agent-tasks/repository.js.map +1 -0
- package/dist/modules/agent-tasks/resolve.d.ts +44 -0
- package/dist/modules/agent-tasks/resolve.d.ts.map +1 -0
- package/dist/modules/agent-tasks/resolve.js +396 -0
- package/dist/modules/agent-tasks/resolve.js.map +1 -0
- package/dist/modules/agent-tasks/routes.d.ts +55 -0
- package/dist/modules/agent-tasks/routes.d.ts.map +1 -0
- package/dist/modules/agent-tasks/routes.js +173 -0
- package/dist/modules/agent-tasks/routes.js.map +1 -0
- package/dist/modules/agent-tasks/schema.d.ts +346 -0
- package/dist/modules/agent-tasks/schema.d.ts.map +1 -0
- package/dist/modules/agent-tasks/schema.js +47 -0
- package/dist/modules/agent-tasks/schema.js.map +1 -0
- package/dist/modules/agent-tasks/service.d.ts +79 -0
- package/dist/modules/agent-tasks/service.d.ts.map +1 -0
- package/dist/modules/agent-tasks/service.js +210 -0
- package/dist/modules/agent-tasks/service.js.map +1 -0
- package/dist/modules/agent-tasks/wire.d.ts +35 -0
- package/dist/modules/agent-tasks/wire.d.ts.map +1 -0
- package/dist/modules/agent-tasks/wire.js +31 -0
- package/dist/modules/agent-tasks/wire.js.map +1 -0
- package/dist/modules/api-keys/index.d.ts +9 -0
- package/dist/modules/api-keys/index.d.ts.map +1 -0
- package/dist/modules/api-keys/index.js +29 -0
- package/dist/modules/api-keys/index.js.map +1 -0
- package/dist/modules/api-keys/keys.d.ts +25 -0
- package/dist/modules/api-keys/keys.d.ts.map +1 -0
- package/dist/modules/api-keys/keys.js +40 -0
- package/dist/modules/api-keys/keys.js.map +1 -0
- package/dist/modules/api-keys/repository.d.ts +15 -0
- package/dist/modules/api-keys/repository.d.ts.map +1 -0
- package/dist/modules/api-keys/repository.js +48 -0
- package/dist/modules/api-keys/repository.js.map +1 -0
- package/dist/modules/api-keys/routes.d.ts +8 -0
- package/dist/modules/api-keys/routes.d.ts.map +1 -0
- package/dist/modules/api-keys/routes.js +52 -0
- package/dist/modules/api-keys/routes.js.map +1 -0
- package/dist/modules/api-keys/schema.d.ts +166 -0
- package/dist/modules/api-keys/schema.d.ts.map +1 -0
- package/dist/modules/api-keys/schema.js +23 -0
- package/dist/modules/api-keys/schema.js.map +1 -0
- package/dist/modules/api-keys/service.d.ts +37 -0
- package/dist/modules/api-keys/service.d.ts.map +1 -0
- package/dist/modules/api-keys/service.js +95 -0
- package/dist/modules/api-keys/service.js.map +1 -0
- package/dist/modules/attachedRecords.d.ts +39 -0
- package/dist/modules/attachedRecords.d.ts.map +1 -0
- package/dist/modules/attachedRecords.js +52 -0
- package/dist/modules/attachedRecords.js.map +1 -0
- package/dist/modules/auth/actor.d.ts +11 -0
- package/dist/modules/auth/actor.d.ts.map +1 -0
- package/dist/modules/auth/actor.js +10 -0
- package/dist/modules/auth/actor.js.map +1 -0
- package/dist/modules/auth/credentials.d.ts +18 -0
- package/dist/modules/auth/credentials.d.ts.map +1 -0
- package/dist/modules/auth/credentials.js +105 -0
- package/dist/modules/auth/credentials.js.map +1 -0
- package/dist/modules/auth/index.d.ts +3 -0
- package/dist/modules/auth/index.d.ts.map +1 -0
- package/dist/modules/auth/index.js +41 -0
- package/dist/modules/auth/index.js.map +1 -0
- package/dist/modules/auth/preferences.d.ts +34 -0
- package/dist/modules/auth/preferences.d.ts.map +1 -0
- package/dist/modules/auth/preferences.js +30 -0
- package/dist/modules/auth/preferences.js.map +1 -0
- package/dist/modules/auth/repository.d.ts +54 -0
- package/dist/modules/auth/repository.d.ts.map +1 -0
- package/dist/modules/auth/repository.js +137 -0
- package/dist/modules/auth/repository.js.map +1 -0
- package/dist/modules/auth/routes.d.ts +10 -0
- package/dist/modules/auth/routes.d.ts.map +1 -0
- package/dist/modules/auth/routes.js +181 -0
- package/dist/modules/auth/routes.js.map +1 -0
- package/dist/modules/auth/schema.d.ts +530 -0
- package/dist/modules/auth/schema.d.ts.map +1 -0
- package/dist/modules/auth/schema.js +67 -0
- package/dist/modules/auth/schema.js.map +1 -0
- package/dist/modules/auth/service.d.ts +73 -0
- package/dist/modules/auth/service.d.ts.map +1 -0
- package/dist/modules/auth/service.js +288 -0
- package/dist/modules/auth/service.js.map +1 -0
- package/dist/modules/auth/session.d.ts +16 -0
- package/dist/modules/auth/session.d.ts.map +1 -0
- package/dist/modules/auth/session.js +30 -0
- package/dist/modules/auth/session.js.map +1 -0
- package/dist/modules/companies/index.d.ts +9 -0
- package/dist/modules/companies/index.d.ts.map +1 -0
- package/dist/modules/companies/index.js +37 -0
- package/dist/modules/companies/index.js.map +1 -0
- package/dist/modules/companies/repository.d.ts +40 -0
- package/dist/modules/companies/repository.d.ts.map +1 -0
- package/dist/modules/companies/repository.js +112 -0
- package/dist/modules/companies/repository.js.map +1 -0
- package/dist/modules/companies/routes.d.ts +89 -0
- package/dist/modules/companies/routes.d.ts.map +1 -0
- package/dist/modules/companies/routes.js +125 -0
- package/dist/modules/companies/routes.js.map +1 -0
- package/dist/modules/companies/schema.d.ts +381 -0
- package/dist/modules/companies/schema.d.ts.map +1 -0
- package/dist/modules/companies/schema.js +51 -0
- package/dist/modules/companies/schema.js.map +1 -0
- package/dist/modules/companies/service.d.ts +49 -0
- package/dist/modules/companies/service.d.ts.map +1 -0
- package/dist/modules/companies/service.js +184 -0
- package/dist/modules/companies/service.js.map +1 -0
- package/dist/modules/companies/tools.d.ts +4 -0
- package/dist/modules/companies/tools.d.ts.map +1 -0
- package/dist/modules/companies/tools.js +27 -0
- package/dist/modules/companies/tools.js.map +1 -0
- package/dist/modules/core.d.ts +21 -0
- package/dist/modules/core.d.ts.map +1 -0
- package/dist/modules/core.js +82 -0
- package/dist/modules/core.js.map +1 -0
- package/dist/modules/crudTools.d.ts +99 -0
- package/dist/modules/crudTools.d.ts.map +1 -0
- package/dist/modules/crudTools.js +123 -0
- package/dist/modules/crudTools.js.map +1 -0
- package/dist/modules/dashboard/attention.d.ts +39 -0
- package/dist/modules/dashboard/attention.d.ts.map +1 -0
- package/dist/modules/dashboard/attention.js +57 -0
- package/dist/modules/dashboard/attention.js.map +1 -0
- package/dist/modules/dashboard/index.d.ts +15 -0
- package/dist/modules/dashboard/index.d.ts.map +1 -0
- package/dist/modules/dashboard/index.js +44 -0
- package/dist/modules/dashboard/index.js.map +1 -0
- package/dist/modules/dashboard/repository.d.ts +83 -0
- package/dist/modules/dashboard/repository.d.ts.map +1 -0
- package/dist/modules/dashboard/repository.js +217 -0
- package/dist/modules/dashboard/repository.js.map +1 -0
- package/dist/modules/dashboard/routes.d.ts +21 -0
- package/dist/modules/dashboard/routes.d.ts.map +1 -0
- package/dist/modules/dashboard/routes.js +116 -0
- package/dist/modules/dashboard/routes.js.map +1 -0
- package/dist/modules/dashboard/service.d.ts +122 -0
- package/dist/modules/dashboard/service.d.ts.map +1 -0
- package/dist/modules/dashboard/service.js +215 -0
- package/dist/modules/dashboard/service.js.map +1 -0
- package/dist/modules/dashboard/tools.d.ts +4 -0
- package/dist/modules/dashboard/tools.d.ts.map +1 -0
- package/dist/modules/dashboard/tools.js +33 -0
- package/dist/modules/dashboard/tools.js.map +1 -0
- package/dist/modules/deals/index.d.ts +11 -0
- package/dist/modules/deals/index.d.ts.map +1 -0
- package/dist/modules/deals/index.js +38 -0
- package/dist/modules/deals/index.js.map +1 -0
- package/dist/modules/deals/repository.d.ts +44 -0
- package/dist/modules/deals/repository.d.ts.map +1 -0
- package/dist/modules/deals/repository.js +160 -0
- package/dist/modules/deals/repository.js.map +1 -0
- package/dist/modules/deals/routes.d.ts +50 -0
- package/dist/modules/deals/routes.d.ts.map +1 -0
- package/dist/modules/deals/routes.js +132 -0
- package/dist/modules/deals/routes.js.map +1 -0
- package/dist/modules/deals/schema.d.ts +419 -0
- package/dist/modules/deals/schema.d.ts.map +1 -0
- package/dist/modules/deals/schema.js +61 -0
- package/dist/modules/deals/schema.js.map +1 -0
- package/dist/modules/deals/service.d.ts +71 -0
- package/dist/modules/deals/service.d.ts.map +1 -0
- package/dist/modules/deals/service.js +277 -0
- package/dist/modules/deals/service.js.map +1 -0
- package/dist/modules/deals/tools.d.ts +4 -0
- package/dist/modules/deals/tools.d.ts.map +1 -0
- package/dist/modules/deals/tools.js +33 -0
- package/dist/modules/deals/tools.js.map +1 -0
- package/dist/modules/decisions/index.d.ts +11 -0
- package/dist/modules/decisions/index.d.ts.map +1 -0
- package/dist/modules/decisions/index.js +34 -0
- package/dist/modules/decisions/index.js.map +1 -0
- package/dist/modules/decisions/repository.d.ts +38 -0
- package/dist/modules/decisions/repository.d.ts.map +1 -0
- package/dist/modules/decisions/repository.js +126 -0
- package/dist/modules/decisions/repository.js.map +1 -0
- package/dist/modules/decisions/routes.d.ts +42 -0
- package/dist/modules/decisions/routes.d.ts.map +1 -0
- package/dist/modules/decisions/routes.js +131 -0
- package/dist/modules/decisions/routes.js.map +1 -0
- package/dist/modules/decisions/schema.d.ts +228 -0
- package/dist/modules/decisions/schema.d.ts.map +1 -0
- package/dist/modules/decisions/schema.js +41 -0
- package/dist/modules/decisions/schema.js.map +1 -0
- package/dist/modules/decisions/service.d.ts +60 -0
- package/dist/modules/decisions/service.d.ts.map +1 -0
- package/dist/modules/decisions/service.js +122 -0
- package/dist/modules/decisions/service.js.map +1 -0
- package/dist/modules/decisions/tools.d.ts +4 -0
- package/dist/modules/decisions/tools.d.ts.map +1 -0
- package/dist/modules/decisions/tools.js +32 -0
- package/dist/modules/decisions/tools.js.map +1 -0
- package/dist/modules/forms/embed.d.ts +50 -0
- package/dist/modules/forms/embed.d.ts.map +1 -0
- package/dist/modules/forms/embed.js +236 -0
- package/dist/modules/forms/embed.js.map +1 -0
- package/dist/modules/forms/fields.d.ts +71 -0
- package/dist/modules/forms/fields.d.ts.map +1 -0
- package/dist/modules/forms/fields.js +122 -0
- package/dist/modules/forms/fields.js.map +1 -0
- package/dist/modules/forms/index.d.ts +15 -0
- package/dist/modules/forms/index.d.ts.map +1 -0
- package/dist/modules/forms/index.js +53 -0
- package/dist/modules/forms/index.js.map +1 -0
- package/dist/modules/forms/mapping.d.ts +99 -0
- package/dist/modules/forms/mapping.d.ts.map +1 -0
- package/dist/modules/forms/mapping.js +152 -0
- package/dist/modules/forms/mapping.js.map +1 -0
- package/dist/modules/forms/publicRoutes.d.ts +11 -0
- package/dist/modules/forms/publicRoutes.d.ts.map +1 -0
- package/dist/modules/forms/publicRoutes.js +68 -0
- package/dist/modules/forms/publicRoutes.js.map +1 -0
- package/dist/modules/forms/repository.d.ts +65 -0
- package/dist/modules/forms/repository.d.ts.map +1 -0
- package/dist/modules/forms/repository.js +139 -0
- package/dist/modules/forms/repository.js.map +1 -0
- package/dist/modules/forms/routes.d.ts +106 -0
- package/dist/modules/forms/routes.d.ts.map +1 -0
- package/dist/modules/forms/routes.js +204 -0
- package/dist/modules/forms/routes.js.map +1 -0
- package/dist/modules/forms/schema.d.ts +643 -0
- package/dist/modules/forms/schema.d.ts.map +1 -0
- package/dist/modules/forms/schema.js +87 -0
- package/dist/modules/forms/schema.js.map +1 -0
- package/dist/modules/forms/service.d.ts +62 -0
- package/dist/modules/forms/service.d.ts.map +1 -0
- package/dist/modules/forms/service.js +208 -0
- package/dist/modules/forms/service.js.map +1 -0
- package/dist/modules/forms/submission.d.ts +30 -0
- package/dist/modules/forms/submission.d.ts.map +1 -0
- package/dist/modules/forms/submission.js +337 -0
- package/dist/modules/forms/submission.js.map +1 -0
- package/dist/modules/forms/tools.d.ts +4 -0
- package/dist/modules/forms/tools.d.ts.map +1 -0
- package/dist/modules/forms/tools.js +46 -0
- package/dist/modules/forms/tools.js.map +1 -0
- package/dist/modules/handbook/index.d.ts +15 -0
- package/dist/modules/handbook/index.d.ts.map +1 -0
- package/dist/modules/handbook/index.js +37 -0
- package/dist/modules/handbook/index.js.map +1 -0
- package/dist/modules/handbook/repository.d.ts +52 -0
- package/dist/modules/handbook/repository.d.ts.map +1 -0
- package/dist/modules/handbook/repository.js +109 -0
- package/dist/modules/handbook/repository.js.map +1 -0
- package/dist/modules/handbook/routes.d.ts +38 -0
- package/dist/modules/handbook/routes.d.ts.map +1 -0
- package/dist/modules/handbook/routes.js +103 -0
- package/dist/modules/handbook/routes.js.map +1 -0
- package/dist/modules/handbook/schema.d.ts +206 -0
- package/dist/modules/handbook/schema.d.ts.map +1 -0
- package/dist/modules/handbook/schema.js +37 -0
- package/dist/modules/handbook/schema.js.map +1 -0
- package/dist/modules/handbook/service.d.ts +59 -0
- package/dist/modules/handbook/service.d.ts.map +1 -0
- package/dist/modules/handbook/service.js +246 -0
- package/dist/modules/handbook/service.js.map +1 -0
- package/dist/modules/handbook/slugs.d.ts +28 -0
- package/dist/modules/handbook/slugs.d.ts.map +1 -0
- package/dist/modules/handbook/slugs.js +48 -0
- package/dist/modules/handbook/slugs.js.map +1 -0
- package/dist/modules/handbook/tools.d.ts +4 -0
- package/dist/modules/handbook/tools.d.ts.map +1 -0
- package/dist/modules/handbook/tools.js +26 -0
- package/dist/modules/handbook/tools.js.map +1 -0
- package/dist/modules/handbook/tree.d.ts +69 -0
- package/dist/modules/handbook/tree.d.ts.map +1 -0
- package/dist/modules/handbook/tree.js +117 -0
- package/dist/modules/handbook/tree.js.map +1 -0
- package/dist/modules/hiring/candidates.d.ts +70 -0
- package/dist/modules/hiring/candidates.d.ts.map +1 -0
- package/dist/modules/hiring/candidates.js +243 -0
- package/dist/modules/hiring/candidates.js.map +1 -0
- package/dist/modules/hiring/index.d.ts +15 -0
- package/dist/modules/hiring/index.d.ts.map +1 -0
- package/dist/modules/hiring/index.js +48 -0
- package/dist/modules/hiring/index.js.map +1 -0
- package/dist/modules/hiring/repository.d.ts +52 -0
- package/dist/modules/hiring/repository.d.ts.map +1 -0
- package/dist/modules/hiring/repository.js +137 -0
- package/dist/modules/hiring/repository.js.map +1 -0
- package/dist/modules/hiring/roles.d.ts +42 -0
- package/dist/modules/hiring/roles.d.ts.map +1 -0
- package/dist/modules/hiring/roles.js +104 -0
- package/dist/modules/hiring/roles.js.map +1 -0
- package/dist/modules/hiring/routes.d.ts +73 -0
- package/dist/modules/hiring/routes.d.ts.map +1 -0
- package/dist/modules/hiring/routes.js +170 -0
- package/dist/modules/hiring/routes.js.map +1 -0
- package/dist/modules/hiring/schema.d.ts +308 -0
- package/dist/modules/hiring/schema.d.ts.map +1 -0
- package/dist/modules/hiring/schema.js +62 -0
- package/dist/modules/hiring/schema.js.map +1 -0
- package/dist/modules/hiring/tools.d.ts +8 -0
- package/dist/modules/hiring/tools.d.ts.map +1 -0
- package/dist/modules/hiring/tools.js +50 -0
- package/dist/modules/hiring/tools.js.map +1 -0
- package/dist/modules/import-export/csv.d.ts +47 -0
- package/dist/modules/import-export/csv.d.ts.map +1 -0
- package/dist/modules/import-export/csv.js +138 -0
- package/dist/modules/import-export/csv.js.map +1 -0
- package/dist/modules/import-export/drafts.d.ts +83 -0
- package/dist/modules/import-export/drafts.d.ts.map +1 -0
- package/dist/modules/import-export/drafts.js +97 -0
- package/dist/modules/import-export/drafts.js.map +1 -0
- package/dist/modules/import-export/exportRows.d.ts +8 -0
- package/dist/modules/import-export/exportRows.d.ts.map +1 -0
- package/dist/modules/import-export/exportRows.js +71 -0
- package/dist/modules/import-export/exportRows.js.map +1 -0
- package/dist/modules/import-export/index.d.ts +15 -0
- package/dist/modules/import-export/index.d.ts.map +1 -0
- package/dist/modules/import-export/index.js +43 -0
- package/dist/modules/import-export/index.js.map +1 -0
- package/dist/modules/import-export/mapping.d.ts +46 -0
- package/dist/modules/import-export/mapping.d.ts.map +1 -0
- package/dist/modules/import-export/mapping.js +115 -0
- package/dist/modules/import-export/mapping.js.map +1 -0
- package/dist/modules/import-export/plan.d.ts +107 -0
- package/dist/modules/import-export/plan.d.ts.map +1 -0
- package/dist/modules/import-export/plan.js +178 -0
- package/dist/modules/import-export/plan.js.map +1 -0
- package/dist/modules/import-export/presets.d.ts +39 -0
- package/dist/modules/import-export/presets.d.ts.map +1 -0
- package/dist/modules/import-export/presets.js +151 -0
- package/dist/modules/import-export/presets.js.map +1 -0
- package/dist/modules/import-export/repository.d.ts +171 -0
- package/dist/modules/import-export/repository.d.ts.map +1 -0
- package/dist/modules/import-export/repository.js +343 -0
- package/dist/modules/import-export/repository.js.map +1 -0
- package/dist/modules/import-export/routes.d.ts +9 -0
- package/dist/modules/import-export/routes.d.ts.map +1 -0
- package/dist/modules/import-export/routes.js +199 -0
- package/dist/modules/import-export/routes.js.map +1 -0
- package/dist/modules/import-export/schema.d.ts +494 -0
- package/dist/modules/import-export/schema.d.ts.map +1 -0
- package/dist/modules/import-export/schema.js +99 -0
- package/dist/modules/import-export/schema.js.map +1 -0
- package/dist/modules/import-export/service.d.ts +74 -0
- package/dist/modules/import-export/service.d.ts.map +1 -0
- package/dist/modules/import-export/service.js +561 -0
- package/dist/modules/import-export/service.js.map +1 -0
- package/dist/modules/import-export/streams.d.ts +4 -0
- package/dist/modules/import-export/streams.d.ts.map +1 -0
- package/dist/modules/import-export/streams.js +55 -0
- package/dist/modules/import-export/streams.js.map +1 -0
- package/dist/modules/import-export/tools.d.ts +22 -0
- package/dist/modules/import-export/tools.d.ts.map +1 -0
- package/dist/modules/import-export/tools.js +116 -0
- package/dist/modules/import-export/tools.js.map +1 -0
- package/dist/modules/import-export/validation.d.ts +7 -0
- package/dist/modules/import-export/validation.d.ts.map +1 -0
- package/dist/modules/import-export/validation.js +114 -0
- package/dist/modules/import-export/validation.js.map +1 -0
- package/dist/modules/import-export/writes.d.ts +45 -0
- package/dist/modules/import-export/writes.d.ts.map +1 -0
- package/dist/modules/import-export/writes.js +247 -0
- package/dist/modules/import-export/writes.js.map +1 -0
- package/dist/modules/integrations/schema.d.ts +185 -0
- package/dist/modules/integrations/schema.d.ts.map +1 -0
- package/dist/modules/integrations/schema.js +26 -0
- package/dist/modules/integrations/schema.js.map +1 -0
- package/dist/modules/mcp/index.d.ts +26 -0
- package/dist/modules/mcp/index.d.ts.map +1 -0
- package/dist/modules/mcp/index.js +45 -0
- package/dist/modules/mcp/index.js.map +1 -0
- package/dist/modules/mcp/protocol.d.ts +166 -0
- package/dist/modules/mcp/protocol.d.ts.map +1 -0
- package/dist/modules/mcp/protocol.js +292 -0
- package/dist/modules/mcp/protocol.js.map +1 -0
- package/dist/modules/mcp/router.d.ts +23 -0
- package/dist/modules/mcp/router.d.ts.map +1 -0
- package/dist/modules/mcp/router.js +298 -0
- package/dist/modules/mcp/router.js.map +1 -0
- package/dist/modules/notes/index.d.ts +9 -0
- package/dist/modules/notes/index.d.ts.map +1 -0
- package/dist/modules/notes/index.js +37 -0
- package/dist/modules/notes/index.js.map +1 -0
- package/dist/modules/notes/repository.d.ts +34 -0
- package/dist/modules/notes/repository.d.ts.map +1 -0
- package/dist/modules/notes/repository.js +70 -0
- package/dist/modules/notes/repository.js.map +1 -0
- package/dist/modules/notes/routes.d.ts +37 -0
- package/dist/modules/notes/routes.d.ts.map +1 -0
- package/dist/modules/notes/routes.js +124 -0
- package/dist/modules/notes/routes.js.map +1 -0
- package/dist/modules/notes/schema.d.ts +176 -0
- package/dist/modules/notes/schema.d.ts.map +1 -0
- package/dist/modules/notes/schema.js +35 -0
- package/dist/modules/notes/schema.js.map +1 -0
- package/dist/modules/notes/service.d.ts +49 -0
- package/dist/modules/notes/service.d.ts.map +1 -0
- package/dist/modules/notes/service.js +118 -0
- package/dist/modules/notes/service.js.map +1 -0
- package/dist/modules/notes/tools.d.ts +4 -0
- package/dist/modules/notes/tools.d.ts.map +1 -0
- package/dist/modules/notes/tools.js +41 -0
- package/dist/modules/notes/tools.js.map +1 -0
- package/dist/modules/opportunities/index.d.ts +11 -0
- package/dist/modules/opportunities/index.d.ts.map +1 -0
- package/dist/modules/opportunities/index.js +38 -0
- package/dist/modules/opportunities/index.js.map +1 -0
- package/dist/modules/opportunities/repository.d.ts +28 -0
- package/dist/modules/opportunities/repository.d.ts.map +1 -0
- package/dist/modules/opportunities/repository.js +89 -0
- package/dist/modules/opportunities/repository.js.map +1 -0
- package/dist/modules/opportunities/routes.d.ts +39 -0
- package/dist/modules/opportunities/routes.d.ts.map +1 -0
- package/dist/modules/opportunities/routes.js +104 -0
- package/dist/modules/opportunities/routes.js.map +1 -0
- package/dist/modules/opportunities/schema.d.ts +266 -0
- package/dist/modules/opportunities/schema.d.ts.map +1 -0
- package/dist/modules/opportunities/schema.js +41 -0
- package/dist/modules/opportunities/schema.js.map +1 -0
- package/dist/modules/opportunities/service.d.ts +60 -0
- package/dist/modules/opportunities/service.d.ts.map +1 -0
- package/dist/modules/opportunities/service.js +212 -0
- package/dist/modules/opportunities/service.js.map +1 -0
- package/dist/modules/opportunities/tools.d.ts +4 -0
- package/dist/modules/opportunities/tools.d.ts.map +1 -0
- package/dist/modules/opportunities/tools.js +33 -0
- package/dist/modules/opportunities/tools.js.map +1 -0
- package/dist/modules/partnerships/index.d.ts +11 -0
- package/dist/modules/partnerships/index.d.ts.map +1 -0
- package/dist/modules/partnerships/index.js +38 -0
- package/dist/modules/partnerships/index.js.map +1 -0
- package/dist/modules/partnerships/repository.d.ts +47 -0
- package/dist/modules/partnerships/repository.d.ts.map +1 -0
- package/dist/modules/partnerships/repository.js +169 -0
- package/dist/modules/partnerships/repository.js.map +1 -0
- package/dist/modules/partnerships/routes.d.ts +46 -0
- package/dist/modules/partnerships/routes.d.ts.map +1 -0
- package/dist/modules/partnerships/routes.js +122 -0
- package/dist/modules/partnerships/routes.js.map +1 -0
- package/dist/modules/partnerships/schema.d.ts +338 -0
- package/dist/modules/partnerships/schema.d.ts.map +1 -0
- package/dist/modules/partnerships/schema.js +54 -0
- package/dist/modules/partnerships/schema.js.map +1 -0
- package/dist/modules/partnerships/service.d.ts +71 -0
- package/dist/modules/partnerships/service.d.ts.map +1 -0
- package/dist/modules/partnerships/service.js +273 -0
- package/dist/modules/partnerships/service.js.map +1 -0
- package/dist/modules/partnerships/tools.d.ts +4 -0
- package/dist/modules/partnerships/tools.d.ts.map +1 -0
- package/dist/modules/partnerships/tools.js +35 -0
- package/dist/modules/partnerships/tools.js.map +1 -0
- package/dist/modules/people/index.d.ts +9 -0
- package/dist/modules/people/index.d.ts.map +1 -0
- package/dist/modules/people/index.js +37 -0
- package/dist/modules/people/index.js.map +1 -0
- package/dist/modules/people/repository.d.ts +31 -0
- package/dist/modules/people/repository.d.ts.map +1 -0
- package/dist/modules/people/repository.js +109 -0
- package/dist/modules/people/repository.js.map +1 -0
- package/dist/modules/people/routes.d.ts +111 -0
- package/dist/modules/people/routes.d.ts.map +1 -0
- package/dist/modules/people/routes.js +134 -0
- package/dist/modules/people/routes.js.map +1 -0
- package/dist/modules/people/schema.d.ts +354 -0
- package/dist/modules/people/schema.d.ts.map +1 -0
- package/dist/modules/people/schema.js +61 -0
- package/dist/modules/people/schema.js.map +1 -0
- package/dist/modules/people/service.d.ts +56 -0
- package/dist/modules/people/service.d.ts.map +1 -0
- package/dist/modules/people/service.js +190 -0
- package/dist/modules/people/service.js.map +1 -0
- package/dist/modules/people/tools.d.ts +4 -0
- package/dist/modules/people/tools.d.ts.map +1 -0
- package/dist/modules/people/tools.js +27 -0
- package/dist/modules/people/tools.js.map +1 -0
- package/dist/modules/pipelines/index.d.ts +9 -0
- package/dist/modules/pipelines/index.d.ts.map +1 -0
- package/dist/modules/pipelines/index.js +37 -0
- package/dist/modules/pipelines/index.js.map +1 -0
- package/dist/modules/pipelines/repository.d.ts +26 -0
- package/dist/modules/pipelines/repository.d.ts.map +1 -0
- package/dist/modules/pipelines/repository.js +67 -0
- package/dist/modules/pipelines/repository.js.map +1 -0
- package/dist/modules/pipelines/routes.d.ts +33 -0
- package/dist/modules/pipelines/routes.d.ts.map +1 -0
- package/dist/modules/pipelines/routes.js +98 -0
- package/dist/modules/pipelines/routes.js.map +1 -0
- package/dist/modules/pipelines/schema.d.ts +170 -0
- package/dist/modules/pipelines/schema.d.ts.map +1 -0
- package/dist/modules/pipelines/schema.js +30 -0
- package/dist/modules/pipelines/schema.js.map +1 -0
- package/dist/modules/pipelines/service.d.ts +49 -0
- package/dist/modules/pipelines/service.d.ts.map +1 -0
- package/dist/modules/pipelines/service.js +227 -0
- package/dist/modules/pipelines/service.js.map +1 -0
- package/dist/modules/pipelines/tools.d.ts +4 -0
- package/dist/modules/pipelines/tools.d.ts.map +1 -0
- package/dist/modules/pipelines/tools.js +43 -0
- package/dist/modules/pipelines/tools.js.map +1 -0
- package/dist/modules/plans/index.d.ts +10 -0
- package/dist/modules/plans/index.d.ts.map +1 -0
- package/dist/modules/plans/index.js +33 -0
- package/dist/modules/plans/index.js.map +1 -0
- package/dist/modules/plans/repository.d.ts +49 -0
- package/dist/modules/plans/repository.d.ts.map +1 -0
- package/dist/modules/plans/repository.js +94 -0
- package/dist/modules/plans/repository.js.map +1 -0
- package/dist/modules/plans/routes.d.ts +46 -0
- package/dist/modules/plans/routes.d.ts.map +1 -0
- package/dist/modules/plans/routes.js +152 -0
- package/dist/modules/plans/routes.js.map +1 -0
- package/dist/modules/plans/schema.d.ts +209 -0
- package/dist/modules/plans/schema.d.ts.map +1 -0
- package/dist/modules/plans/schema.js +37 -0
- package/dist/modules/plans/schema.js.map +1 -0
- package/dist/modules/plans/service.d.ts +57 -0
- package/dist/modules/plans/service.d.ts.map +1 -0
- package/dist/modules/plans/service.js +125 -0
- package/dist/modules/plans/service.js.map +1 -0
- package/dist/modules/plans/tools.d.ts +4 -0
- package/dist/modules/plans/tools.d.ts.map +1 -0
- package/dist/modules/plans/tools.js +39 -0
- package/dist/modules/plans/tools.js.map +1 -0
- package/dist/modules/positions/index.d.ts +9 -0
- package/dist/modules/positions/index.d.ts.map +1 -0
- package/dist/modules/positions/index.js +36 -0
- package/dist/modules/positions/index.js.map +1 -0
- package/dist/modules/positions/repository.d.ts +34 -0
- package/dist/modules/positions/repository.d.ts.map +1 -0
- package/dist/modules/positions/repository.js +71 -0
- package/dist/modules/positions/repository.js.map +1 -0
- package/dist/modules/positions/routes.d.ts +22 -0
- package/dist/modules/positions/routes.d.ts.map +1 -0
- package/dist/modules/positions/routes.js +56 -0
- package/dist/modules/positions/routes.js.map +1 -0
- package/dist/modules/positions/schema.d.ts +154 -0
- package/dist/modules/positions/schema.d.ts.map +1 -0
- package/dist/modules/positions/schema.js +36 -0
- package/dist/modules/positions/schema.js.map +1 -0
- package/dist/modules/positions/service.d.ts +46 -0
- package/dist/modules/positions/service.d.ts.map +1 -0
- package/dist/modules/positions/service.js +159 -0
- package/dist/modules/positions/service.js.map +1 -0
- package/dist/modules/positions/tools.d.ts +4 -0
- package/dist/modules/positions/tools.d.ts.map +1 -0
- package/dist/modules/positions/tools.js +26 -0
- package/dist/modules/positions/tools.js.map +1 -0
- package/dist/modules/raises/index.d.ts +11 -0
- package/dist/modules/raises/index.d.ts.map +1 -0
- package/dist/modules/raises/index.js +38 -0
- package/dist/modules/raises/index.js.map +1 -0
- package/dist/modules/raises/repository.d.ts +48 -0
- package/dist/modules/raises/repository.d.ts.map +1 -0
- package/dist/modules/raises/repository.js +164 -0
- package/dist/modules/raises/repository.js.map +1 -0
- package/dist/modules/raises/routes.d.ts +48 -0
- package/dist/modules/raises/routes.d.ts.map +1 -0
- package/dist/modules/raises/routes.js +126 -0
- package/dist/modules/raises/routes.js.map +1 -0
- package/dist/modules/raises/schema.d.ts +356 -0
- package/dist/modules/raises/schema.d.ts.map +1 -0
- package/dist/modules/raises/schema.js +55 -0
- package/dist/modules/raises/schema.js.map +1 -0
- package/dist/modules/raises/service.d.ts +79 -0
- package/dist/modules/raises/service.d.ts.map +1 -0
- package/dist/modules/raises/service.js +275 -0
- package/dist/modules/raises/service.js.map +1 -0
- package/dist/modules/raises/tools.d.ts +4 -0
- package/dist/modules/raises/tools.d.ts.map +1 -0
- package/dist/modules/raises/tools.js +33 -0
- package/dist/modules/raises/tools.js.map +1 -0
- package/dist/modules/recordTargets.d.ts +55 -0
- package/dist/modules/recordTargets.d.ts.map +1 -0
- package/dist/modules/recordTargets.js +107 -0
- package/dist/modules/recordTargets.js.map +1 -0
- package/dist/modules/references.d.ts +8 -0
- package/dist/modules/references.d.ts.map +1 -0
- package/dist/modules/references.js +40 -0
- package/dist/modules/references.js.map +1 -0
- package/dist/modules/reseal.d.ts +33 -0
- package/dist/modules/reseal.d.ts.map +1 -0
- package/dist/modules/reseal.js +108 -0
- package/dist/modules/reseal.js.map +1 -0
- package/dist/modules/search/index.d.ts +21 -0
- package/dist/modules/search/index.d.ts.map +1 -0
- package/dist/modules/search/index.js +50 -0
- package/dist/modules/search/index.js.map +1 -0
- package/dist/modules/search/query.d.ts +44 -0
- package/dist/modules/search/query.d.ts.map +1 -0
- package/dist/modules/search/query.js +88 -0
- package/dist/modules/search/query.js.map +1 -0
- package/dist/modules/search/repository.d.ts +44 -0
- package/dist/modules/search/repository.d.ts.map +1 -0
- package/dist/modules/search/repository.js +252 -0
- package/dist/modules/search/repository.js.map +1 -0
- package/dist/modules/search/routes.d.ts +17 -0
- package/dist/modules/search/routes.d.ts.map +1 -0
- package/dist/modules/search/routes.js +93 -0
- package/dist/modules/search/routes.js.map +1 -0
- package/dist/modules/search/service.d.ts +55 -0
- package/dist/modules/search/service.d.ts.map +1 -0
- package/dist/modules/search/service.js +69 -0
- package/dist/modules/search/service.js.map +1 -0
- package/dist/modules/search/tools.d.ts +4 -0
- package/dist/modules/search/tools.d.ts.map +1 -0
- package/dist/modules/search/tools.js +52 -0
- package/dist/modules/search/tools.js.map +1 -0
- package/dist/modules/stagedRecords.d.ts +28 -0
- package/dist/modules/stagedRecords.d.ts.map +1 -0
- package/dist/modules/stagedRecords.js +50 -0
- package/dist/modules/stagedRecords.js.map +1 -0
- package/dist/modules/webhooks/delivery.d.ts +98 -0
- package/dist/modules/webhooks/delivery.d.ts.map +1 -0
- package/dist/modules/webhooks/delivery.js +237 -0
- package/dist/modules/webhooks/delivery.js.map +1 -0
- package/dist/modules/webhooks/index.d.ts +23 -0
- package/dist/modules/webhooks/index.d.ts.map +1 -0
- package/dist/modules/webhooks/index.js +48 -0
- package/dist/modules/webhooks/index.js.map +1 -0
- package/dist/modules/webhooks/payloads.d.ts +31 -0
- package/dist/modules/webhooks/payloads.d.ts.map +1 -0
- package/dist/modules/webhooks/payloads.js +52 -0
- package/dist/modules/webhooks/payloads.js.map +1 -0
- package/dist/modules/webhooks/repository.d.ts +70 -0
- package/dist/modules/webhooks/repository.d.ts.map +1 -0
- package/dist/modules/webhooks/repository.js +140 -0
- package/dist/modules/webhooks/repository.js.map +1 -0
- package/dist/modules/webhooks/routes.d.ts +47 -0
- package/dist/modules/webhooks/routes.d.ts.map +1 -0
- package/dist/modules/webhooks/routes.js +170 -0
- package/dist/modules/webhooks/routes.js.map +1 -0
- package/dist/modules/webhooks/schema.d.ts +396 -0
- package/dist/modules/webhooks/schema.d.ts.map +1 -0
- package/dist/modules/webhooks/schema.js +61 -0
- package/dist/modules/webhooks/schema.js.map +1 -0
- package/dist/modules/webhooks/service.d.ts +65 -0
- package/dist/modules/webhooks/service.d.ts.map +1 -0
- package/dist/modules/webhooks/service.js +202 -0
- package/dist/modules/webhooks/service.js.map +1 -0
- package/dist/modules/webhooks/signing.d.ts +57 -0
- package/dist/modules/webhooks/signing.d.ts.map +1 -0
- package/dist/modules/webhooks/signing.js +69 -0
- package/dist/modules/webhooks/signing.js.map +1 -0
- package/dist/modules/webhooks/tools.d.ts +4 -0
- package/dist/modules/webhooks/tools.d.ts.map +1 -0
- package/dist/modules/webhooks/tools.js +77 -0
- package/dist/modules/webhooks/tools.js.map +1 -0
- package/dist/modules/webhooks/url.d.ts +10 -0
- package/dist/modules/webhooks/url.d.ts.map +1 -0
- package/dist/modules/webhooks/url.js +9 -0
- package/dist/modules/webhooks/url.js.map +1 -0
- package/dist/modules/workspace/capabilities.d.ts +9 -0
- package/dist/modules/workspace/capabilities.d.ts.map +1 -0
- package/dist/modules/workspace/capabilities.js +12 -0
- package/dist/modules/workspace/capabilities.js.map +1 -0
- package/dist/modules/workspace/idempotencyMiddleware.d.ts +16 -0
- package/dist/modules/workspace/idempotencyMiddleware.d.ts.map +1 -0
- package/dist/modules/workspace/idempotencyMiddleware.js +142 -0
- package/dist/modules/workspace/idempotencyMiddleware.js.map +1 -0
- package/dist/modules/workspace/idempotencyRepository.d.ts +43 -0
- package/dist/modules/workspace/idempotencyRepository.d.ts.map +1 -0
- package/dist/modules/workspace/idempotencyRepository.js +75 -0
- package/dist/modules/workspace/idempotencyRepository.js.map +1 -0
- package/dist/modules/workspace/index.d.ts +9 -0
- package/dist/modules/workspace/index.d.ts.map +1 -0
- package/dist/modules/workspace/index.js +53 -0
- package/dist/modules/workspace/index.js.map +1 -0
- package/dist/modules/workspace/repository.d.ts +112 -0
- package/dist/modules/workspace/repository.d.ts.map +1 -0
- package/dist/modules/workspace/repository.js +266 -0
- package/dist/modules/workspace/repository.js.map +1 -0
- package/dist/modules/workspace/roles.d.ts +22 -0
- package/dist/modules/workspace/roles.d.ts.map +1 -0
- package/dist/modules/workspace/roles.js +31 -0
- package/dist/modules/workspace/roles.js.map +1 -0
- package/dist/modules/workspace/routes.d.ts +41 -0
- package/dist/modules/workspace/routes.d.ts.map +1 -0
- package/dist/modules/workspace/routes.js +158 -0
- package/dist/modules/workspace/routes.js.map +1 -0
- package/dist/modules/workspace/schema.d.ts +719 -0
- package/dist/modules/workspace/schema.d.ts.map +1 -0
- package/dist/modules/workspace/schema.js +102 -0
- package/dist/modules/workspace/schema.js.map +1 -0
- package/dist/modules/workspace/service.d.ts +94 -0
- package/dist/modules/workspace/service.d.ts.map +1 -0
- package/dist/modules/workspace/service.js +528 -0
- package/dist/modules/workspace/service.js.map +1 -0
- package/dist/modules/workspace/starters.d.ts +22 -0
- package/dist/modules/workspace/starters.d.ts.map +1 -0
- package/dist/modules/workspace/starters.js +56 -0
- package/dist/modules/workspace/starters.js.map +1 -0
- package/dist/modules/workspace/tools.d.ts +4 -0
- package/dist/modules/workspace/tools.d.ts.map +1 -0
- package/dist/modules/workspace/tools.js +95 -0
- package/dist/modules/workspace/tools.js.map +1 -0
- package/dist/runtime/entitlements.d.ts +66 -0
- package/dist/runtime/entitlements.d.ts.map +1 -0
- package/dist/runtime/entitlements.js +62 -0
- package/dist/runtime/entitlements.js.map +1 -0
- package/dist/runtime/events.d.ts +139 -0
- package/dist/runtime/events.d.ts.map +1 -0
- package/dist/runtime/events.js +98 -0
- package/dist/runtime/events.js.map +1 -0
- package/dist/runtime/migrate.d.ts +28 -0
- package/dist/runtime/migrate.d.ts.map +1 -0
- package/dist/runtime/migrate.js +43 -0
- package/dist/runtime/migrate.js.map +1 -0
- package/dist/runtime/module.d.ts +138 -0
- package/dist/runtime/module.d.ts.map +1 -0
- package/dist/runtime/module.js +2 -0
- package/dist/runtime/module.js.map +1 -0
- package/dist/runtime/moduleConfig.d.ts +21 -0
- package/dist/runtime/moduleConfig.d.ts.map +1 -0
- package/dist/runtime/moduleConfig.js +54 -0
- package/dist/runtime/moduleConfig.js.map +1 -0
- package/dist/runtime/order.d.ts +21 -0
- package/dist/runtime/order.d.ts.map +1 -0
- package/dist/runtime/order.js +72 -0
- package/dist/runtime/order.js.map +1 -0
- package/dist/runtime/registry.d.ts +66 -0
- package/dist/runtime/registry.d.ts.map +1 -0
- package/dist/runtime/registry.js +148 -0
- package/dist/runtime/registry.js.map +1 -0
- package/dist/runtime/transaction.d.ts +34 -0
- package/dist/runtime/transaction.d.ts.map +1 -0
- package/dist/runtime/transaction.js +24 -0
- package/dist/runtime/transaction.js.map +1 -0
- package/dist/schema/index.d.ts +30 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +30 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/testing/app.d.ts +42 -0
- package/dist/testing/app.d.ts.map +1 -0
- package/dist/testing/app.js +31 -0
- package/dist/testing/app.js.map +1 -0
- package/dist/testing/client.d.ts +34 -0
- package/dist/testing/client.d.ts.map +1 -0
- package/dist/testing/client.js +70 -0
- package/dist/testing/client.js.map +1 -0
- package/dist/testing/database.d.ts +17 -0
- package/dist/testing/database.d.ts.map +1 -0
- package/dist/testing/database.js +84 -0
- package/dist/testing/database.js.map +1 -0
- package/dist/testing/environment.d.ts +17 -0
- package/dist/testing/environment.d.ts.map +1 -0
- package/dist/testing/environment.js +19 -0
- package/dist/testing/environment.js.map +1 -0
- package/dist/testing/fixtures.d.ts +22 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +55 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +6 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/services.d.ts +18 -0
- package/dist/testing/services.d.ts.map +1 -0
- package/dist/testing/services.js +43 -0
- package/dist/testing/services.js.map +1 -0
- package/migrations/0000_initial_schema.sql +597 -0
- package/migrations/0001_uneven_lockjaw.sql +11 -0
- package/migrations/0002_neat_madame_web.sql +2 -0
- package/migrations/0003_bright_shockwave.sql +1 -0
- package/migrations/0004_drop_unused_import_columns.sql +2 -0
- package/migrations/0005_import_job_rows.sql +23 -0
- package/migrations/0006_drop_webhook_secret_hash.sql +1 -0
- package/migrations/0007_add_webhook_secret_encrypted.sql +1 -0
- package/migrations/0008_rich_mister_sinister.sql +3 -0
- package/migrations/0009_natural_proemial_gods.sql +1 -0
- package/migrations/0010_fine_brood.sql +1 -0
- package/migrations/0011_add_webhook_previous_secret.sql +2 -0
- package/migrations/0012_idempotency_keys_response_nullable.sql +1 -0
- package/migrations/0013_add_agent_run_failure_reason.sql +1 -0
- package/migrations/0014_right_shinko_yamashiro.sql +12 -0
- package/migrations/0015_peaceful_chimera.sql +33 -0
- package/migrations/meta/0000_snapshot.json +4467 -0
- package/migrations/meta/0001_snapshot.json +4539 -0
- package/migrations/meta/0002_snapshot.json +4539 -0
- package/migrations/meta/0003_snapshot.json +4544 -0
- package/migrations/meta/0004_snapshot.json +4531 -0
- package/migrations/meta/0005_snapshot.json +4674 -0
- package/migrations/meta/0006_snapshot.json +4668 -0
- package/migrations/meta/0007_snapshot.json +4674 -0
- package/migrations/meta/0008_snapshot.json +4694 -0
- package/migrations/meta/0009_snapshot.json +4700 -0
- package/migrations/meta/0010_snapshot.json +4694 -0
- package/migrations/meta/0011_snapshot.json +4706 -0
- package/migrations/meta/0012_snapshot.json +4706 -0
- package/migrations/meta/0013_snapshot.json +4712 -0
- package/migrations/meta/0014_snapshot.json +4802 -0
- package/migrations/meta/0015_snapshot.json +5077 -0
- package/migrations/meta/_journal.json +118 -0
- package/package.json +68 -0
- package/src/app.ts +157 -0
- package/src/index.ts +113 -0
- package/src/lib/actor.ts +99 -0
- package/src/lib/changes.ts +43 -0
- package/src/lib/columns.ts +170 -0
- package/src/lib/config.ts +86 -0
- package/src/lib/database.ts +118 -0
- package/src/lib/dates.ts +18 -0
- package/src/lib/email.ts +65 -0
- package/src/lib/errors.ts +156 -0
- package/src/lib/http.ts +109 -0
- package/src/lib/ids.ts +61 -0
- package/src/lib/logger.ts +73 -0
- package/src/lib/moduleConfig.ts +65 -0
- package/src/lib/normalisation.ts +36 -0
- package/src/lib/pagination.ts +291 -0
- package/src/lib/passwords.ts +56 -0
- package/src/lib/search.ts +29 -0
- package/src/lib/secrets.ts +223 -0
- package/src/lib/timezones.ts +59 -0
- package/src/lib/tokens.ts +37 -0
- package/src/lib/url.ts +52 -0
- package/src/modules/activities/index.ts +43 -0
- package/src/modules/activities/recorder.ts +108 -0
- package/src/modules/activities/repository.ts +196 -0
- package/src/modules/activities/routes.ts +78 -0
- package/src/modules/activities/schema.ts +41 -0
- package/src/modules/activities/service.ts +93 -0
- package/src/modules/activities/tools.ts +40 -0
- package/src/modules/activities/wording.ts +168 -0
- package/src/modules/agent-tasks/catalog.ts +712 -0
- package/src/modules/agent-tasks/dispatch.ts +188 -0
- package/src/modules/agent-tasks/index.ts +79 -0
- package/src/modules/agent-tasks/prompt.ts +140 -0
- package/src/modules/agent-tasks/repository.ts +152 -0
- package/src/modules/agent-tasks/resolve.ts +704 -0
- package/src/modules/agent-tasks/routes.ts +260 -0
- package/src/modules/agent-tasks/schema.ts +57 -0
- package/src/modules/agent-tasks/service.ts +370 -0
- package/src/modules/agent-tasks/wire.ts +61 -0
- package/src/modules/api-keys/index.ts +34 -0
- package/src/modules/api-keys/keys.ts +59 -0
- package/src/modules/api-keys/repository.ts +82 -0
- package/src/modules/api-keys/routes.ts +83 -0
- package/src/modules/api-keys/schema.ts +28 -0
- package/src/modules/api-keys/service.ts +152 -0
- package/src/modules/attachedRecords.ts +85 -0
- package/src/modules/auth/actor.ts +17 -0
- package/src/modules/auth/credentials.ts +153 -0
- package/src/modules/auth/index.ts +49 -0
- package/src/modules/auth/preferences.ts +57 -0
- package/src/modules/auth/repository.ts +240 -0
- package/src/modules/auth/routes.ts +247 -0
- package/src/modules/auth/schema.ts +77 -0
- package/src/modules/auth/service.ts +441 -0
- package/src/modules/auth/session.ts +40 -0
- package/src/modules/companies/index.ts +43 -0
- package/src/modules/companies/repository.ts +185 -0
- package/src/modules/companies/routes.ts +170 -0
- package/src/modules/companies/schema.ts +66 -0
- package/src/modules/companies/service.ts +267 -0
- package/src/modules/companies/tools.ts +32 -0
- package/src/modules/core.ts +93 -0
- package/src/modules/crudTools.ts +226 -0
- package/src/modules/dashboard/attention.ts +67 -0
- package/src/modules/dashboard/index.ts +49 -0
- package/src/modules/dashboard/repository.ts +360 -0
- package/src/modules/dashboard/routes.ts +171 -0
- package/src/modules/dashboard/service.ts +449 -0
- package/src/modules/dashboard/tools.ts +39 -0
- package/src/modules/deals/index.ts +44 -0
- package/src/modules/deals/repository.ts +251 -0
- package/src/modules/deals/routes.ts +166 -0
- package/src/modules/deals/schema.ts +72 -0
- package/src/modules/deals/service.ts +433 -0
- package/src/modules/deals/tools.ts +39 -0
- package/src/modules/decisions/index.ts +40 -0
- package/src/modules/decisions/repository.ts +204 -0
- package/src/modules/decisions/routes.ts +184 -0
- package/src/modules/decisions/schema.ts +56 -0
- package/src/modules/decisions/service.ts +223 -0
- package/src/modules/decisions/tools.ts +38 -0
- package/src/modules/forms/embed.ts +274 -0
- package/src/modules/forms/fields.ts +206 -0
- package/src/modules/forms/index.ts +61 -0
- package/src/modules/forms/mapping.ts +222 -0
- package/src/modules/forms/publicRoutes.ts +92 -0
- package/src/modules/forms/repository.ts +223 -0
- package/src/modules/forms/routes.ts +276 -0
- package/src/modules/forms/schema.ts +135 -0
- package/src/modules/forms/service.ts +362 -0
- package/src/modules/forms/submission.ts +496 -0
- package/src/modules/forms/tools.ts +66 -0
- package/src/modules/handbook/index.ts +43 -0
- package/src/modules/handbook/repository.ts +173 -0
- package/src/modules/handbook/routes.ts +145 -0
- package/src/modules/handbook/schema.ts +43 -0
- package/src/modules/handbook/service.ts +399 -0
- package/src/modules/handbook/slugs.ts +54 -0
- package/src/modules/handbook/tools.ts +32 -0
- package/src/modules/handbook/tree.ts +158 -0
- package/src/modules/hiring/candidates.ts +391 -0
- package/src/modules/hiring/index.ts +55 -0
- package/src/modules/hiring/repository.ts +244 -0
- package/src/modules/hiring/roles.ts +174 -0
- package/src/modules/hiring/routes.ts +257 -0
- package/src/modules/hiring/schema.ts +93 -0
- package/src/modules/hiring/tools.ts +73 -0
- package/src/modules/import-export/csv.ts +180 -0
- package/src/modules/import-export/drafts.ts +182 -0
- package/src/modules/import-export/exportRows.ts +85 -0
- package/src/modules/import-export/index.ts +49 -0
- package/src/modules/import-export/mapping.ts +154 -0
- package/src/modules/import-export/plan.ts +311 -0
- package/src/modules/import-export/presets.ts +183 -0
- package/src/modules/import-export/repository.ts +603 -0
- package/src/modules/import-export/routes.ts +276 -0
- package/src/modules/import-export/schema.ts +142 -0
- package/src/modules/import-export/service.ts +842 -0
- package/src/modules/import-export/streams.ts +98 -0
- package/src/modules/import-export/tools.ts +153 -0
- package/src/modules/import-export/validation.ts +163 -0
- package/src/modules/import-export/writes.ts +365 -0
- package/src/modules/integrations/schema.ts +31 -0
- package/src/modules/mcp/index.ts +52 -0
- package/src/modules/mcp/protocol.ts +442 -0
- package/src/modules/mcp/router.ts +425 -0
- package/src/modules/notes/index.ts +43 -0
- package/src/modules/notes/repository.ts +130 -0
- package/src/modules/notes/routes.ts +170 -0
- package/src/modules/notes/schema.ts +42 -0
- package/src/modules/notes/service.ts +204 -0
- package/src/modules/notes/tools.ts +46 -0
- package/src/modules/opportunities/index.ts +44 -0
- package/src/modules/opportunities/repository.ts +157 -0
- package/src/modules/opportunities/routes.ts +152 -0
- package/src/modules/opportunities/schema.ts +47 -0
- package/src/modules/opportunities/service.ts +342 -0
- package/src/modules/opportunities/tools.ts +39 -0
- package/src/modules/partnerships/index.ts +44 -0
- package/src/modules/partnerships/repository.ts +274 -0
- package/src/modules/partnerships/routes.ts +170 -0
- package/src/modules/partnerships/schema.ts +65 -0
- package/src/modules/partnerships/service.ts +442 -0
- package/src/modules/partnerships/tools.ts +41 -0
- package/src/modules/people/index.ts +43 -0
- package/src/modules/people/repository.ts +167 -0
- package/src/modules/people/routes.ts +175 -0
- package/src/modules/people/schema.ts +89 -0
- package/src/modules/people/service.ts +284 -0
- package/src/modules/people/tools.ts +32 -0
- package/src/modules/pipelines/index.ts +43 -0
- package/src/modules/pipelines/repository.ts +116 -0
- package/src/modules/pipelines/routes.ts +157 -0
- package/src/modules/pipelines/schema.ts +37 -0
- package/src/modules/pipelines/service.ts +339 -0
- package/src/modules/pipelines/tools.ts +52 -0
- package/src/modules/plans/index.ts +39 -0
- package/src/modules/plans/repository.ts +174 -0
- package/src/modules/plans/routes.ts +212 -0
- package/src/modules/plans/schema.ts +45 -0
- package/src/modules/plans/service.ts +223 -0
- package/src/modules/plans/tools.ts +45 -0
- package/src/modules/positions/index.ts +42 -0
- package/src/modules/positions/repository.ts +136 -0
- package/src/modules/positions/routes.ts +97 -0
- package/src/modules/positions/schema.ts +42 -0
- package/src/modules/positions/service.ts +253 -0
- package/src/modules/positions/tools.ts +32 -0
- package/src/modules/raises/index.ts +44 -0
- package/src/modules/raises/repository.ts +254 -0
- package/src/modules/raises/routes.ts +160 -0
- package/src/modules/raises/schema.ts +66 -0
- package/src/modules/raises/service.ts +442 -0
- package/src/modules/raises/tools.ts +39 -0
- package/src/modules/recordTargets.ts +194 -0
- package/src/modules/references.ts +44 -0
- package/src/modules/reseal.ts +178 -0
- package/src/modules/search/index.ts +55 -0
- package/src/modules/search/query.ts +104 -0
- package/src/modules/search/repository.ts +388 -0
- package/src/modules/search/routes.ts +131 -0
- package/src/modules/search/service.ts +153 -0
- package/src/modules/search/tools.ts +60 -0
- package/src/modules/stagedRecords.ts +91 -0
- package/src/modules/webhooks/delivery.ts +349 -0
- package/src/modules/webhooks/index.ts +85 -0
- package/src/modules/webhooks/payloads.ts +84 -0
- package/src/modules/webhooks/repository.ts +244 -0
- package/src/modules/webhooks/routes.ts +240 -0
- package/src/modules/webhooks/schema.ts +78 -0
- package/src/modules/webhooks/service.ts +347 -0
- package/src/modules/webhooks/signing.ts +95 -0
- package/src/modules/webhooks/tools.ts +108 -0
- package/src/modules/webhooks/url.ts +21 -0
- package/src/modules/workspace/capabilities.ts +14 -0
- package/src/modules/workspace/idempotencyMiddleware.ts +207 -0
- package/src/modules/workspace/idempotencyRepository.ts +111 -0
- package/src/modules/workspace/index.ts +64 -0
- package/src/modules/workspace/repository.ts +420 -0
- package/src/modules/workspace/roles.ts +38 -0
- package/src/modules/workspace/routes.ts +255 -0
- package/src/modules/workspace/schema.ts +130 -0
- package/src/modules/workspace/service.ts +798 -0
- package/src/modules/workspace/starters.ts +69 -0
- package/src/modules/workspace/tools.ts +141 -0
- package/src/runtime/entitlements.ts +142 -0
- package/src/runtime/events.ts +185 -0
- package/src/runtime/migrate.ts +75 -0
- package/src/runtime/module.ts +147 -0
- package/src/runtime/moduleConfig.ts +68 -0
- package/src/runtime/order.ts +90 -0
- package/src/runtime/registry.ts +263 -0
- package/src/runtime/transaction.ts +80 -0
- package/src/schema/index.ts +30 -0
- package/src/testing/app.ts +79 -0
- package/src/testing/client.ts +118 -0
- package/src/testing/database.ts +106 -0
- package/src/testing/environment.ts +22 -0
- package/src/testing/fixtures.ts +70 -0
- package/src/testing/index.ts +13 -0
- package/src/testing/services.ts +67 -0
|
@@ -0,0 +1,842 @@
|
|
|
1
|
+
import {
|
|
2
|
+
IMPORT_PREVIEW_ROWS,
|
|
3
|
+
IMPORT_REPORTED_ERRORS,
|
|
4
|
+
MAX_IMPORT_ROWS,
|
|
5
|
+
OBJECT_COLUMNS,
|
|
6
|
+
SYNC_IMPORT_ROWS,
|
|
7
|
+
findMatchKey,
|
|
8
|
+
requiredColumns,
|
|
9
|
+
} from '@kelpie/schemas'
|
|
10
|
+
import type {
|
|
11
|
+
ImportColumnMap,
|
|
12
|
+
ImportConflictMode,
|
|
13
|
+
ImportCounts,
|
|
14
|
+
ImportJobStatus,
|
|
15
|
+
ImportObject,
|
|
16
|
+
ImportPreviewRow,
|
|
17
|
+
ImportRowError,
|
|
18
|
+
ImportSource,
|
|
19
|
+
MatchKeyOption,
|
|
20
|
+
} from '@kelpie/schemas'
|
|
21
|
+
|
|
22
|
+
import type { Database } from '../../lib/database.ts'
|
|
23
|
+
import { AppError, describeThrown } from '../../lib/errors.ts'
|
|
24
|
+
import type { IdFactory } from '../../lib/ids.ts'
|
|
25
|
+
import type { Logger } from '../../lib/logger.ts'
|
|
26
|
+
import { normaliseDomain, normaliseEmail } from '../../lib/normalisation.ts'
|
|
27
|
+
import type { Queryable, TransactionScope } from '../../runtime/transaction.ts'
|
|
28
|
+
import type { ActivityRecorder } from '../activities/recorder.ts'
|
|
29
|
+
import type { Actor } from '../auth/actor.ts'
|
|
30
|
+
import { requireWorkspaceId } from '../auth/actor.ts'
|
|
31
|
+
import { CsvFormatError, csvLine, fileDigest, parseCsv } from './csv.ts'
|
|
32
|
+
import type { CsvRow, ParsedCsv } from './csv.ts'
|
|
33
|
+
import { headersFor } from './exportRows.ts'
|
|
34
|
+
import { buildMatchKey, mapRow, splitList } from './mapping.ts'
|
|
35
|
+
import { applyWrite } from './writes.ts'
|
|
36
|
+
import { countPlans, planRow, planRows } from './plan.ts'
|
|
37
|
+
import type { ImportLookups, MappedRow, PlanContext, PlannedRow } from './plan.ts'
|
|
38
|
+
import { defaultColumnMap } from './presets.ts'
|
|
39
|
+
import * as repository from './repository.ts'
|
|
40
|
+
import type { ImportJobRecord, KeyedRecord } from './repository.ts'
|
|
41
|
+
import { streamExport } from './streams.ts'
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* CSV import jobs and CSV export, per `import-export.md`.
|
|
45
|
+
*
|
|
46
|
+
* The shape of a job is: upload, which stores the file; a dry run, which plans
|
|
47
|
+
* each line against the workspace and reports what would happen; then a commit,
|
|
48
|
+
* which applies the file while re-resolving every match. Re-resolving is the
|
|
49
|
+
* point — the workspace can change between the two calls, and lines earlier in
|
|
50
|
+
* the same file create records later lines must match against. It is also what
|
|
51
|
+
* makes a commit idempotent: run it twice and the second pass finds the records
|
|
52
|
+
* the first one made.
|
|
53
|
+
*
|
|
54
|
+
* Only the commit writes `import_job_rows`. A dry run plans from the stored file
|
|
55
|
+
* in memory and keeps nothing but its counts, its first errors and its preview,
|
|
56
|
+
* because a forecast nobody committed is not a thing to store ten thousand rows
|
|
57
|
+
* for. That is also why a corrected mapping — which is a new job over the same
|
|
58
|
+
* file — costs one row rather than the file again.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
export interface ImportExportDependencies {
|
|
62
|
+
readonly db: Database
|
|
63
|
+
readonly transaction: TransactionScope
|
|
64
|
+
readonly createId: IdFactory
|
|
65
|
+
readonly now: () => Date
|
|
66
|
+
readonly recordActivity: ActivityRecorder
|
|
67
|
+
readonly log: Logger
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** A job as the API returns one: the stored row minus tenancy, with its errors and preview. */
|
|
71
|
+
export interface ImportJobView {
|
|
72
|
+
readonly id: string
|
|
73
|
+
readonly source: ImportSource
|
|
74
|
+
readonly object: ImportObject
|
|
75
|
+
readonly status: string
|
|
76
|
+
readonly conflictMode: ImportConflictMode
|
|
77
|
+
readonly matchKey: string
|
|
78
|
+
readonly columnMap: ImportColumnMap
|
|
79
|
+
readonly sourceHeaders: readonly string[]
|
|
80
|
+
readonly fileName: string | null
|
|
81
|
+
readonly counts: ImportCounts
|
|
82
|
+
readonly errors: readonly ImportRowError[]
|
|
83
|
+
readonly preview: readonly ImportPreviewRow[]
|
|
84
|
+
readonly createdAt: Date
|
|
85
|
+
readonly updatedAt: Date
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface CreateImportJobInput {
|
|
89
|
+
readonly source: ImportSource
|
|
90
|
+
readonly object: ImportObject
|
|
91
|
+
readonly conflictMode: ImportConflictMode
|
|
92
|
+
readonly matchKeyId: string
|
|
93
|
+
/** Absent means "derive one from the source preset and the file's own headers". */
|
|
94
|
+
readonly columnMap: ImportColumnMap | undefined
|
|
95
|
+
readonly fileName: string | null
|
|
96
|
+
readonly csv: string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface ImportExportService {
|
|
100
|
+
createJob(actor: Actor, input: CreateImportJobInput): Promise<ImportJobView>
|
|
101
|
+
getJob(actor: Actor, id: string): Promise<ImportJobView>
|
|
102
|
+
/**
|
|
103
|
+
* @param csv The same file the dry run read. A job holds only its digest, so
|
|
104
|
+
* the caller brings the bytes back and a different file is refused.
|
|
105
|
+
*/
|
|
106
|
+
commit(actor: Actor, id: string, csv: string): Promise<ImportJobView>
|
|
107
|
+
deleteJob(actor: Actor, id: string): Promise<void>
|
|
108
|
+
/** CSV lines for a whole object, a page of records at a time. */
|
|
109
|
+
exportCsv(actor: Actor, object: ImportObject): AsyncGenerator<string>
|
|
110
|
+
templateCsv(object: ImportObject): string
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const EMPTY_COUNTS: ImportCounts = { total: 0, create: 0, update: 0, skip: 0, error: 0 }
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The statuses a job may be deleted in: everything except the two a background
|
|
117
|
+
* pass is working through.
|
|
118
|
+
*
|
|
119
|
+
* `pending` is here because a job stranded in it by a crash is exactly the
|
|
120
|
+
* unreachable garbage this delete exists to clear. `validating` and
|
|
121
|
+
* `committing` are not, because the detached pass holds the rows and would carry
|
|
122
|
+
* on writing records against a job that is no longer there.
|
|
123
|
+
*/
|
|
124
|
+
const DELETABLE_STATUSES: readonly ImportJobStatus[] = [
|
|
125
|
+
'pending',
|
|
126
|
+
'ready',
|
|
127
|
+
'completed',
|
|
128
|
+
'failed',
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
/** Rows committed between two writes of the job's running counts, so polling shows progress. */
|
|
132
|
+
const COMMIT_PROGRESS_INTERVAL = 100
|
|
133
|
+
|
|
134
|
+
/** The stored job minus tenancy, the failure reason, and the file digest. */
|
|
135
|
+
function toView(job: ImportJobRecord): ImportJobView {
|
|
136
|
+
const {
|
|
137
|
+
workspaceId: _workspaceId,
|
|
138
|
+
failureReason: _failureReason,
|
|
139
|
+
fileSha256: _fileSha256,
|
|
140
|
+
...rest
|
|
141
|
+
} = job
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
...rest,
|
|
145
|
+
source: rest.source as ImportSource,
|
|
146
|
+
object: rest.object as ImportObject,
|
|
147
|
+
conflictMode: rest.conflictMode as ImportConflictMode,
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** The distinct non-null values of one column across a file, for a lookup's `in (…)`. */
|
|
152
|
+
function distinct(values: readonly (string | null)[]): readonly string[] {
|
|
153
|
+
return [...new Set(values.filter((value): value is string => value !== null))]
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export function createImportExportService(
|
|
157
|
+
dependencies: ImportExportDependencies,
|
|
158
|
+
): ImportExportService {
|
|
159
|
+
async function requireJob(workspaceId: string, id: string): Promise<ImportJobRecord> {
|
|
160
|
+
const job = await repository.findJob(dependencies.db, workspaceId, id)
|
|
161
|
+
|
|
162
|
+
// A job in another workspace is indistinguishable from one that never
|
|
163
|
+
// existed, per `api.md`.
|
|
164
|
+
if (job === undefined) {
|
|
165
|
+
throw AppError.notFound('Import job not found')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return job
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function requireMatchKey(object: ImportObject, matchKeyId: string): MatchKeyOption {
|
|
172
|
+
const matchKey = findMatchKey(object, matchKeyId)
|
|
173
|
+
|
|
174
|
+
if (matchKey === undefined) {
|
|
175
|
+
throw AppError.validationFailed(`"${matchKeyId}" is not a match key for ${object}`, [
|
|
176
|
+
{ field: 'match_key', message: 'Use one of the keys this object declares' },
|
|
177
|
+
])
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return matchKey
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Checks a column map against the object it claims to describe and the file it
|
|
185
|
+
* will be applied to.
|
|
186
|
+
*
|
|
187
|
+
* All three problems are reported at once, and a mapping mistake is the one a
|
|
188
|
+
* caller is most likely to make twice.
|
|
189
|
+
*/
|
|
190
|
+
function requireUsableColumnMap(
|
|
191
|
+
object: ImportObject,
|
|
192
|
+
matchKey: MatchKeyOption,
|
|
193
|
+
columnMap: ImportColumnMap,
|
|
194
|
+
headers: readonly string[],
|
|
195
|
+
): void {
|
|
196
|
+
const known = new Set(OBJECT_COLUMNS[object].map((column) => column.key))
|
|
197
|
+
const present = new Set(headers)
|
|
198
|
+
const problems = [
|
|
199
|
+
...Object.keys(columnMap)
|
|
200
|
+
.filter((column) => !known.has(column))
|
|
201
|
+
.map((column) => ({
|
|
202
|
+
field: `column_map.${column}`,
|
|
203
|
+
message: `${object} has no column called "${column}"`,
|
|
204
|
+
})),
|
|
205
|
+
...Object.entries(columnMap)
|
|
206
|
+
.filter(([, header]) => header !== null && !present.has(header))
|
|
207
|
+
.map(([column, header]) => ({
|
|
208
|
+
field: `column_map.${column}`,
|
|
209
|
+
message: `The file has no column headed "${String(header)}"`,
|
|
210
|
+
})),
|
|
211
|
+
...requiredColumns(object, matchKey)
|
|
212
|
+
.filter((column) => (columnMap[column] ?? null) === null)
|
|
213
|
+
.map((column) => ({
|
|
214
|
+
field: `column_map.${column}`,
|
|
215
|
+
message: 'Required, and required columns must be mapped',
|
|
216
|
+
})),
|
|
217
|
+
]
|
|
218
|
+
|
|
219
|
+
if (problems.length > 0) {
|
|
220
|
+
throw AppError.validationFailed('That column map cannot read this file', problems)
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* The stored records that already hold any of the match keys this file uses.
|
|
226
|
+
*
|
|
227
|
+
* Both sides of a comparison go through `buildMatchKey`, so a row and the
|
|
228
|
+
* record it should match reduce to the same string by construction rather than
|
|
229
|
+
* by two implementations agreeing.
|
|
230
|
+
*/
|
|
231
|
+
async function findExistingKeys(
|
|
232
|
+
db: Queryable,
|
|
233
|
+
workspaceId: string,
|
|
234
|
+
object: ImportObject,
|
|
235
|
+
matchKey: MatchKeyOption,
|
|
236
|
+
rows: readonly MappedRow[],
|
|
237
|
+
): Promise<ReadonlyMap<string, string>> {
|
|
238
|
+
const column = (name: string): readonly string[] =>
|
|
239
|
+
distinct(rows.map((row) => (row.mapped[name] ?? '').trim() || null))
|
|
240
|
+
const emails = distinct(rows.map((row) => normaliseEmail(row.mapped.person_email ?? '')))
|
|
241
|
+
const domains = distinct(rows.map((row) => normaliseDomain(row.mapped.company_domain ?? '')))
|
|
242
|
+
|
|
243
|
+
const records: readonly KeyedRecord[] = await (async (): Promise<readonly KeyedRecord[]> => {
|
|
244
|
+
switch (object) {
|
|
245
|
+
case 'companies':
|
|
246
|
+
return repository.findCompanyKeys(
|
|
247
|
+
db,
|
|
248
|
+
workspaceId,
|
|
249
|
+
distinct(rows.map((row) => normaliseDomain(row.mapped.domain ?? ''))),
|
|
250
|
+
matchKey.id === 'name' ? column('name').map((name) => name.toLowerCase()) : [],
|
|
251
|
+
)
|
|
252
|
+
case 'people':
|
|
253
|
+
return repository.findPeopleKeys(
|
|
254
|
+
db,
|
|
255
|
+
workspaceId,
|
|
256
|
+
distinct(rows.map((row) => normaliseEmail(row.mapped.email ?? ''))),
|
|
257
|
+
)
|
|
258
|
+
case 'positions':
|
|
259
|
+
return repository.findPositionKeys(db, workspaceId, emails)
|
|
260
|
+
case 'deals':
|
|
261
|
+
return matchKey.id === 'external_id'
|
|
262
|
+
? repository.findDealKeysByExternalId(db, workspaceId, column('external_id'))
|
|
263
|
+
: repository.findDealKeysByCompany(db, workspaceId, domains)
|
|
264
|
+
}
|
|
265
|
+
})()
|
|
266
|
+
|
|
267
|
+
const keys = new Map<string, string>()
|
|
268
|
+
|
|
269
|
+
for (const record of records) {
|
|
270
|
+
const key = buildMatchKey(matchKey, record.parts)
|
|
271
|
+
|
|
272
|
+
// First writer wins, so a workspace holding two records under one key
|
|
273
|
+
// matches the same one every time rather than following whichever the
|
|
274
|
+
// planner saw last.
|
|
275
|
+
if (key !== null && !keys.has(key)) {
|
|
276
|
+
keys.set(key, record.id)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return keys
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/** The references a plan resolves: people, companies, members, and deal stages. */
|
|
284
|
+
async function buildLookups(
|
|
285
|
+
db: Queryable,
|
|
286
|
+
workspaceId: string,
|
|
287
|
+
object: ImportObject,
|
|
288
|
+
matchKey: MatchKeyOption,
|
|
289
|
+
rows: readonly MappedRow[],
|
|
290
|
+
): Promise<ImportLookups> {
|
|
291
|
+
const existing = await findExistingKeys(db, workspaceId, object, matchKey, rows)
|
|
292
|
+
|
|
293
|
+
if (object === 'companies' || object === 'people') {
|
|
294
|
+
return {
|
|
295
|
+
existing,
|
|
296
|
+
personIdByEmail: new Map(),
|
|
297
|
+
companyIdByDomain: new Map(),
|
|
298
|
+
memberIdByEmail: new Map(),
|
|
299
|
+
dealStageIdByName: new Map(),
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const emails = distinct([
|
|
304
|
+
...rows.map((row) => normaliseEmail(row.mapped.person_email ?? '')),
|
|
305
|
+
...rows.flatMap((row) =>
|
|
306
|
+
splitList(row.mapped.person_emails).map((address) => normaliseEmail(address)),
|
|
307
|
+
),
|
|
308
|
+
])
|
|
309
|
+
const domains = distinct(rows.map((row) => normaliseDomain(row.mapped.company_domain ?? '')))
|
|
310
|
+
const [peopleRows, companyRows] = await Promise.all([
|
|
311
|
+
repository.findPersonIdsByEmail(db, workspaceId, emails),
|
|
312
|
+
repository.findCompanyIdsByDomain(db, workspaceId, domains),
|
|
313
|
+
])
|
|
314
|
+
|
|
315
|
+
if (object === 'positions') {
|
|
316
|
+
return {
|
|
317
|
+
existing,
|
|
318
|
+
personIdByEmail: new Map(
|
|
319
|
+
peopleRows.flatMap((row) => (row.email === null ? [] : [[row.email, row.id] as const])),
|
|
320
|
+
),
|
|
321
|
+
companyIdByDomain: new Map(
|
|
322
|
+
companyRows.flatMap((row) => (row.domain === null ? [] : [[row.domain, row.id] as const])),
|
|
323
|
+
),
|
|
324
|
+
memberIdByEmail: new Map(),
|
|
325
|
+
dealStageIdByName: new Map(),
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const [members, stages] = await Promise.all([
|
|
330
|
+
repository.listMemberEmails(db, workspaceId),
|
|
331
|
+
repository.listDealStages(db, workspaceId),
|
|
332
|
+
])
|
|
333
|
+
|
|
334
|
+
// A stage answers to its slug and to its label. The slug is the stable one
|
|
335
|
+
// an export writes; the label is what a person typed into the spreadsheet.
|
|
336
|
+
const stagesByName = new Map<string, string>()
|
|
337
|
+
|
|
338
|
+
for (const stage of stages) {
|
|
339
|
+
stagesByName.set(stage.slug.toLowerCase(), stage.id)
|
|
340
|
+
stagesByName.set(stage.label.toLowerCase(), stage.id)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return {
|
|
344
|
+
existing,
|
|
345
|
+
personIdByEmail: new Map(
|
|
346
|
+
peopleRows.flatMap((row) => (row.email === null ? [] : [[row.email, row.id] as const])),
|
|
347
|
+
),
|
|
348
|
+
companyIdByDomain: new Map(
|
|
349
|
+
companyRows.flatMap((row) => (row.domain === null ? [] : [[row.domain, row.id] as const])),
|
|
350
|
+
),
|
|
351
|
+
memberIdByEmail: new Map(members.map((member) => [member.email.toLowerCase(), member.id])),
|
|
352
|
+
dealStageIdByName: stagesByName,
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function contextFor(job: ImportJobRecord, lookups: ImportLookups): PlanContext {
|
|
357
|
+
return {
|
|
358
|
+
object: job.object as ImportObject,
|
|
359
|
+
matchKey: requireMatchKey(job.object as ImportObject, job.matchKey),
|
|
360
|
+
conflictMode: job.conflictMode as ImportConflictMode,
|
|
361
|
+
lookups,
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/** A parsed file, mapped to Kelpie columns through the job's own column map. */
|
|
366
|
+
function readFile(
|
|
367
|
+
job: ImportJobRecord,
|
|
368
|
+
parsed: ParsedCsv,
|
|
369
|
+
): { rows: MappedRow[]; values: Map<number, CsvRow> } {
|
|
370
|
+
return {
|
|
371
|
+
rows: parsed.rows.map((row) => ({ row: row.number, mapped: mapRow(row.values, job.columnMap) })),
|
|
372
|
+
values: new Map(parsed.rows.map((row) => [row.number, row])),
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Checks a file handed back at commit against the one the dry run forecast.
|
|
378
|
+
*
|
|
379
|
+
* The counts a caller approved describe one particular file. Without this the
|
|
380
|
+
* commit would apply whatever arrived and report it under a forecast taken
|
|
381
|
+
* from something else.
|
|
382
|
+
*
|
|
383
|
+
* @throws AppError 409 when it is a different file, or when the job predates
|
|
384
|
+
* the digest and there is nothing to compare against.
|
|
385
|
+
*/
|
|
386
|
+
function requireForecastFile(job: ImportJobRecord, csv: string): void {
|
|
387
|
+
if (job.fileSha256 === null) {
|
|
388
|
+
throw AppError.conflict('This job was created before its file was fingerprinted', [
|
|
389
|
+
{ field: 'file', message: 'Upload the file again as a new job' },
|
|
390
|
+
])
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
if (fileDigest(csv) !== job.fileSha256) {
|
|
394
|
+
throw AppError.conflict('That is not the file this job dry-ran', [
|
|
395
|
+
{
|
|
396
|
+
field: 'file',
|
|
397
|
+
message: 'Commit the file the dry run read, or upload this one as a new job',
|
|
398
|
+
},
|
|
399
|
+
])
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
function toOutcome(planned: PlannedRow): repository.RowOutcome {
|
|
404
|
+
return {
|
|
405
|
+
rowNumber: planned.row,
|
|
406
|
+
action: planned.plan.action,
|
|
407
|
+
errors: planned.plan.action === 'error' ? planned.plan.errors : [],
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* The first errors and the first preview rows, as a caller reads them off a
|
|
413
|
+
* job.
|
|
414
|
+
*
|
|
415
|
+
* Takes outcomes rather than plans, because the dry run and the commit produce
|
|
416
|
+
* the same three facts about a line and the job reports whichever ran last.
|
|
417
|
+
*/
|
|
418
|
+
function reportOf(
|
|
419
|
+
outcomes: readonly repository.RowOutcome[],
|
|
420
|
+
mapped: readonly MappedRow[],
|
|
421
|
+
): { errors: readonly ImportRowError[]; preview: readonly ImportPreviewRow[] } {
|
|
422
|
+
const byRow = new Map(mapped.map((row) => [row.row, row.mapped]))
|
|
423
|
+
|
|
424
|
+
return {
|
|
425
|
+
errors: outcomes
|
|
426
|
+
.filter((outcome) => outcome.action === 'error')
|
|
427
|
+
.slice(0, IMPORT_REPORTED_ERRORS)
|
|
428
|
+
.flatMap((outcome) =>
|
|
429
|
+
outcome.errors.map((problem) => ({
|
|
430
|
+
row: outcome.rowNumber,
|
|
431
|
+
field: problem.field,
|
|
432
|
+
message: problem.message,
|
|
433
|
+
})),
|
|
434
|
+
),
|
|
435
|
+
preview: outcomes.slice(0, IMPORT_PREVIEW_ROWS).map((outcome) => ({
|
|
436
|
+
row: outcome.rowNumber,
|
|
437
|
+
action: outcome.action,
|
|
438
|
+
values: byRow.get(outcome.rowNumber) ?? {},
|
|
439
|
+
})),
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Plans every line of a job's file and records the forecast on the job.
|
|
445
|
+
*
|
|
446
|
+
* Writes no `import_job_rows`: a dry run is a forecast, and the three things a
|
|
447
|
+
* caller reads off it are the counts, the first errors and the preview. Runs
|
|
448
|
+
* inside the request for a small file and detached for a large one, which is
|
|
449
|
+
* the only difference between the two paths.
|
|
450
|
+
*
|
|
451
|
+
* Takes the parse rather than reading it back, because the job does not hold
|
|
452
|
+
* the file. The detached path closes over it for as long as it runs, which is
|
|
453
|
+
* the same lifetime the request would have had.
|
|
454
|
+
*/
|
|
455
|
+
async function runDryRun(workspaceId: string, jobId: string, parsed: ParsedCsv): Promise<void> {
|
|
456
|
+
const job = await requireJob(workspaceId, jobId)
|
|
457
|
+
const { rows } = readFile(job, parsed)
|
|
458
|
+
const lookups = await buildLookups(
|
|
459
|
+
dependencies.db,
|
|
460
|
+
workspaceId,
|
|
461
|
+
job.object as ImportObject,
|
|
462
|
+
requireMatchKey(job.object as ImportObject, job.matchKey),
|
|
463
|
+
rows,
|
|
464
|
+
)
|
|
465
|
+
const planned = planRows(contextFor(job, lookups), rows)
|
|
466
|
+
|
|
467
|
+
await repository.updateJob(dependencies.db, workspaceId, jobId, {
|
|
468
|
+
status: 'ready',
|
|
469
|
+
counts: countPlans(planned),
|
|
470
|
+
...reportOf(planned.map(toOutcome), rows),
|
|
471
|
+
updatedAt: dependencies.now(),
|
|
472
|
+
})
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Marks a job failed with the reason.
|
|
477
|
+
*
|
|
478
|
+
* A background pass has nobody to throw to: the request that started it has
|
|
479
|
+
* already answered. The job is where the caller looks next, so that is where
|
|
480
|
+
* the failure has to land.
|
|
481
|
+
*/
|
|
482
|
+
async function failJob(workspaceId: string, jobId: string, error: unknown): Promise<void> {
|
|
483
|
+
const reason = describeThrown(error)
|
|
484
|
+
|
|
485
|
+
dependencies.log.error('import job failed', { jobId, error: reason })
|
|
486
|
+
|
|
487
|
+
await repository
|
|
488
|
+
.updateJob(dependencies.db, workspaceId, jobId, {
|
|
489
|
+
status: 'failed',
|
|
490
|
+
failureReason: reason,
|
|
491
|
+
updatedAt: dependencies.now(),
|
|
492
|
+
})
|
|
493
|
+
.catch((writeError: unknown) => {
|
|
494
|
+
dependencies.log.error('could not record an import failure', {
|
|
495
|
+
jobId,
|
|
496
|
+
error: describeThrown(writeError),
|
|
497
|
+
})
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Runs work detached from the request that asked for it.
|
|
503
|
+
*
|
|
504
|
+
* The same shape `runtime/transaction.ts` uses to publish events: not awaited,
|
|
505
|
+
* and a rejection is logged rather than lost. A crash between here and the
|
|
506
|
+
* final status leaves the job in its transient status with nothing to move it
|
|
507
|
+
* on — stated in the README, because there is no durable queue to fix it with.
|
|
508
|
+
*/
|
|
509
|
+
function detach(workspaceId: string, jobId: string, work: () => Promise<void>): void {
|
|
510
|
+
void work().catch((error: unknown) => failJob(workspaceId, jobId, error))
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/** Applies one line, in its own transaction, and returns what it did. */
|
|
514
|
+
async function commitRow(
|
|
515
|
+
workspaceId: string,
|
|
516
|
+
actor: Actor,
|
|
517
|
+
job: ImportJobRecord,
|
|
518
|
+
line: CsvRow,
|
|
519
|
+
): Promise<repository.RowOutcome> {
|
|
520
|
+
const object = job.object as ImportObject
|
|
521
|
+
const matchKey = requireMatchKey(object, job.matchKey)
|
|
522
|
+
const mapped = mapRow(line.values, job.columnMap)
|
|
523
|
+
const row: MappedRow = { row: line.number, mapped }
|
|
524
|
+
|
|
525
|
+
return dependencies.transaction(async ({ tx, events }) => {
|
|
526
|
+
// Resolved inside the transaction, against the rows this commit has
|
|
527
|
+
// already written. That is what makes a file listing one company twice
|
|
528
|
+
// create it once, and what lets an interrupted commit be re-run.
|
|
529
|
+
const lookups = await buildLookups(tx, workspaceId, object, matchKey, [row])
|
|
530
|
+
const plan = planRow(contextFor(job, lookups), mapped)
|
|
531
|
+
|
|
532
|
+
const outcome: repository.RowOutcome = {
|
|
533
|
+
rowNumber: line.number,
|
|
534
|
+
action: plan.action,
|
|
535
|
+
errors: plan.action === 'error' ? plan.errors : [],
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (plan.action !== 'error' && plan.action !== 'skip') {
|
|
539
|
+
const written = await applyWrite(
|
|
540
|
+
{
|
|
541
|
+
tx,
|
|
542
|
+
workspaceId,
|
|
543
|
+
createId: dependencies.createId,
|
|
544
|
+
now: dependencies.now(),
|
|
545
|
+
actor,
|
|
546
|
+
recordActivity: dependencies.recordActivity,
|
|
547
|
+
sourceName: job.fileName ?? 'a CSV import',
|
|
548
|
+
},
|
|
549
|
+
plan,
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
if (plan.action === 'create') {
|
|
553
|
+
events.emit('record.created', {
|
|
554
|
+
workspaceId,
|
|
555
|
+
objectType: written.objectType,
|
|
556
|
+
recordId: written.recordId,
|
|
557
|
+
})
|
|
558
|
+
} else if (written.changedFields.length > 0) {
|
|
559
|
+
// An update that moved nothing publishes nothing. Re-running the same
|
|
560
|
+
// file must not wake every consumer watching for a change.
|
|
561
|
+
events.emit('record.updated', {
|
|
562
|
+
workspaceId,
|
|
563
|
+
objectType: written.objectType,
|
|
564
|
+
recordId: written.recordId,
|
|
565
|
+
changedFields: written.changedFields,
|
|
566
|
+
})
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// In the same transaction as the record it wrote, so the account of the
|
|
571
|
+
// line and the record it made either both land or neither does.
|
|
572
|
+
await repository.recordRowOutcome(
|
|
573
|
+
tx,
|
|
574
|
+
workspaceId,
|
|
575
|
+
job.id,
|
|
576
|
+
line.values,
|
|
577
|
+
outcome,
|
|
578
|
+
dependencies.now(),
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
return outcome
|
|
582
|
+
})
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Applies every row of a job.
|
|
587
|
+
*
|
|
588
|
+
* One transaction per row rather than one per batch. A batch would be fewer
|
|
589
|
+
* round trips, and a single row hitting a unique constraint would abort the
|
|
590
|
+
* transaction it shares with ninety-nine others, turning one bad row into a
|
|
591
|
+
* hundred. Containment is worth the commits here: this already runs in the
|
|
592
|
+
* background for anything large.
|
|
593
|
+
*/
|
|
594
|
+
async function runCommit(
|
|
595
|
+
workspaceId: string,
|
|
596
|
+
actor: Actor,
|
|
597
|
+
jobId: string,
|
|
598
|
+
parsed: ParsedCsv,
|
|
599
|
+
): Promise<void> {
|
|
600
|
+
const job = await requireJob(workspaceId, jobId)
|
|
601
|
+
const { rows, values } = readFile(job, parsed)
|
|
602
|
+
const counts = { ...EMPTY_COUNTS, total: rows.length }
|
|
603
|
+
const outcomes: repository.RowOutcome[] = []
|
|
604
|
+
let sinceProgress = 0
|
|
605
|
+
|
|
606
|
+
for (const row of rows) {
|
|
607
|
+
const line = values.get(row.row)
|
|
608
|
+
|
|
609
|
+
if (line === undefined) {
|
|
610
|
+
throw new Error(`unreachable: line ${String(row.row)} is missing from its own parse`)
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// A line that throws is a row error, not the end of the import. The other
|
|
614
|
+
// nine thousand have nothing to do with it.
|
|
615
|
+
const outcome = await commitRow(workspaceId, actor, job, line).catch(
|
|
616
|
+
async (error: unknown): Promise<repository.RowOutcome> => {
|
|
617
|
+
const failure = {
|
|
618
|
+
rowNumber: row.row,
|
|
619
|
+
action: 'error' as const,
|
|
620
|
+
errors: [{ field: '', message: describeThrown(error) }],
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Its own statement: the transaction that would have carried this one
|
|
624
|
+
// is the one that just rolled back.
|
|
625
|
+
await repository.recordRowOutcome(
|
|
626
|
+
dependencies.db,
|
|
627
|
+
workspaceId,
|
|
628
|
+
jobId,
|
|
629
|
+
line.values,
|
|
630
|
+
failure,
|
|
631
|
+
dependencies.now(),
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
return failure
|
|
635
|
+
},
|
|
636
|
+
)
|
|
637
|
+
|
|
638
|
+
outcomes.push({ ...outcome })
|
|
639
|
+
counts[outcome.action] += 1
|
|
640
|
+
sinceProgress += 1
|
|
641
|
+
|
|
642
|
+
if (sinceProgress >= COMMIT_PROGRESS_INTERVAL) {
|
|
643
|
+
sinceProgress = 0
|
|
644
|
+
await repository.updateJob(dependencies.db, workspaceId, jobId, {
|
|
645
|
+
counts,
|
|
646
|
+
updatedAt: dependencies.now(),
|
|
647
|
+
})
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
await repository.updateJob(dependencies.db, workspaceId, jobId, {
|
|
652
|
+
status: 'completed',
|
|
653
|
+
counts,
|
|
654
|
+
// Replaced with what actually happened. A dry run's forecast and a
|
|
655
|
+
// commit's outcome can differ, and the job reports the later one.
|
|
656
|
+
...reportOf(outcomes, rows),
|
|
657
|
+
updatedAt: dependencies.now(),
|
|
658
|
+
})
|
|
659
|
+
|
|
660
|
+
await dependencies.transaction(({ events }) => {
|
|
661
|
+
events.emit('import.completed', { workspaceId, importJobId: jobId, object: job.object })
|
|
662
|
+
|
|
663
|
+
return Promise.resolve()
|
|
664
|
+
})
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* The job body.
|
|
669
|
+
*
|
|
670
|
+
* Everything a caller reads is on the job itself, so this is one row and no
|
|
671
|
+
* query over `import_job_rows`. A job with no pass behind it yet reports empty
|
|
672
|
+
* errors and an empty preview, which is what its columns default to.
|
|
673
|
+
*/
|
|
674
|
+
function viewOf(job: ImportJobRecord): ImportJobView {
|
|
675
|
+
return toView(job)
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
return {
|
|
679
|
+
async createJob(actor, input) {
|
|
680
|
+
const workspaceId = requireWorkspaceId(actor)
|
|
681
|
+
const parsed = ((): ReturnType<typeof parseCsv> => {
|
|
682
|
+
try {
|
|
683
|
+
return parseCsv(input.csv)
|
|
684
|
+
} catch (error: unknown) {
|
|
685
|
+
if (error instanceof CsvFormatError) {
|
|
686
|
+
throw AppError.validationFailed(error.message, [
|
|
687
|
+
{ field: 'file', message: error.message },
|
|
688
|
+
])
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
throw error
|
|
692
|
+
}
|
|
693
|
+
})()
|
|
694
|
+
|
|
695
|
+
if (parsed.rows.length > MAX_IMPORT_ROWS) {
|
|
696
|
+
throw AppError.validationFailed(
|
|
697
|
+
`A file may carry at most ${String(MAX_IMPORT_ROWS)} rows`,
|
|
698
|
+
[{ field: 'file', message: `This one has ${String(parsed.rows.length)}` }],
|
|
699
|
+
)
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const matchKey = requireMatchKey(input.object, input.matchKeyId)
|
|
703
|
+
const columnMap =
|
|
704
|
+
input.columnMap ?? defaultColumnMap(input.source, input.object, parsed.headers)
|
|
705
|
+
|
|
706
|
+
requireUsableColumnMap(input.object, matchKey, columnMap, parsed.headers)
|
|
707
|
+
|
|
708
|
+
const id = dependencies.createId('importJob')
|
|
709
|
+
const now = dependencies.now()
|
|
710
|
+
|
|
711
|
+
// One row, and no part of the file in it. A caller correcting a mapping
|
|
712
|
+
// over a ten thousand line file leaves one row per attempt rather than ten
|
|
713
|
+
// thousand rows or ten megabytes.
|
|
714
|
+
const job = await repository.insertJob(dependencies.db, {
|
|
715
|
+
id,
|
|
716
|
+
workspaceId,
|
|
717
|
+
source: input.source,
|
|
718
|
+
object: input.object,
|
|
719
|
+
status: 'pending',
|
|
720
|
+
conflictMode: input.conflictMode,
|
|
721
|
+
matchKey: matchKey.id,
|
|
722
|
+
columnMap,
|
|
723
|
+
sourceHeaders: parsed.headers,
|
|
724
|
+
counts: { ...EMPTY_COUNTS, total: parsed.rows.length },
|
|
725
|
+
errors: [],
|
|
726
|
+
preview: [],
|
|
727
|
+
fileSha256: fileDigest(input.csv),
|
|
728
|
+
fileName: input.fileName,
|
|
729
|
+
failureReason: null,
|
|
730
|
+
createdAt: now,
|
|
731
|
+
updatedAt: now,
|
|
732
|
+
})
|
|
733
|
+
|
|
734
|
+
if (parsed.rows.length <= SYNC_IMPORT_ROWS) {
|
|
735
|
+
await runDryRun(workspaceId, id, parsed)
|
|
736
|
+
|
|
737
|
+
return viewOf(await requireJob(workspaceId, id))
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
const validating = await repository.updateJob(dependencies.db, workspaceId, id, {
|
|
741
|
+
status: 'validating',
|
|
742
|
+
updatedAt: dependencies.now(),
|
|
743
|
+
})
|
|
744
|
+
|
|
745
|
+
detach(workspaceId, id, () => runDryRun(workspaceId, id, parsed))
|
|
746
|
+
|
|
747
|
+
return viewOf(validating ?? job)
|
|
748
|
+
},
|
|
749
|
+
|
|
750
|
+
async getJob(actor, id) {
|
|
751
|
+
return viewOf(await requireJob(requireWorkspaceId(actor), id))
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Commits a job that a dry run left `ready`, applying the file handed back.
|
|
756
|
+
*
|
|
757
|
+
* Re-committing a `completed` job answers with it and writes nothing, per
|
|
758
|
+
* `import-export.md`, and does not need the file to do so. Anything else is
|
|
759
|
+
* a conflict: a job still validating has no plan to apply, one already
|
|
760
|
+
* committing is being applied by somebody else, and a failed one has nothing
|
|
761
|
+
* to apply.
|
|
762
|
+
*/
|
|
763
|
+
async commit(actor, id, csv) {
|
|
764
|
+
const workspaceId = requireWorkspaceId(actor)
|
|
765
|
+
const job = await requireJob(workspaceId, id)
|
|
766
|
+
|
|
767
|
+
// Checked before the file, so a caller re-POSTing a finished job gets the
|
|
768
|
+
// documented no-op whether or not they still have it.
|
|
769
|
+
if (job.status === 'completed') {
|
|
770
|
+
return viewOf(job)
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
requireForecastFile(job, csv)
|
|
774
|
+
|
|
775
|
+
const parsed = parseCsv(csv)
|
|
776
|
+
|
|
777
|
+
// Compare-and-set rather than a check followed by a write: two commits
|
|
778
|
+
// arriving together both read `ready`, and only the one whose update
|
|
779
|
+
// matched a row may proceed.
|
|
780
|
+
const claimed = await repository.moveJobStatus(dependencies.db, workspaceId, id, 'ready', {
|
|
781
|
+
status: 'committing',
|
|
782
|
+
updatedAt: dependencies.now(),
|
|
783
|
+
})
|
|
784
|
+
|
|
785
|
+
if (claimed === undefined) {
|
|
786
|
+
throw AppError.conflict(`An import job in status "${job.status}" cannot be committed`, [
|
|
787
|
+
{ field: 'status', message: 'Only a job a dry run left ready can be committed' },
|
|
788
|
+
])
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
if (claimed.counts.total <= SYNC_IMPORT_ROWS) {
|
|
792
|
+
await runCommit(workspaceId, actor, id, parsed)
|
|
793
|
+
|
|
794
|
+
return viewOf(await requireJob(workspaceId, id))
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
detach(workspaceId, id, () => runCommit(workspaceId, actor, id, parsed))
|
|
798
|
+
|
|
799
|
+
return viewOf(claimed)
|
|
800
|
+
},
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Deletes a job and its stored rows.
|
|
804
|
+
*
|
|
805
|
+
* The delete carries the status predicate rather than checking first, so a
|
|
806
|
+
* commit arriving in between claims the job and this finds nothing to
|
|
807
|
+
* remove. Only then is the job read again, to answer with the reason: gone
|
|
808
|
+
* is a `404` and in-flight is a `409`, and one query on the happy path tells
|
|
809
|
+
* neither of those stories wrongly.
|
|
810
|
+
*/
|
|
811
|
+
async deleteJob(actor, id) {
|
|
812
|
+
const workspaceId = requireWorkspaceId(actor)
|
|
813
|
+
const removed = await repository.deleteJob(
|
|
814
|
+
dependencies.db,
|
|
815
|
+
workspaceId,
|
|
816
|
+
id,
|
|
817
|
+
DELETABLE_STATUSES,
|
|
818
|
+
)
|
|
819
|
+
|
|
820
|
+
if (removed > 0) {
|
|
821
|
+
return
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
const job = await requireJob(workspaceId, id)
|
|
825
|
+
|
|
826
|
+
throw AppError.conflict(`An import job in status "${job.status}" cannot be deleted`, [
|
|
827
|
+
{
|
|
828
|
+
field: 'status',
|
|
829
|
+
message: 'Wait for the pass working through it to finish, then delete it',
|
|
830
|
+
},
|
|
831
|
+
])
|
|
832
|
+
},
|
|
833
|
+
|
|
834
|
+
exportCsv(actor, object) {
|
|
835
|
+
return streamExport(dependencies.db, requireWorkspaceId(actor), object)
|
|
836
|
+
},
|
|
837
|
+
|
|
838
|
+
templateCsv(object) {
|
|
839
|
+
return csvLine(headersFor(object))
|
|
840
|
+
},
|
|
841
|
+
}
|
|
842
|
+
}
|