@kelpie/server 0.11.0 → 0.13.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.
Files changed (399) hide show
  1. package/dist/app.d.ts +13 -0
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +8 -1
  4. package/dist/app.js.map +1 -1
  5. package/dist/boot.d.ts.map +1 -1
  6. package/dist/boot.js +1 -0
  7. package/dist/boot.js.map +1 -1
  8. package/dist/index.d.ts +3 -3
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/apiKeyScopes.d.ts.map +1 -1
  13. package/dist/lib/apiKeyScopes.js +6 -0
  14. package/dist/lib/apiKeyScopes.js.map +1 -1
  15. package/dist/lib/columns.d.ts +6 -0
  16. package/dist/lib/columns.d.ts.map +1 -1
  17. package/dist/lib/columns.js +5 -3
  18. package/dist/lib/columns.js.map +1 -1
  19. package/dist/lib/config.d.ts +17 -0
  20. package/dist/lib/config.d.ts.map +1 -1
  21. package/dist/lib/config.js +3 -0
  22. package/dist/lib/config.js.map +1 -1
  23. package/dist/lib/egress.d.ts.map +1 -1
  24. package/dist/lib/egress.js +8 -4
  25. package/dist/lib/egress.js.map +1 -1
  26. package/dist/lib/errors.d.ts +18 -0
  27. package/dist/lib/errors.d.ts.map +1 -1
  28. package/dist/lib/errors.js +25 -0
  29. package/dist/lib/errors.js.map +1 -1
  30. package/dist/lib/ids.d.ts +11 -0
  31. package/dist/lib/ids.d.ts.map +1 -1
  32. package/dist/lib/ids.js +11 -0
  33. package/dist/lib/ids.js.map +1 -1
  34. package/dist/lib/kelpieConfigFile.d.ts +15 -1
  35. package/dist/lib/kelpieConfigFile.d.ts.map +1 -1
  36. package/dist/lib/kelpieConfigFile.js +33 -1
  37. package/dist/lib/kelpieConfigFile.js.map +1 -1
  38. package/dist/modules/agent-tasks/catalog.d.ts.map +1 -1
  39. package/dist/modules/agent-tasks/catalog.js +32 -1
  40. package/dist/modules/agent-tasks/catalog.js.map +1 -1
  41. package/dist/modules/agent-tasks/index.d.ts.map +1 -1
  42. package/dist/modules/agent-tasks/index.js +1 -0
  43. package/dist/modules/agent-tasks/index.js.map +1 -1
  44. package/dist/modules/agent-tasks/resolve.d.ts.map +1 -1
  45. package/dist/modules/agent-tasks/resolve.js +5 -0
  46. package/dist/modules/agent-tasks/resolve.js.map +1 -1
  47. package/dist/modules/agent-tasks/routes.d.ts +2 -0
  48. package/dist/modules/agent-tasks/routes.d.ts.map +1 -1
  49. package/dist/modules/attachedRecords.d.ts +22 -8
  50. package/dist/modules/attachedRecords.d.ts.map +1 -1
  51. package/dist/modules/attachedRecords.js +42 -5
  52. package/dist/modules/attachedRecords.js.map +1 -1
  53. package/dist/modules/auth/index.d.ts.map +1 -1
  54. package/dist/modules/auth/index.js +22 -4
  55. package/dist/modules/auth/index.js.map +1 -1
  56. package/dist/modules/auth/repository.d.ts +16 -1
  57. package/dist/modules/auth/repository.d.ts.map +1 -1
  58. package/dist/modules/auth/repository.js +21 -2
  59. package/dist/modules/auth/repository.js.map +1 -1
  60. package/dist/modules/auth/routes.d.ts.map +1 -1
  61. package/dist/modules/auth/routes.js +32 -6
  62. package/dist/modules/auth/routes.js.map +1 -1
  63. package/dist/modules/auth/schema.d.ts +18 -1
  64. package/dist/modules/auth/schema.d.ts.map +1 -1
  65. package/dist/modules/auth/schema.js +12 -1
  66. package/dist/modules/auth/schema.js.map +1 -1
  67. package/dist/modules/auth/service.d.ts +46 -0
  68. package/dist/modules/auth/service.d.ts.map +1 -1
  69. package/dist/modules/auth/service.js +167 -10
  70. package/dist/modules/auth/service.js.map +1 -1
  71. package/dist/modules/auth/session.d.ts +12 -0
  72. package/dist/modules/auth/session.d.ts.map +1 -1
  73. package/dist/modules/auth/session.js +12 -0
  74. package/dist/modules/auth/session.js.map +1 -1
  75. package/dist/modules/companies/repository.d.ts.map +1 -1
  76. package/dist/modules/companies/repository.js +1 -1
  77. package/dist/modules/companies/repository.js.map +1 -1
  78. package/dist/modules/companies/routes.d.ts +2 -4
  79. package/dist/modules/companies/routes.d.ts.map +1 -1
  80. package/dist/modules/companies/routes.js +6 -11
  81. package/dist/modules/companies/routes.js.map +1 -1
  82. package/dist/modules/companies/schema.d.ts +13 -28
  83. package/dist/modules/companies/schema.d.ts.map +1 -1
  84. package/dist/modules/companies/schema.js +2 -2
  85. package/dist/modules/companies/schema.js.map +1 -1
  86. package/dist/modules/companies/service.d.ts +2 -3
  87. package/dist/modules/companies/service.d.ts.map +1 -1
  88. package/dist/modules/companies/service.js +4 -7
  89. package/dist/modules/companies/service.js.map +1 -1
  90. package/dist/modules/core.d.ts.map +1 -1
  91. package/dist/modules/core.js +2 -0
  92. package/dist/modules/core.js.map +1 -1
  93. package/dist/modules/custom-fields/repository.d.ts.map +1 -1
  94. package/dist/modules/custom-fields/repository.js +2 -0
  95. package/dist/modules/custom-fields/repository.js.map +1 -1
  96. package/dist/modules/custom-fields/routes.d.ts +1 -0
  97. package/dist/modules/custom-fields/routes.d.ts.map +1 -1
  98. package/dist/modules/dashboard/index.d.ts.map +1 -1
  99. package/dist/modules/dashboard/index.js +1 -0
  100. package/dist/modules/dashboard/index.js.map +1 -1
  101. package/dist/modules/dashboard/repository.d.ts +13 -0
  102. package/dist/modules/dashboard/repository.d.ts.map +1 -1
  103. package/dist/modules/dashboard/repository.js +36 -0
  104. package/dist/modules/dashboard/repository.js.map +1 -1
  105. package/dist/modules/dashboard/routes.d.ts.map +1 -1
  106. package/dist/modules/dashboard/routes.js +13 -0
  107. package/dist/modules/dashboard/routes.js.map +1 -1
  108. package/dist/modules/dashboard/service.d.ts +11 -0
  109. package/dist/modules/dashboard/service.d.ts.map +1 -1
  110. package/dist/modules/dashboard/service.js +24 -1
  111. package/dist/modules/dashboard/service.js.map +1 -1
  112. package/dist/modules/decisions/repository.d.ts.map +1 -1
  113. package/dist/modules/decisions/repository.js +2 -0
  114. package/dist/modules/decisions/repository.js.map +1 -1
  115. package/dist/modules/decisions/routes.d.ts +2 -0
  116. package/dist/modules/decisions/routes.d.ts.map +1 -1
  117. package/dist/modules/events/attendances.d.ts +35 -0
  118. package/dist/modules/events/attendances.d.ts.map +1 -0
  119. package/dist/modules/events/attendances.js +157 -0
  120. package/dist/modules/events/attendances.js.map +1 -0
  121. package/dist/modules/events/catalog.d.ts +35 -0
  122. package/dist/modules/events/catalog.d.ts.map +1 -0
  123. package/dist/modules/events/catalog.js +11 -0
  124. package/dist/modules/events/catalog.js.map +1 -0
  125. package/dist/modules/events/index.d.ts +10 -0
  126. package/dist/modules/events/index.d.ts.map +1 -0
  127. package/dist/modules/events/index.js +47 -0
  128. package/dist/modules/events/index.js.map +1 -0
  129. package/dist/modules/events/repository.d.ts +67 -0
  130. package/dist/modules/events/repository.d.ts.map +1 -0
  131. package/dist/modules/events/repository.js +212 -0
  132. package/dist/modules/events/repository.js.map +1 -0
  133. package/dist/modules/events/routes.d.ts +136 -0
  134. package/dist/modules/events/routes.d.ts.map +1 -0
  135. package/dist/modules/events/routes.js +280 -0
  136. package/dist/modules/events/routes.js.map +1 -0
  137. package/dist/modules/events/schema.d.ts +626 -0
  138. package/dist/modules/events/schema.d.ts.map +1 -0
  139. package/dist/modules/events/schema.js +93 -0
  140. package/dist/modules/events/schema.js.map +1 -0
  141. package/dist/modules/events/service.d.ts +68 -0
  142. package/dist/modules/events/service.d.ts.map +1 -0
  143. package/dist/modules/events/service.js +262 -0
  144. package/dist/modules/events/service.js.map +1 -0
  145. package/dist/modules/events/tools.d.ts +8 -0
  146. package/dist/modules/events/tools.d.ts.map +1 -0
  147. package/dist/modules/events/tools.js +80 -0
  148. package/dist/modules/events/tools.js.map +1 -0
  149. package/dist/modules/forms/applySubmissionFields.d.ts.map +1 -1
  150. package/dist/modules/forms/applySubmissionFields.js +7 -5
  151. package/dist/modules/forms/applySubmissionFields.js.map +1 -1
  152. package/dist/modules/forms/fillAddresses.d.ts +4 -0
  153. package/dist/modules/forms/fillAddresses.d.ts.map +1 -0
  154. package/dist/modules/forms/fillAddresses.js +93 -0
  155. package/dist/modules/forms/fillAddresses.js.map +1 -0
  156. package/dist/modules/forms/repository.d.ts +2 -2
  157. package/dist/modules/forms/repository.d.ts.map +1 -1
  158. package/dist/modules/forms/repository.js.map +1 -1
  159. package/dist/modules/forms/routes.d.ts +2 -0
  160. package/dist/modules/forms/routes.d.ts.map +1 -1
  161. package/dist/modules/forms/routes.js +2 -2
  162. package/dist/modules/forms/routes.js.map +1 -1
  163. package/dist/modules/forms/schema.js +2 -2
  164. package/dist/modules/forms/schema.js.map +1 -1
  165. package/dist/modules/forms/service.js +2 -2
  166. package/dist/modules/forms/service.js.map +1 -1
  167. package/dist/modules/forms/submission.d.ts +1 -0
  168. package/dist/modules/forms/submission.d.ts.map +1 -1
  169. package/dist/modules/forms/submission.js +27 -4
  170. package/dist/modules/forms/submission.js.map +1 -1
  171. package/dist/modules/hiring/roles.d.ts.map +1 -1
  172. package/dist/modules/hiring/roles.js +2 -1
  173. package/dist/modules/hiring/roles.js.map +1 -1
  174. package/dist/modules/import-export/addresses.d.ts +22 -0
  175. package/dist/modules/import-export/addresses.d.ts.map +1 -0
  176. package/dist/modules/import-export/addresses.js +83 -0
  177. package/dist/modules/import-export/addresses.js.map +1 -0
  178. package/dist/modules/import-export/drafts.d.ts +3 -4
  179. package/dist/modules/import-export/drafts.d.ts.map +1 -1
  180. package/dist/modules/import-export/drafts.js +4 -5
  181. package/dist/modules/import-export/drafts.js.map +1 -1
  182. package/dist/modules/import-export/exportRows.d.ts.map +1 -1
  183. package/dist/modules/import-export/exportRows.js +3 -3
  184. package/dist/modules/import-export/exportRows.js.map +1 -1
  185. package/dist/modules/import-export/plan.d.ts.map +1 -1
  186. package/dist/modules/import-export/plan.js +17 -2
  187. package/dist/modules/import-export/plan.js.map +1 -1
  188. package/dist/modules/import-export/presets.d.ts.map +1 -1
  189. package/dist/modules/import-export/presets.js +52 -7
  190. package/dist/modules/import-export/presets.js.map +1 -1
  191. package/dist/modules/import-export/repository.d.ts +3 -4
  192. package/dist/modules/import-export/repository.d.ts.map +1 -1
  193. package/dist/modules/import-export/repository.js +2 -3
  194. package/dist/modules/import-export/repository.js.map +1 -1
  195. package/dist/modules/import-export/writes.d.ts.map +1 -1
  196. package/dist/modules/import-export/writes.js +8 -4
  197. package/dist/modules/import-export/writes.js.map +1 -1
  198. package/dist/modules/lists/routes.d.ts +4 -0
  199. package/dist/modules/lists/routes.d.ts.map +1 -1
  200. package/dist/modules/notes/routes.d.ts +2 -0
  201. package/dist/modules/notes/routes.d.ts.map +1 -1
  202. package/dist/modules/people/repository.d.ts.map +1 -1
  203. package/dist/modules/people/repository.js +1 -1
  204. package/dist/modules/people/repository.js.map +1 -1
  205. package/dist/modules/people/routes.d.ts +2 -2
  206. package/dist/modules/people/routes.js +6 -6
  207. package/dist/modules/people/routes.js.map +1 -1
  208. package/dist/modules/people/schema.d.ts +17 -14
  209. package/dist/modules/people/schema.d.ts.map +1 -1
  210. package/dist/modules/people/schema.js +6 -4
  211. package/dist/modules/people/schema.js.map +1 -1
  212. package/dist/modules/people/service.d.ts +2 -2
  213. package/dist/modules/people/service.d.ts.map +1 -1
  214. package/dist/modules/people/service.js +5 -4
  215. package/dist/modules/people/service.js.map +1 -1
  216. package/dist/modules/plans/repository.d.ts +2 -2
  217. package/dist/modules/plans/repository.d.ts.map +1 -1
  218. package/dist/modules/plans/routes.d.ts +1 -0
  219. package/dist/modules/plans/routes.d.ts.map +1 -1
  220. package/dist/modules/plans/routes.js +4 -4
  221. package/dist/modules/plans/routes.js.map +1 -1
  222. package/dist/modules/plans/schema.d.ts +2 -2
  223. package/dist/modules/plans/schema.d.ts.map +1 -1
  224. package/dist/modules/plans/schema.js +3 -3
  225. package/dist/modules/plans/schema.js.map +1 -1
  226. package/dist/modules/plans/service.d.ts +2 -2
  227. package/dist/modules/plans/service.d.ts.map +1 -1
  228. package/dist/modules/plans/service.js.map +1 -1
  229. package/dist/modules/plans/tools.js +2 -2
  230. package/dist/modules/plans/tools.js.map +1 -1
  231. package/dist/modules/recordTargets.d.ts.map +1 -1
  232. package/dist/modules/recordTargets.js +11 -0
  233. package/dist/modules/recordTargets.js.map +1 -1
  234. package/dist/modules/references.d.ts.map +1 -1
  235. package/dist/modules/references.js +2 -0
  236. package/dist/modules/references.js.map +1 -1
  237. package/dist/modules/sample-data/fixture.d.ts +26 -4
  238. package/dist/modules/sample-data/fixture.d.ts.map +1 -1
  239. package/dist/modules/sample-data/fixture.js +157 -23
  240. package/dist/modules/sample-data/fixture.js.map +1 -1
  241. package/dist/modules/sample-data/index.d.ts +5 -2
  242. package/dist/modules/sample-data/index.d.ts.map +1 -1
  243. package/dist/modules/sample-data/index.js +7 -2
  244. package/dist/modules/sample-data/index.js.map +1 -1
  245. package/dist/modules/sample-data/routes.d.ts.map +1 -1
  246. package/dist/modules/sample-data/routes.js +2 -0
  247. package/dist/modules/sample-data/routes.js.map +1 -1
  248. package/dist/modules/sample-data/service.d.ts +11 -3
  249. package/dist/modules/sample-data/service.d.ts.map +1 -1
  250. package/dist/modules/sample-data/service.js +452 -363
  251. package/dist/modules/sample-data/service.js.map +1 -1
  252. package/dist/modules/sample-data/tools.d.ts.map +1 -1
  253. package/dist/modules/sample-data/tools.js +4 -3
  254. package/dist/modules/sample-data/tools.js.map +1 -1
  255. package/dist/modules/search/index.d.ts +1 -1
  256. package/dist/modules/search/index.d.ts.map +1 -1
  257. package/dist/modules/search/index.js +2 -1
  258. package/dist/modules/search/index.js.map +1 -1
  259. package/dist/modules/search/repository.d.ts +1 -0
  260. package/dist/modules/search/repository.d.ts.map +1 -1
  261. package/dist/modules/search/repository.js +22 -0
  262. package/dist/modules/search/repository.js.map +1 -1
  263. package/dist/modules/search/service.d.ts +2 -2
  264. package/dist/modules/search/service.d.ts.map +1 -1
  265. package/dist/modules/search/service.js +4 -3
  266. package/dist/modules/search/service.js.map +1 -1
  267. package/dist/modules/smtp-email/index.d.ts +12 -4
  268. package/dist/modules/smtp-email/index.d.ts.map +1 -1
  269. package/dist/modules/smtp-email/index.js +25 -5
  270. package/dist/modules/smtp-email/index.js.map +1 -1
  271. package/dist/modules/workspace/repository.d.ts +2 -0
  272. package/dist/modules/workspace/repository.d.ts.map +1 -1
  273. package/dist/modules/workspace/repository.js +12 -0
  274. package/dist/modules/workspace/repository.js.map +1 -1
  275. package/dist/modules/workspace/routes.d.ts.map +1 -1
  276. package/dist/modules/workspace/routes.js +13 -0
  277. package/dist/modules/workspace/routes.js.map +1 -1
  278. package/dist/modules/workspace/service.d.ts +10 -0
  279. package/dist/modules/workspace/service.d.ts.map +1 -1
  280. package/dist/modules/workspace/service.js +34 -10
  281. package/dist/modules/workspace/service.js.map +1 -1
  282. package/dist/modules/workspace/starters.d.ts +17 -2
  283. package/dist/modules/workspace/starters.d.ts.map +1 -1
  284. package/dist/modules/workspace/starters.js +141 -14
  285. package/dist/modules/workspace/starters.js.map +1 -1
  286. package/dist/modules/workspace/workspaceAccessMiddleware.d.ts.map +1 -1
  287. package/dist/modules/workspace/workspaceAccessMiddleware.js +3 -4
  288. package/dist/modules/workspace/workspaceAccessMiddleware.js.map +1 -1
  289. package/dist/runtime/events.d.ts +1 -1
  290. package/dist/runtime/events.d.ts.map +1 -1
  291. package/dist/runtime/events.js +2 -0
  292. package/dist/runtime/events.js.map +1 -1
  293. package/dist/runtime/module.d.ts +71 -1
  294. package/dist/runtime/module.d.ts.map +1 -1
  295. package/dist/runtime/registry.d.ts.map +1 -1
  296. package/dist/runtime/registry.js +142 -9
  297. package/dist/runtime/registry.js.map +1 -1
  298. package/dist/schema/index.d.ts +1 -0
  299. package/dist/schema/index.d.ts.map +1 -1
  300. package/dist/schema/index.js +1 -0
  301. package/dist/schema/index.js.map +1 -1
  302. package/dist/testing/app.d.ts +8 -0
  303. package/dist/testing/app.d.ts.map +1 -1
  304. package/dist/testing/app.js +6 -1
  305. package/dist/testing/app.js.map +1 -1
  306. package/dist/testing/client.d.ts.map +1 -1
  307. package/dist/testing/client.js +9 -1
  308. package/dist/testing/client.js.map +1 -1
  309. package/migrations/0043_external_sign_in.sql +2 -0
  310. package/migrations/0044_events.sql +79 -0
  311. package/migrations/0045_addresses.sql +66 -0
  312. package/migrations/0046_drop_company_website.sql +66 -0
  313. package/migrations/meta/_journal.json +28 -0
  314. package/package.json +3 -3
  315. package/src/app.ts +25 -1
  316. package/src/boot.ts +1 -0
  317. package/src/index.ts +13 -1
  318. package/src/lib/apiKeyScopes.ts +6 -0
  319. package/src/lib/columns.ts +12 -3
  320. package/src/lib/config.ts +21 -0
  321. package/src/lib/egress.ts +8 -4
  322. package/src/lib/errors.ts +37 -0
  323. package/src/lib/ids.ts +11 -0
  324. package/src/lib/kelpieConfigFile.ts +69 -1
  325. package/src/modules/agent-tasks/catalog.ts +33 -1
  326. package/src/modules/agent-tasks/index.ts +1 -0
  327. package/src/modules/agent-tasks/resolve.ts +11 -0
  328. package/src/modules/attachedRecords.ts +85 -13
  329. package/src/modules/auth/index.ts +26 -4
  330. package/src/modules/auth/repository.ts +36 -4
  331. package/src/modules/auth/routes.ts +46 -9
  332. package/src/modules/auth/schema.ts +12 -1
  333. package/src/modules/auth/service.ts +261 -10
  334. package/src/modules/auth/session.ts +14 -0
  335. package/src/modules/companies/repository.ts +1 -0
  336. package/src/modules/companies/routes.ts +6 -11
  337. package/src/modules/companies/schema.ts +3 -3
  338. package/src/modules/companies/service.ts +6 -10
  339. package/src/modules/core.ts +2 -0
  340. package/src/modules/custom-fields/repository.ts +2 -0
  341. package/src/modules/dashboard/index.ts +1 -0
  342. package/src/modules/dashboard/repository.ts +64 -0
  343. package/src/modules/dashboard/routes.ts +15 -0
  344. package/src/modules/dashboard/service.ts +48 -0
  345. package/src/modules/decisions/repository.ts +2 -0
  346. package/src/modules/events/attendances.ts +245 -0
  347. package/src/modules/events/catalog.ts +36 -0
  348. package/src/modules/events/index.ts +54 -0
  349. package/src/modules/events/repository.ts +396 -0
  350. package/src/modules/events/routes.ts +405 -0
  351. package/src/modules/events/schema.ts +148 -0
  352. package/src/modules/events/service.ts +443 -0
  353. package/src/modules/events/tools.ts +118 -0
  354. package/src/modules/forms/applySubmissionFields.ts +7 -5
  355. package/src/modules/forms/fillAddresses.ts +185 -0
  356. package/src/modules/forms/repository.ts +3 -3
  357. package/src/modules/forms/routes.ts +2 -2
  358. package/src/modules/forms/schema.ts +2 -2
  359. package/src/modules/forms/service.ts +2 -2
  360. package/src/modules/forms/submission.ts +34 -4
  361. package/src/modules/hiring/roles.ts +2 -1
  362. package/src/modules/import-export/addresses.ts +150 -0
  363. package/src/modules/import-export/drafts.ts +7 -9
  364. package/src/modules/import-export/exportRows.ts +3 -3
  365. package/src/modules/import-export/plan.ts +30 -2
  366. package/src/modules/import-export/presets.ts +55 -7
  367. package/src/modules/import-export/repository.ts +5 -7
  368. package/src/modules/import-export/writes.ts +8 -4
  369. package/src/modules/people/repository.ts +1 -0
  370. package/src/modules/people/routes.ts +6 -6
  371. package/src/modules/people/schema.ts +7 -5
  372. package/src/modules/people/service.ts +7 -5
  373. package/src/modules/plans/repository.ts +2 -2
  374. package/src/modules/plans/routes.ts +6 -6
  375. package/src/modules/plans/schema.ts +4 -4
  376. package/src/modules/plans/service.ts +3 -3
  377. package/src/modules/plans/tools.ts +2 -2
  378. package/src/modules/recordTargets.ts +14 -0
  379. package/src/modules/references.ts +2 -0
  380. package/src/modules/sample-data/fixture.ts +208 -27
  381. package/src/modules/sample-data/index.ts +7 -2
  382. package/src/modules/sample-data/routes.ts +2 -0
  383. package/src/modules/sample-data/service.ts +166 -49
  384. package/src/modules/sample-data/tools.ts +4 -3
  385. package/src/modules/search/index.ts +2 -1
  386. package/src/modules/search/repository.ts +32 -1
  387. package/src/modules/search/service.ts +6 -4
  388. package/src/modules/smtp-email/index.ts +32 -10
  389. package/src/modules/workspace/repository.ts +18 -0
  390. package/src/modules/workspace/routes.ts +16 -0
  391. package/src/modules/workspace/service.ts +59 -14
  392. package/src/modules/workspace/starters.ts +275 -14
  393. package/src/modules/workspace/workspaceAccessMiddleware.ts +3 -4
  394. package/src/runtime/events.ts +2 -0
  395. package/src/runtime/module.ts +78 -1
  396. package/src/runtime/registry.ts +176 -8
  397. package/src/schema/index.ts +1 -0
  398. package/src/testing/app.ts +14 -1
  399. package/src/testing/client.ts +11 -1
@@ -9,6 +9,7 @@ import { activities } from '../activities/schema.ts'
9
9
  import { decisions } from '../decisions/schema.ts'
10
10
  import { deals } from '../deals/schema.ts'
11
11
  import { enquiries } from '../enquiries/schema.ts'
12
+ import { attendances, events } from '../events/schema.ts'
12
13
  import { notes } from '../notes/schema.ts'
13
14
  import { opportunities } from '../opportunities/schema.ts'
14
15
  import { partnerships } from '../partnerships/schema.ts'
@@ -242,6 +243,69 @@ export async function listPartnershipTouchpoints(
242
243
  )
243
244
  }
244
245
 
246
+ /** A scheduled Event whose start is inside `[from, to)`. */
247
+ export interface UpcomingEventRecord {
248
+ readonly id: string
249
+ readonly name: string
250
+ readonly startsAt: Date
251
+ readonly endsAt: Date
252
+ readonly format: string
253
+ readonly location: string
254
+ readonly attendeeCount: number
255
+ readonly ownerId: string | null
256
+ }
257
+
258
+ function upcomingEventConditions(workspaceId: string, from: Date, to: Date): (SQL | undefined)[] {
259
+ return [
260
+ eq(events.workspaceId, workspaceId),
261
+ eq(events.status, 'scheduled'),
262
+ gte(events.startsAt, from),
263
+ lt(events.startsAt, to),
264
+ ]
265
+ }
266
+
267
+ export async function countUpcomingEvents(
268
+ db: Queryable,
269
+ workspaceId: string,
270
+ from: Date,
271
+ to: Date,
272
+ ): Promise<number> {
273
+ const [row] = await db
274
+ .select({ total: count() })
275
+ .from(events)
276
+ .where(and(...upcomingEventConditions(workspaceId, from, to)))
277
+
278
+ return row?.total ?? 0
279
+ }
280
+
281
+ export async function listUpcomingEvents(
282
+ db: Queryable,
283
+ workspaceId: string,
284
+ from: Date,
285
+ to: Date,
286
+ limit: number,
287
+ ): Promise<readonly UpcomingEventRecord[]> {
288
+ const rows = await db
289
+ .select({
290
+ id: events.id,
291
+ name: events.name,
292
+ startsAt: events.startsAt,
293
+ endsAt: events.endsAt,
294
+ format: events.format,
295
+ location: events.location,
296
+ ownerId: events.ownerId,
297
+ attendeeCount: sql<number>`coalesce(count(${attendances.id}) filter (where ${attendances.status} <> 'cancelled'), 0)::int`,
298
+ })
299
+ .from(events)
300
+ .leftJoin(attendances, eq(attendances.eventId, events.id))
301
+ .where(and(...upcomingEventConditions(workspaceId, from, to)))
302
+ .groupBy(events.id)
303
+ .orderBy(asc(events.startsAt), asc(events.id))
304
+ .limit(limit)
305
+
306
+ return rows
307
+ }
308
+
245
309
  /**
246
310
  * The calendar day a contact happened on, in the workspace's zone.
247
311
  *
@@ -15,6 +15,7 @@ import type {
15
15
  SignalList,
16
16
  StaleContactSignal,
17
17
  TouchpointSignal,
18
+ UpcomingEventSignal,
18
19
  } from './service.ts'
19
20
 
20
21
  /**
@@ -83,6 +84,19 @@ function touchpointBody(touchpoint: TouchpointSignal): Record<string, unknown> {
83
84
  }
84
85
  }
85
86
 
87
+ function upcomingEventBody(event: UpcomingEventSignal): Record<string, unknown> {
88
+ return {
89
+ id: event.id,
90
+ name: event.name,
91
+ starts_at: event.startsAt.toISOString(),
92
+ ends_at: event.endsAt.toISOString(),
93
+ format: event.format,
94
+ location: event.location,
95
+ attendee_count: event.attendeeCount,
96
+ owner_id: event.ownerId,
97
+ }
98
+ }
99
+
86
100
  function staleContactBody(contact: StaleContactSignal): Record<string, unknown> {
87
101
  return {
88
102
  id: contact.id,
@@ -147,6 +161,7 @@ export function dashboardResponse(snapshot: DashboardSnapshot): Record<string, u
147
161
  overdue_plan_items: signalListBody(snapshot.overduePlanItems, planItemBody),
148
162
  due_soon_plan_items: signalListBody(snapshot.dueSoonPlanItems, planItemBody),
149
163
  partnership_touchpoints: signalListBody(snapshot.partnershipTouchpoints, touchpointBody),
164
+ upcoming_events: signalListBody(snapshot.upcomingEvents, upcomingEventBody),
150
165
  stale_contacts: signalListBody(snapshot.staleContacts, staleContactBody),
151
166
  recent_activity: snapshot.recentActivity.map(activityBody),
152
167
  recent_notes: snapshot.recentNotes.map(noteBody),
@@ -117,6 +117,17 @@ export interface DecisionSignal extends TargetRef {
117
117
  readonly dueAt: Date | null
118
118
  }
119
119
 
120
+ export interface UpcomingEventSignal {
121
+ readonly id: string
122
+ readonly name: string
123
+ readonly startsAt: Date
124
+ readonly endsAt: Date
125
+ readonly format: string
126
+ readonly location: string
127
+ readonly attendeeCount: number
128
+ readonly ownerId: string | null
129
+ }
130
+
120
131
  export interface DashboardSnapshot {
121
132
  readonly generatedAt: Date
122
133
  /** The day everything below was computed against, `YYYY-MM-DD`. */
@@ -129,6 +140,7 @@ export interface DashboardSnapshot {
129
140
  readonly overduePlanItems: SignalList<PlanItemSignal>
130
141
  readonly dueSoonPlanItems: SignalList<PlanItemSignal>
131
142
  readonly partnershipTouchpoints: SignalList<TouchpointSignal>
143
+ readonly upcomingEvents: SignalList<UpcomingEventSignal>
132
144
  readonly staleContacts: SignalList<StaleContactSignal>
133
145
  readonly recentActivity: readonly ActivitySignal[]
134
146
  readonly recentNotes: readonly NoteSignal[]
@@ -155,6 +167,10 @@ interface DayBounds {
155
167
  readonly through: string
156
168
  /** The first day a contact still counts as fresh. */
157
169
  readonly staleCutoff: string
170
+ /** Instant the upcoming Events window starts (now). */
171
+ readonly fromInstant: Date
172
+ /** Instant the upcoming Events window ends (now plus `UPCOMING_DAYS`). */
173
+ readonly throughInstant: Date
158
174
  }
159
175
 
160
176
  /** Everything read from the database, before any of it is named or shaped. */
@@ -163,6 +179,7 @@ interface SignalRows {
163
179
  readonly overduePlanItems: SignalList<repository.PlanItemRecord>
164
180
  readonly dueSoonPlanItems: SignalList<repository.PlanItemRecord>
165
181
  readonly partnershipTouchpoints: SignalList<repository.TouchpointRecord>
182
+ readonly upcomingEvents: SignalList<repository.UpcomingEventRecord>
166
183
  readonly staleContacts: SignalList<repository.StaleContactRecord>
167
184
  readonly recentActivity: readonly repository.ActivityRecord[]
168
185
  readonly recentNotes: readonly repository.NoteRecord[]
@@ -201,6 +218,19 @@ async function readTouchpoints(
201
218
  }
202
219
  }
203
220
 
221
+ async function readUpcomingEvents(
222
+ db: Database,
223
+ workspaceId: string,
224
+ from: Date,
225
+ to: Date,
226
+ limit: number,
227
+ ): Promise<SignalList<repository.UpcomingEventRecord>> {
228
+ return {
229
+ total: await repository.countUpcomingEvents(db, workspaceId, from, to),
230
+ items: await repository.listUpcomingEvents(db, workspaceId, from, to, limit),
231
+ }
232
+ }
233
+
204
234
  async function readStaleContacts(
205
235
  db: Database,
206
236
  workspaceId: string,
@@ -236,6 +266,7 @@ async function readSignals(
236
266
  overduePlanItems,
237
267
  dueSoonPlanItems,
238
268
  partnershipTouchpoints,
269
+ upcomingEvents,
239
270
  staleContacts,
240
271
  recentActivity,
241
272
  recentNotes,
@@ -245,6 +276,7 @@ async function readSignals(
245
276
  readPlanItems(db, workspaceId, { before: days.today }, limit),
246
277
  readPlanItems(db, workspaceId, { from: days.today, to: days.through }, limit),
247
278
  readTouchpoints(db, workspaceId, days.through, limit),
279
+ readUpcomingEvents(db, workspaceId, days.fromInstant, days.throughInstant, limit),
248
280
  readStaleContacts(db, workspaceId, timezone, days.staleCutoff, limit),
249
281
  repository.listRecentActivity(db, workspaceId, limit),
250
282
  repository.listRecentNotes(db, workspaceId, limit),
@@ -256,6 +288,7 @@ async function readSignals(
256
288
  overduePlanItems,
257
289
  dueSoonPlanItems,
258
290
  partnershipTouchpoints,
291
+ upcomingEvents,
259
292
  staleContacts,
260
293
  recentActivity,
261
294
  recentNotes,
@@ -376,6 +409,19 @@ function toSnapshot(
376
409
  overduePlanItems: toPlanItemSignal(rows.overduePlanItems, nameOf),
377
410
  dueSoonPlanItems: toPlanItemSignal(rows.dueSoonPlanItems, nameOf),
378
411
  partnershipTouchpoints: toTouchpointSignal(rows.partnershipTouchpoints, days.today),
412
+ upcomingEvents: {
413
+ total: rows.upcomingEvents.total,
414
+ items: rows.upcomingEvents.items.map((row) => ({
415
+ id: row.id,
416
+ name: row.name,
417
+ startsAt: row.startsAt,
418
+ endsAt: row.endsAt,
419
+ format: row.format,
420
+ location: row.location,
421
+ attendeeCount: row.attendeeCount,
422
+ ownerId: row.ownerId,
423
+ })),
424
+ },
379
425
  staleContacts: toStaleContactSignal(rows.staleContacts, days.today),
380
426
  recentActivity: rows.recentActivity.map((row) => ({
381
427
  id: row.id,
@@ -436,6 +482,8 @@ export function createDashboardService(dependencies: DashboardDependencies): Das
436
482
  today,
437
483
  through: upcomingEnd(today),
438
484
  staleCutoff: staleContactCutoff(today),
485
+ fromInstant: generatedAt,
486
+ throughInstant: new Date(generatedAt.getTime() + UPCOMING_DAYS * 24 * 60 * 60 * 1000),
439
487
  }
440
488
 
441
489
  const rows = await readSignals(dependencies.db, workspaceId, timezone, days, limit)
@@ -8,6 +8,7 @@ import type { Queryable } from '../../runtime/transaction.ts'
8
8
  import { companies } from '../companies/schema.ts'
9
9
  import { deals } from '../deals/schema.ts'
10
10
  import { enquiries } from '../enquiries/schema.ts'
11
+ import { events } from '../events/schema.ts'
11
12
  import { opportunities } from '../opportunities/schema.ts'
12
13
  import { partnerships } from '../partnerships/schema.ts'
13
14
  import { people } from '../people/schema.ts'
@@ -57,6 +58,7 @@ const NAMED_TARGET_TABLES = [
57
58
  { table: partnerships, id: partnerships.id, workspaceId: partnerships.workspaceId, name: partnerships.name },
58
59
  { table: raises, id: raises.id, workspaceId: raises.workspaceId, name: raises.name },
59
60
  { table: enquiries, id: enquiries.id, workspaceId: enquiries.workspaceId, name: enquiries.name },
61
+ { table: events, id: events.id, workspaceId: events.workspaceId, name: events.name },
60
62
  ]
61
63
 
62
64
  /**
@@ -0,0 +1,245 @@
1
+ import { ATTENDANCE_STATUS_LABELS } from '@kelpie/schemas'
2
+ import type { AttendanceSource, AttendanceStatus } from '@kelpie/schemas'
3
+
4
+ import { changedKeys } from '../../lib/changes.ts'
5
+ import { UNIQUE_VIOLATION, postgresErrorCode } from '../../lib/database.ts'
6
+ import type { Database } from '../../lib/database.ts'
7
+ import { AppError } from '../../lib/errors.ts'
8
+ import type { IdFactory } from '../../lib/ids.ts'
9
+ import { mapPage, readListWindow, toPage } from '../../lib/pagination.ts'
10
+ import type { ListQueryParameters, Page } from '../../lib/pagination.ts'
11
+ import { toEventActor } from '../../lib/actor.ts'
12
+ import type { TransactionScope } from '../../runtime/transaction.ts'
13
+ import type { ActivityRecorder } from '../activities/recorder.ts'
14
+ import { describeLink, describeUnlink, describeUpdate } from '../activities/wording.ts'
15
+ import type { FieldLabels } from '../activities/wording.ts'
16
+ import type { Actor } from '../auth/actor.ts'
17
+ import { requireWorkspaceId } from '../auth/actor.ts'
18
+ import { deleteRecordsAttachedTo } from '../attachedRecords.ts'
19
+ import * as personLinks from '../personLinks.ts'
20
+ import './catalog.ts'
21
+ import * as repository from './repository.ts'
22
+ import { ATTENDANCE_SORTS, DEFAULT_ATTENDANCE_SORT } from './repository.ts'
23
+ import type { AttendanceFilters, AttendanceRecord } from './repository.ts'
24
+
25
+ export interface AttendancesDependencies {
26
+ readonly db: Database
27
+ readonly transaction: TransactionScope
28
+ readonly createId: IdFactory
29
+ readonly now: () => Date
30
+ readonly recordActivity: ActivityRecorder
31
+ }
32
+
33
+ const ATTENDANCE_FIELD_LABELS: FieldLabels = {
34
+ status: 'Attendance status',
35
+ }
36
+
37
+ export type AttendanceView = Omit<AttendanceRecord, 'workspaceId'>
38
+
39
+ export interface CreateAttendanceInput {
40
+ readonly eventId: string
41
+ readonly personId: string
42
+ readonly status: AttendanceStatus
43
+ readonly source: AttendanceSource
44
+ }
45
+
46
+ export interface UpdateAttendanceInput {
47
+ readonly status?: AttendanceStatus | undefined
48
+ }
49
+
50
+ export interface AttendancesService {
51
+ list(
52
+ actor: Actor,
53
+ filters: AttendanceFilters,
54
+ query: ListQueryParameters,
55
+ ): Promise<Page<AttendanceView>>
56
+ get(actor: Actor, id: string): Promise<AttendanceView>
57
+ create(actor: Actor, input: CreateAttendanceInput): Promise<AttendanceView>
58
+ update(actor: Actor, id: string, changes: UpdateAttendanceInput): Promise<AttendanceView>
59
+ remove(actor: Actor, id: string): Promise<void>
60
+ }
61
+
62
+ function toView(record: AttendanceRecord): AttendanceView {
63
+ const { workspaceId: _workspaceId, ...view } = record
64
+
65
+ return view
66
+ }
67
+
68
+ function duplicateAttendance(): AppError {
69
+ return AppError.conflict('That person is already registered for that event', [
70
+ { field: 'person_id', message: 'Already registered for this event' },
71
+ ])
72
+ }
73
+
74
+ export function createAttendancesService(
75
+ dependencies: AttendancesDependencies,
76
+ ): AttendancesService {
77
+ async function require(workspaceId: string, id: string): Promise<AttendanceRecord> {
78
+ const row = await repository.findAttendance(dependencies.db, workspaceId, id)
79
+
80
+ if (row === undefined) {
81
+ throw AppError.notFound('Attendance not found')
82
+ }
83
+
84
+ return row
85
+ }
86
+
87
+ async function requireEvent(workspaceId: string, eventId: string): Promise<string> {
88
+ const event = await repository.findEvent(dependencies.db, workspaceId, eventId)
89
+
90
+ if (event === undefined) {
91
+ throw AppError.notFound('Event not found')
92
+ }
93
+
94
+ return event.name
95
+ }
96
+
97
+ async function requirePerson(workspaceId: string, personId: string): Promise<string> {
98
+ const named = await personLinks.findPeopleNamed(dependencies.db, workspaceId, [personId])
99
+ const name = named.get(personId)
100
+
101
+ if (name === undefined) {
102
+ throw AppError.notFound('Person not found')
103
+ }
104
+
105
+ return name
106
+ }
107
+
108
+ return {
109
+ async list(actor, filters, query) {
110
+ const workspaceId = requireWorkspaceId(actor)
111
+ const window = readListWindow(query, ATTENDANCE_SORTS, DEFAULT_ATTENDANCE_SORT)
112
+ const rows = await repository.listAttendances(dependencies.db, workspaceId, filters, window)
113
+
114
+ return mapPage(toPage(rows, window, (row) => row.id), toView)
115
+ },
116
+
117
+ async get(actor, id) {
118
+ return toView(await require(requireWorkspaceId(actor), id))
119
+ },
120
+
121
+ async create(actor, input) {
122
+ const workspaceId = requireWorkspaceId(actor)
123
+ const eventName = await requireEvent(workspaceId, input.eventId)
124
+ const personName = await requirePerson(workspaceId, input.personId)
125
+ const id = dependencies.createId('attendance')
126
+
127
+ return dependencies.transaction(
128
+ async ({ tx, events }) => {
129
+ let created: AttendanceRecord
130
+
131
+ try {
132
+ created = await repository.insertAttendance(tx, {
133
+ id,
134
+ workspaceId,
135
+ eventId: input.eventId,
136
+ personId: input.personId,
137
+ status: input.status,
138
+ source: input.source,
139
+ })
140
+ } catch (error: unknown) {
141
+ if (postgresErrorCode(error) === UNIQUE_VIOLATION) {
142
+ throw duplicateAttendance()
143
+ }
144
+
145
+ throw error
146
+ }
147
+
148
+ await dependencies.recordActivity(tx, workspaceId, actor, {
149
+ targetType: 'event',
150
+ targetId: input.eventId,
151
+ kind: 'linked',
152
+ ...describeLink('person', personName),
153
+ })
154
+ await dependencies.recordActivity(tx, workspaceId, actor, {
155
+ targetType: 'person',
156
+ targetId: input.personId,
157
+ kind: 'linked',
158
+ ...describeLink('event', eventName),
159
+ })
160
+
161
+ events.emit('events.attendance.created', { type: 'attendance', id }, {})
162
+
163
+ return toView(created)
164
+ },
165
+ { workspaceId, actor: toEventActor(actor) },
166
+ )
167
+ },
168
+
169
+ async update(actor, id, changes) {
170
+ const workspaceId = requireWorkspaceId(actor)
171
+ const existing = await require(workspaceId, id)
172
+ const columns: Partial<repository.AttendanceColumns> = {
173
+ ...(changes.status === undefined ? {} : { status: changes.status }),
174
+ }
175
+ const changed = changedKeys(existing, columns)
176
+
177
+ if (changed.length === 0) {
178
+ return toView(existing)
179
+ }
180
+
181
+ return dependencies.transaction(
182
+ async ({ tx, events }) => {
183
+ const updated = await repository.updateAttendance(tx, workspaceId, id, {
184
+ ...columns,
185
+ updatedAt: dependencies.now(),
186
+ })
187
+
188
+ if (updated === undefined) {
189
+ throw AppError.notFound('Attendance not found')
190
+ }
191
+
192
+ const before = {
193
+ status: ATTENDANCE_STATUS_LABELS[existing.status as AttendanceStatus],
194
+ }
195
+ const after = {
196
+ status:
197
+ ATTENDANCE_STATUS_LABELS[(columns.status as AttendanceStatus | undefined) ?? existing.status as AttendanceStatus],
198
+ }
199
+
200
+ await dependencies.recordActivity(tx, workspaceId, actor, {
201
+ targetType: 'attendance',
202
+ targetId: id,
203
+ kind: 'updated',
204
+ ...describeUpdate(changed, ATTENDANCE_FIELD_LABELS, before, after),
205
+ })
206
+
207
+ events.emit('events.attendance.updated', { type: 'attendance', id }, { changed })
208
+
209
+ return toView(updated)
210
+ },
211
+ { workspaceId, actor: toEventActor(actor) },
212
+ )
213
+ },
214
+
215
+ async remove(actor, id) {
216
+ const workspaceId = requireWorkspaceId(actor)
217
+ const existing = await require(workspaceId, id)
218
+ const eventName = await requireEvent(workspaceId, existing.eventId)
219
+ const personName = await requirePerson(workspaceId, existing.personId)
220
+
221
+ await dependencies.transaction(
222
+ async ({ tx, events }) => {
223
+ await deleteRecordsAttachedTo(tx, workspaceId, 'attendance', id)
224
+ await repository.deleteAttendance(tx, workspaceId, id)
225
+
226
+ await dependencies.recordActivity(tx, workspaceId, actor, {
227
+ targetType: 'event',
228
+ targetId: existing.eventId,
229
+ kind: 'unlinked',
230
+ ...describeUnlink('person', personName),
231
+ })
232
+ await dependencies.recordActivity(tx, workspaceId, actor, {
233
+ targetType: 'person',
234
+ targetId: existing.personId,
235
+ kind: 'unlinked',
236
+ ...describeUnlink('event', eventName),
237
+ })
238
+
239
+ events.emit('events.attendance.deleted', { type: 'attendance', id }, {})
240
+ },
241
+ { workspaceId, actor: toEventActor(actor) },
242
+ )
243
+ },
244
+ }
245
+ }
@@ -0,0 +1,36 @@
1
+ import { z } from 'zod'
2
+
3
+ import type { ModuleEventCatalog } from '../../runtime/module.ts'
4
+
5
+ /** Domain events published by the events module (CRM gatherings + attendances). */
6
+
7
+ export const crmEventsCatalog = {
8
+ 'events.event.created': z.object({}).strict(),
9
+ 'events.event.updated': z.object({ changed: z.array(z.string()).readonly() }),
10
+ 'events.event.deleted': z.object({}).strict(),
11
+ 'events.attendance.created': z.object({}).strict(),
12
+ 'events.attendance.updated': z.object({ changed: z.array(z.string()).readonly() }),
13
+ 'events.attendance.deleted': z.object({}).strict(),
14
+ } satisfies ModuleEventCatalog
15
+
16
+ export type CrmEventCreatedData = Record<string, never>
17
+ export interface CrmEventUpdatedData {
18
+ readonly changed: readonly string[]
19
+ }
20
+ export type CrmEventDeletedData = Record<string, never>
21
+ export type AttendanceCreatedData = Record<string, never>
22
+ export interface AttendanceUpdatedData {
23
+ readonly changed: readonly string[]
24
+ }
25
+ export type AttendanceDeletedData = Record<string, never>
26
+
27
+ declare module '../../runtime/events.ts' {
28
+ interface KelpieEventMap {
29
+ 'events.event.created': CrmEventCreatedData
30
+ 'events.event.updated': CrmEventUpdatedData
31
+ 'events.event.deleted': CrmEventDeletedData
32
+ 'events.attendance.created': AttendanceCreatedData
33
+ 'events.attendance.updated': AttendanceUpdatedData
34
+ 'events.attendance.deleted': AttendanceDeletedData
35
+ }
36
+ }
@@ -0,0 +1,54 @@
1
+ import type { KelpieModule } from '../../runtime/module.ts'
2
+ import { createActivityRecorder } from '../activities/index.ts'
3
+ import { createCustomFieldValues } from '../custom-fields/index.ts'
4
+ import { createAttendancesService } from './attendances.ts'
5
+ import { crmEventsCatalog } from './catalog.ts'
6
+ import { mountEventsRoutes } from './routes.ts'
7
+ import * as schema from './schema.ts'
8
+ import { createEventsService } from './service.ts'
9
+ import { registerEventsTools } from './tools.ts'
10
+
11
+ /**
12
+ * Events: dated gatherings, attendances, and Event-only associations.
13
+ *
14
+ * Requires people (attendees), activities (timeline), and custom-fields
15
+ * (workspace-defined attributes on the Event). Associations resolve other
16
+ * modules' tables directly, the way notes resolve polymorphic targets.
17
+ */
18
+ export function createEventsModule(migrationsDirectory: string): KelpieModule {
19
+ return {
20
+ id: 'events',
21
+ requires: ['people', 'activities', 'custom-fields'],
22
+ events: crmEventsCatalog,
23
+
24
+ register(context) {
25
+ const recordActivity = createActivityRecorder({
26
+ createId: context.createId,
27
+ now: context.now,
28
+ })
29
+ const shared = {
30
+ db: context.db,
31
+ transaction: context.transaction,
32
+ createId: context.createId,
33
+ now: context.now,
34
+ recordActivity,
35
+ }
36
+
37
+ context.schema(schema, migrationsDirectory)
38
+
39
+ const events = createEventsService({
40
+ ...shared,
41
+ customFields: createCustomFieldValues({ db: context.db }),
42
+ })
43
+ const attendances = createAttendancesService(shared)
44
+
45
+ context.routes((router) => {
46
+ mountEventsRoutes(router, { db: context.db, now: context.now, events, attendances })
47
+ })
48
+
49
+ registerEventsTools(context.mcp, { events, attendances })
50
+
51
+ return Promise.resolve()
52
+ },
53
+ }
54
+ }