vintasend 0.4.0 → 0.4.7

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 (284) hide show
  1. package/README.md +5 -0
  2. package/dist/examples/vintasend-medplum-example/.env.example +11 -0
  3. package/dist/examples/vintasend-medplum-example/IMPLEMENTATION_PLAN_FILE_ATTACHMENTS.md +597 -0
  4. package/dist/examples/vintasend-medplum-example/README.md +190 -0
  5. package/dist/examples/vintasend-medplum-example/TUTORIAL_EMAIL_NOTIFICATIONS.md +2596 -0
  6. package/dist/examples/vintasend-medplum-example/bots/handlers/send-pending-notifications-bot.ts +39 -0
  7. package/dist/examples/vintasend-medplum-example/bots/handlers/send-task-assignment-email.ts +41 -0
  8. package/dist/examples/vintasend-medplum-example/bots/handlers/task-due-soon-notification-bot.ts +86 -0
  9. package/dist/examples/vintasend-medplum-example/bots/index.ts +53 -0
  10. package/dist/examples/vintasend-medplum-example/bots/services/emails/schedule-task-due-soon-email.ts +84 -0
  11. package/dist/examples/vintasend-medplum-example/bots/services/emails/send-task-assignment-email.test.ts +388 -0
  12. package/dist/examples/vintasend-medplum-example/bots/services/emails/send-task-assignment-email.ts +113 -0
  13. package/dist/examples/vintasend-medplum-example/bots/shared/task-due-soon-helpers.ts +115 -0
  14. package/dist/examples/vintasend-medplum-example/bots/task-assignment-bot.ts +41 -0
  15. package/dist/examples/vintasend-medplum-example/compiled-notification-templates.json +6 -0
  16. package/dist/examples/vintasend-medplum-example/esbuild-script.mjs +71 -0
  17. package/dist/examples/vintasend-medplum-example/index.html +14 -0
  18. package/dist/examples/vintasend-medplum-example/lib/constants.ts +32 -0
  19. package/dist/examples/vintasend-medplum-example/lib/extensions.ts +1 -0
  20. package/dist/examples/vintasend-medplum-example/lib/file-upload.test.ts +389 -0
  21. package/dist/examples/vintasend-medplum-example/lib/file-upload.ts +222 -0
  22. package/dist/examples/vintasend-medplum-example/lib/medplum-singleton.ts +18 -0
  23. package/dist/examples/vintasend-medplum-example/lib/notification-service.test.ts +293 -0
  24. package/dist/examples/vintasend-medplum-example/lib/notification-service.ts +284 -0
  25. package/dist/examples/vintasend-medplum-example/lib/patients.ts +20 -0
  26. package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-assignment/body.html.pug +37 -0
  27. package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-assignment/subject.txt.pug +4 -0
  28. package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-due-soon/body.html.pug +34 -0
  29. package/dist/examples/vintasend-medplum-example/notification-templates/emails/task-due-soon/subject.txt.pug +4 -0
  30. package/dist/examples/vintasend-medplum-example/package.json +75 -0
  31. package/dist/examples/vintasend-medplum-example/plugins/gql-plugin.mjs +31 -0
  32. package/dist/examples/vintasend-medplum-example/postcss.config.mjs +21 -0
  33. package/dist/examples/vintasend-medplum-example/public/favicon.ico +0 -0
  34. package/dist/examples/vintasend-medplum-example/public/img/integrations/acuity.png +0 -0
  35. package/dist/examples/vintasend-medplum-example/public/img/integrations/auth0.png +0 -0
  36. package/dist/examples/vintasend-medplum-example/public/img/integrations/azure.png +0 -0
  37. package/dist/examples/vintasend-medplum-example/public/img/integrations/calcom.png +0 -0
  38. package/dist/examples/vintasend-medplum-example/public/img/integrations/candid.png +0 -0
  39. package/dist/examples/vintasend-medplum-example/public/img/integrations/claude.png +0 -0
  40. package/dist/examples/vintasend-medplum-example/public/img/integrations/datadog.png +0 -0
  41. package/dist/examples/vintasend-medplum-example/public/img/integrations/deepseek.png +0 -0
  42. package/dist/examples/vintasend-medplum-example/public/img/integrations/entra.png +0 -0
  43. package/dist/examples/vintasend-medplum-example/public/img/integrations/epic.png +0 -0
  44. package/dist/examples/vintasend-medplum-example/public/img/integrations/google.png +0 -0
  45. package/dist/examples/vintasend-medplum-example/public/img/integrations/healthgorilla.png +0 -0
  46. package/dist/examples/vintasend-medplum-example/public/img/integrations/healthie.png +0 -0
  47. package/dist/examples/vintasend-medplum-example/public/img/integrations/labcorp.png +0 -0
  48. package/dist/examples/vintasend-medplum-example/public/img/integrations/okta.png +0 -0
  49. package/dist/examples/vintasend-medplum-example/public/img/integrations/openai.png +0 -0
  50. package/dist/examples/vintasend-medplum-example/public/img/integrations/particle.png +0 -0
  51. package/dist/examples/vintasend-medplum-example/public/img/integrations/quest.png +0 -0
  52. package/dist/examples/vintasend-medplum-example/public/img/integrations/recaptcha.png +0 -0
  53. package/dist/examples/vintasend-medplum-example/public/img/integrations/snowflake.png +0 -0
  54. package/dist/examples/vintasend-medplum-example/public/img/integrations/stedi.png +0 -0
  55. package/dist/examples/vintasend-medplum-example/public/img/integrations/stripe.png +0 -0
  56. package/dist/examples/vintasend-medplum-example/public/img/integrations/sumo.png +0 -0
  57. package/dist/examples/vintasend-medplum-example/scripts/README.md +162 -0
  58. package/dist/examples/vintasend-medplum-example/scripts/client.ts +18 -0
  59. package/dist/examples/vintasend-medplum-example/scripts/deploy-bots.ts +171 -0
  60. package/dist/examples/vintasend-medplum-example/src/App.tsx +185 -0
  61. package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemList.test.tsx +350 -0
  62. package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemList.tsx +241 -0
  63. package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemPanel.test.tsx +616 -0
  64. package/dist/examples/vintasend-medplum-example/src/components/ChargeItem/ChargeItemPanel.tsx +138 -0
  65. package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionItem.test.tsx +92 -0
  66. package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionItem.tsx +47 -0
  67. package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionList.test.tsx +464 -0
  68. package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionList.tsx +186 -0
  69. package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionModal.test.tsx +80 -0
  70. package/dist/examples/vintasend-medplum-example/src/components/Conditions/ConditionModal.tsx +82 -0
  71. package/dist/examples/vintasend-medplum-example/src/components/DoseSpotIcon.test.tsx +100 -0
  72. package/dist/examples/vintasend-medplum-example/src/components/DoseSpotIcon.tsx +20 -0
  73. package/dist/examples/vintasend-medplum-example/src/components/IntegrationCard.module.css +3 -0
  74. package/dist/examples/vintasend-medplum-example/src/components/IntegrationCard.tsx +62 -0
  75. package/dist/examples/vintasend-medplum-example/src/components/MessageWithLinks.tsx +47 -0
  76. package/dist/examples/vintasend-medplum-example/src/components/PerformingLabInput.test.tsx +299 -0
  77. package/dist/examples/vintasend-medplum-example/src/components/PerformingLabInput.tsx +52 -0
  78. package/dist/examples/vintasend-medplum-example/src/components/ResourceFormWithRequiredProfile.tsx +82 -0
  79. package/dist/examples/vintasend-medplum-example/src/components/encounter/BillingTab.test.tsx +1016 -0
  80. package/dist/examples/vintasend-medplum-example/src/components/encounter/BillingTab.tsx +298 -0
  81. package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterChart.test.tsx +732 -0
  82. package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterChart.tsx +282 -0
  83. package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterHeader.test.tsx +268 -0
  84. package/dist/examples/vintasend-medplum-example/src/components/encounter/EncounterHeader.tsx +224 -0
  85. package/dist/examples/vintasend-medplum-example/src/components/encounter/SignAddendum.test.tsx +255 -0
  86. package/dist/examples/vintasend-medplum-example/src/components/encounter/SignAddendum.tsx +212 -0
  87. package/dist/examples/vintasend-medplum-example/src/components/encounter/SignLockDialog.test.tsx +120 -0
  88. package/dist/examples/vintasend-medplum-example/src/components/encounter/SignLockDialog.tsx +57 -0
  89. package/dist/examples/vintasend-medplum-example/src/components/encounter/VisitDetailsPanel.test.tsx +224 -0
  90. package/dist/examples/vintasend-medplum-example/src/components/encounter/VisitDetailsPanel.tsx +100 -0
  91. package/dist/examples/vintasend-medplum-example/src/components/labs/CoverageInput.test.tsx +431 -0
  92. package/dist/examples/vintasend-medplum-example/src/components/labs/CoverageInput.tsx +130 -0
  93. package/dist/examples/vintasend-medplum-example/src/components/labs/LabListItem.module.css +31 -0
  94. package/dist/examples/vintasend-medplum-example/src/components/labs/LabListItem.test.tsx +234 -0
  95. package/dist/examples/vintasend-medplum-example/src/components/labs/LabListItem.tsx +143 -0
  96. package/dist/examples/vintasend-medplum-example/src/components/labs/LabOrderDetails.module.css +11 -0
  97. package/dist/examples/vintasend-medplum-example/src/components/labs/LabOrderDetails.test.tsx +875 -0
  98. package/dist/examples/vintasend-medplum-example/src/components/labs/LabOrderDetails.tsx +943 -0
  99. package/dist/examples/vintasend-medplum-example/src/components/labs/LabResultDetails.test.tsx +413 -0
  100. package/dist/examples/vintasend-medplum-example/src/components/labs/LabResultDetails.tsx +203 -0
  101. package/dist/examples/vintasend-medplum-example/src/components/labs/LabSelectEmpty.tsx +22 -0
  102. package/dist/examples/vintasend-medplum-example/src/components/labs/README.md +104 -0
  103. package/dist/examples/vintasend-medplum-example/src/components/labs/TestMetadataCardInput.test.tsx +318 -0
  104. package/dist/examples/vintasend-medplum-example/src/components/labs/TestMetadataCardInput.tsx +87 -0
  105. package/dist/examples/vintasend-medplum-example/src/components/messages/ChatList.test.tsx +126 -0
  106. package/dist/examples/vintasend-medplum-example/src/components/messages/ChatList.tsx +38 -0
  107. package/dist/examples/vintasend-medplum-example/src/components/messages/ChatListItem.module.css +23 -0
  108. package/dist/examples/vintasend-medplum-example/src/components/messages/ChatListItem.test.tsx +167 -0
  109. package/dist/examples/vintasend-medplum-example/src/components/messages/ChatListItem.tsx +53 -0
  110. package/dist/examples/vintasend-medplum-example/src/components/messages/NewTopicDialog.test.tsx +94 -0
  111. package/dist/examples/vintasend-medplum-example/src/components/messages/NewTopicDialog.tsx +165 -0
  112. package/dist/examples/vintasend-medplum-example/src/components/messages/ParticipantFilter.module.css +8 -0
  113. package/dist/examples/vintasend-medplum-example/src/components/messages/ParticipantFilter.test.tsx +523 -0
  114. package/dist/examples/vintasend-medplum-example/src/components/messages/ParticipantFilter.tsx +230 -0
  115. package/dist/examples/vintasend-medplum-example/src/components/messages/ThreadInbox.module.css +23 -0
  116. package/dist/examples/vintasend-medplum-example/src/components/messages/ThreadInbox.test.tsx +567 -0
  117. package/dist/examples/vintasend-medplum-example/src/components/messages/ThreadInbox.tsx +358 -0
  118. package/dist/examples/vintasend-medplum-example/src/components/plandefinition/AddPlanDefinition.module.css +40 -0
  119. package/dist/examples/vintasend-medplum-example/src/components/plandefinition/AddPlanDefinition.tsx +257 -0
  120. package/dist/examples/vintasend-medplum-example/src/components/schedule/CreateVisit.module.css +7 -0
  121. package/dist/examples/vintasend-medplum-example/src/components/schedule/CreateVisit.test.tsx +279 -0
  122. package/dist/examples/vintasend-medplum-example/src/components/schedule/CreateVisit.tsx +156 -0
  123. package/dist/examples/vintasend-medplum-example/src/components/spaces/HistoryList.module.css +45 -0
  124. package/dist/examples/vintasend-medplum-example/src/components/spaces/HistoryList.test.tsx +90 -0
  125. package/dist/examples/vintasend-medplum-example/src/components/spaces/HistoryList.tsx +84 -0
  126. package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourceBox.module.css +26 -0
  127. package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourceBox.tsx +90 -0
  128. package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourcePanel.test.tsx +305 -0
  129. package/dist/examples/vintasend-medplum-example/src/components/spaces/ResourcePanel.tsx +46 -0
  130. package/dist/examples/vintasend-medplum-example/src/components/spaces/SpacesInbox.module.css +262 -0
  131. package/dist/examples/vintasend-medplum-example/src/components/spaces/SpacesInbox.test.tsx +622 -0
  132. package/dist/examples/vintasend-medplum-example/src/components/spaces/SpacesInbox.tsx +286 -0
  133. package/dist/examples/vintasend-medplum-example/src/components/tasks/NewTaskModal.tsx +275 -0
  134. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskAttachmentList.tsx +132 -0
  135. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskBoard.module.css +45 -0
  136. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskBoard.test.tsx +749 -0
  137. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskBoard.tsx +416 -0
  138. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailPanel.test.tsx +278 -0
  139. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailPanel.tsx +133 -0
  140. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailsModal.module.css +16 -0
  141. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailsModal.test.tsx +255 -0
  142. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskDetailsModal.tsx +203 -0
  143. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFileUpload.tsx +129 -0
  144. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFilterMenu.test.tsx +156 -0
  145. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFilterMenu.tsx +142 -0
  146. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskFilterMenu.utils.ts +28 -0
  147. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskInputNote.test.tsx +134 -0
  148. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskInputNote.tsx +250 -0
  149. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskListItem.module.css +23 -0
  150. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskListItem.test.tsx +149 -0
  151. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskListItem.tsx +53 -0
  152. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskNoteItem.test.tsx +68 -0
  153. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskNoteItem.tsx +46 -0
  154. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskProperties.test.tsx +555 -0
  155. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskProperties.tsx +170 -0
  156. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskSelectEmpty.test.tsx +32 -0
  157. package/dist/examples/vintasend-medplum-example/src/components/tasks/TaskSelectEmpty.tsx +34 -0
  158. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/SimpleTask.test.tsx +47 -0
  159. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/SimpleTask.tsx +29 -0
  160. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskPanel.test.tsx +285 -0
  161. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskPanel.tsx +129 -0
  162. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskQuestionnaireForm.test.tsx +455 -0
  163. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskQuestionnaireForm.tsx +167 -0
  164. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskServiceRequest.test.tsx +435 -0
  165. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskServiceRequest.tsx +116 -0
  166. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskStatusPanel.module.css +38 -0
  167. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskStatusPanel.test.tsx +200 -0
  168. package/dist/examples/vintasend-medplum-example/src/components/tasks/encounter/TaskStatusPanel.tsx +84 -0
  169. package/dist/examples/vintasend-medplum-example/src/components/utils.test.ts +176 -0
  170. package/dist/examples/vintasend-medplum-example/src/components/utils.ts +17 -0
  171. package/dist/examples/vintasend-medplum-example/src/config/constants.ts +3 -0
  172. package/dist/examples/vintasend-medplum-example/src/hooks/useDebouncedUpdateResource.test.tsx +166 -0
  173. package/dist/examples/vintasend-medplum-example/src/hooks/useDebouncedUpdateResource.ts +28 -0
  174. package/dist/examples/vintasend-medplum-example/src/hooks/useEncounter.test.tsx +94 -0
  175. package/dist/examples/vintasend-medplum-example/src/hooks/useEncounter.ts +11 -0
  176. package/dist/examples/vintasend-medplum-example/src/hooks/useEncounterChart.test.tsx +477 -0
  177. package/dist/examples/vintasend-medplum-example/src/hooks/useEncounterChart.ts +191 -0
  178. package/dist/examples/vintasend-medplum-example/src/hooks/usePatient.test.tsx +100 -0
  179. package/dist/examples/vintasend-medplum-example/src/hooks/usePatient.ts +18 -0
  180. package/dist/examples/vintasend-medplum-example/src/hooks/useThreadInbox.test.tsx +379 -0
  181. package/dist/examples/vintasend-medplum-example/src/hooks/useThreadInbox.ts +194 -0
  182. package/dist/examples/vintasend-medplum-example/src/index.css +8 -0
  183. package/dist/examples/vintasend-medplum-example/src/main.tsx +57 -0
  184. package/dist/examples/vintasend-medplum-example/src/pages/SearchPage.module.css +6 -0
  185. package/dist/examples/vintasend-medplum-example/src/pages/SearchPage.test.tsx +295 -0
  186. package/dist/examples/vintasend-medplum-example/src/pages/SearchPage.tsx +124 -0
  187. package/dist/examples/vintasend-medplum-example/src/pages/SignInPage.test.tsx +77 -0
  188. package/dist/examples/vintasend-medplum-example/src/pages/SignInPage.tsx +22 -0
  189. package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterChartPage.test.tsx +87 -0
  190. package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterChartPage.tsx +27 -0
  191. package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterModal.module.css +16 -0
  192. package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterModal.test.tsx +287 -0
  193. package/dist/examples/vintasend-medplum-example/src/pages/encounter/EncounterModal.tsx +151 -0
  194. package/dist/examples/vintasend-medplum-example/src/pages/integrations/DoseSpotFavoritesPage.test.tsx +519 -0
  195. package/dist/examples/vintasend-medplum-example/src/pages/integrations/DoseSpotFavoritesPage.tsx +179 -0
  196. package/dist/examples/vintasend-medplum-example/src/pages/integrations/FavoriteMedicationsTable.tsx +76 -0
  197. package/dist/examples/vintasend-medplum-example/src/pages/integrations/IntegrationsPage.test.tsx +234 -0
  198. package/dist/examples/vintasend-medplum-example/src/pages/integrations/IntegrationsPage.tsx +222 -0
  199. package/dist/examples/vintasend-medplum-example/src/pages/labs/OrderLabsPage.test.tsx +356 -0
  200. package/dist/examples/vintasend-medplum-example/src/pages/labs/OrderLabsPage.tsx +275 -0
  201. package/dist/examples/vintasend-medplum-example/src/pages/messages/MessagesPage.module.css +8 -0
  202. package/dist/examples/vintasend-medplum-example/src/pages/messages/MessagesPage.test.tsx +103 -0
  203. package/dist/examples/vintasend-medplum-example/src/pages/messages/MessagesPage.tsx +78 -0
  204. package/dist/examples/vintasend-medplum-example/src/pages/patient/CommunicationTab.test.tsx +84 -0
  205. package/dist/examples/vintasend-medplum-example/src/pages/patient/CommunicationTab.tsx +82 -0
  206. package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotAdvancedOptions.test.tsx +364 -0
  207. package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotAdvancedOptions.tsx +149 -0
  208. package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotTab.test.tsx +159 -0
  209. package/dist/examples/vintasend-medplum-example/src/pages/patient/DoseSpotTab.tsx +37 -0
  210. package/dist/examples/vintasend-medplum-example/src/pages/patient/EditTab.test.tsx +140 -0
  211. package/dist/examples/vintasend-medplum-example/src/pages/patient/EditTab.tsx +72 -0
  212. package/dist/examples/vintasend-medplum-example/src/pages/patient/ExportTab.test.tsx +57 -0
  213. package/dist/examples/vintasend-medplum-example/src/pages/patient/ExportTab.tsx +14 -0
  214. package/dist/examples/vintasend-medplum-example/src/pages/patient/IntakeFormPage.test.tsx +241 -0
  215. package/dist/examples/vintasend-medplum-example/src/pages/patient/IntakeFormPage.tsx +710 -0
  216. package/dist/examples/vintasend-medplum-example/src/pages/patient/LabsPage.module.css +37 -0
  217. package/dist/examples/vintasend-medplum-example/src/pages/patient/LabsPage.test.tsx +428 -0
  218. package/dist/examples/vintasend-medplum-example/src/pages/patient/LabsPage.tsx +334 -0
  219. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.module.css +24 -0
  220. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.test.tsx +154 -0
  221. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.tsx +115 -0
  222. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.utils.test.ts +223 -0
  223. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientPage.utils.ts +89 -0
  224. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientSearchPage.test.tsx +147 -0
  225. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientSearchPage.tsx +79 -0
  226. package/dist/examples/vintasend-medplum-example/src/pages/patient/PatientTabsNavigation.tsx +35 -0
  227. package/dist/examples/vintasend-medplum-example/src/pages/patient/TasksTab.test.tsx +185 -0
  228. package/dist/examples/vintasend-medplum-example/src/pages/patient/TasksTab.tsx +115 -0
  229. package/dist/examples/vintasend-medplum-example/src/pages/patient/TimelineTab.tsx +14 -0
  230. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceCreatePage.test.tsx +170 -0
  231. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceCreatePage.tsx +117 -0
  232. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceDetailPage.tsx +28 -0
  233. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceEditPage.test.tsx +131 -0
  234. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceEditPage.tsx +65 -0
  235. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceHistoryPage.test.tsx +108 -0
  236. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourceHistoryPage.tsx +16 -0
  237. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourcePage.module.css +7 -0
  238. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourcePage.test.tsx +37 -0
  239. package/dist/examples/vintasend-medplum-example/src/pages/resource/ResourcePage.tsx +44 -0
  240. package/dist/examples/vintasend-medplum-example/src/pages/resource/useResourceType.ts +44 -0
  241. package/dist/examples/vintasend-medplum-example/src/pages/resource/utils.ts +9 -0
  242. package/dist/examples/vintasend-medplum-example/src/pages/schedule/SchedulePage.test.tsx +302 -0
  243. package/dist/examples/vintasend-medplum-example/src/pages/schedule/SchedulePage.tsx +416 -0
  244. package/dist/examples/vintasend-medplum-example/src/pages/spaces/ChatInput.tsx +91 -0
  245. package/dist/examples/vintasend-medplum-example/src/pages/spaces/SpacesPage.module.css +6 -0
  246. package/dist/examples/vintasend-medplum-example/src/pages/spaces/SpacesPage.test.tsx +102 -0
  247. package/dist/examples/vintasend-medplum-example/src/pages/spaces/SpacesPage.tsx +44 -0
  248. package/dist/examples/vintasend-medplum-example/src/pages/tasks/TasksPage.module.css +7 -0
  249. package/dist/examples/vintasend-medplum-example/src/pages/tasks/TasksPage.test.tsx +133 -0
  250. package/dist/examples/vintasend-medplum-example/src/pages/tasks/TasksPage.tsx +91 -0
  251. package/dist/examples/vintasend-medplum-example/src/test-utils/render.tsx +20 -0
  252. package/dist/examples/vintasend-medplum-example/src/test.setup.ts +49 -0
  253. package/dist/examples/vintasend-medplum-example/src/types/encounter.ts +8 -0
  254. package/dist/examples/vintasend-medplum-example/src/types/spaces.ts +10 -0
  255. package/dist/examples/vintasend-medplum-example/src/utils/chargeitems.test.ts +141 -0
  256. package/dist/examples/vintasend-medplum-example/src/utils/chargeitems.ts +59 -0
  257. package/dist/examples/vintasend-medplum-example/src/utils/claims.test.ts +153 -0
  258. package/dist/examples/vintasend-medplum-example/src/utils/claims.ts +65 -0
  259. package/dist/examples/vintasend-medplum-example/src/utils/communication-search.ts +47 -0
  260. package/dist/examples/vintasend-medplum-example/src/utils/coverage.test.ts +48 -0
  261. package/dist/examples/vintasend-medplum-example/src/utils/coverage.ts +33 -0
  262. package/dist/examples/vintasend-medplum-example/src/utils/documentReference.test.ts +102 -0
  263. package/dist/examples/vintasend-medplum-example/src/utils/documentReference.ts +55 -0
  264. package/dist/examples/vintasend-medplum-example/src/utils/encounter.test.ts +169 -0
  265. package/dist/examples/vintasend-medplum-example/src/utils/encounter.ts +261 -0
  266. package/dist/examples/vintasend-medplum-example/src/utils/intake-form.test.ts +154 -0
  267. package/dist/examples/vintasend-medplum-example/src/utils/intake-form.ts +272 -0
  268. package/dist/examples/vintasend-medplum-example/src/utils/intake-utils.test.ts +1137 -0
  269. package/dist/examples/vintasend-medplum-example/src/utils/intake-utils.ts +827 -0
  270. package/dist/examples/vintasend-medplum-example/src/utils/notifications.test.ts +27 -0
  271. package/dist/examples/vintasend-medplum-example/src/utils/notifications.ts +15 -0
  272. package/dist/examples/vintasend-medplum-example/src/utils/spaceMessaging.ts +249 -0
  273. package/dist/examples/vintasend-medplum-example/src/utils/spacePersistence.test.ts +450 -0
  274. package/dist/examples/vintasend-medplum-example/src/utils/spacePersistence.ts +147 -0
  275. package/dist/examples/vintasend-medplum-example/src/utils/task-search.ts +63 -0
  276. package/dist/examples/vintasend-medplum-example/src/vite-env.d.ts +3 -0
  277. package/dist/examples/vintasend-medplum-example/tsconfig.bots.json +4 -0
  278. package/dist/examples/vintasend-medplum-example/tsconfig.json +19 -0
  279. package/dist/examples/vintasend-medplum-example/vercel.json +3 -0
  280. package/dist/examples/vintasend-medplum-example/vite.config.ts +44 -0
  281. package/dist/services/notification-backends/base-notification-backend.d.ts +5 -0
  282. package/dist/services/notification-service.js +11 -1
  283. package/dist/services/notification-template-renderers/base-email-template-renderer.d.ts +5 -0
  284. package/package.json +1 -1
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "medplum-provider",
3
+ "version": "5.0.10",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "tsc && vite build",
8
+ "dev": "vite",
9
+ "lint": "eslint .",
10
+ "lint:fix": "eslint . --fix",
11
+ "preview": "vite preview",
12
+ "test": "vitest run",
13
+ "test:coverage": "vitest run --coverage",
14
+ "clean": "rm -rf dist && rm -f compiled-notification-templates.json",
15
+ "compile-templates": "compile-pug-templates ./notification-templates ./compiled-notification-templates.json",
16
+ "bots:build": "npm run clean && npm run compile-templates && tsc --project tsconfig.bots.json && node --no-warnings esbuild-script.mjs",
17
+ "bots:deploy": "tsx scripts/deploy-bots.ts",
18
+ "bots:build:dev": "npm run clean && npm run compile-templates && node --no-warnings esbuild-script.mjs"
19
+ },
20
+ "prettier": {
21
+ "printWidth": 120,
22
+ "singleQuote": true,
23
+ "trailingComma": "es5"
24
+ },
25
+ "devDependencies": {
26
+ "@mantine/core": "8.3.11",
27
+ "@mantine/hooks": "8.3.11",
28
+ "@mantine/notifications": "8.3.11",
29
+ "@mantine/spotlight": "8.3.11",
30
+ "@medplum/bot-layer": "^5.0.12",
31
+ "@medplum/core": "5.0.10",
32
+ "@medplum/dosespot-react": "5.0.10",
33
+ "@medplum/eslint-config": "5.0.10",
34
+ "@medplum/fhirtypes": "5.0.10",
35
+ "@medplum/health-gorilla-core": "5.0.10",
36
+ "@medplum/health-gorilla-react": "5.0.10",
37
+ "@medplum/mock": "^5.0.12",
38
+ "@medplum/react": "5.0.10",
39
+ "@sentry/esbuild-plugin": "^4.7.0",
40
+ "@tabler/icons-react": "3.36.1",
41
+ "@testing-library/dom": "10.4.1",
42
+ "@testing-library/jest-dom": "6.9.1",
43
+ "@testing-library/react": "16.3.1",
44
+ "@testing-library/user-event": "14.6.1",
45
+ "@types/node": "22.19.3",
46
+ "@types/react": "19.2.7",
47
+ "@types/react-big-calendar": "1.16.3",
48
+ "@types/react-dom": "19.2.3",
49
+ "@vitejs/plugin-react": "5.1.2",
50
+ "dayjs": "1.11.19",
51
+ "dotenv": "^17.2.3",
52
+ "fast-glob": "^3.3.3",
53
+ "jsdom": "27.4.0",
54
+ "postcss": "8.5.6",
55
+ "postcss-preset-mantine": "1.18.0",
56
+ "react": "19.2.3",
57
+ "react-big-calendar": "1.19.4",
58
+ "react-dom": "19.2.3",
59
+ "react-router": "7.12.0",
60
+ "tsx": "^4.21.0",
61
+ "typescript": "5.9.3",
62
+ "uuid": "11.1.0",
63
+ "vite": "7.3.1",
64
+ "vitest": "4.0.16"
65
+ },
66
+ "packageManager": "npm@10.9.4",
67
+ "engines": {
68
+ "node": "^22.18.0 || >=24.2.0"
69
+ },
70
+ "dependencies": {
71
+ "vintasend": "^0.4.3",
72
+ "vintasend-medplum": "^0.4.5",
73
+ "vintasend-sendgrid": "^0.4.3"
74
+ }
75
+ }
@@ -0,0 +1,31 @@
1
+ import fs from 'fs/promises';
2
+
3
+ /**
4
+ * esbuild plugin for handling GraphQL files.
5
+ * Automatically exports all named operations (queries, mutations) and fragments.
6
+ */
7
+ export const gqlPlugin = {
8
+ name: 'gql',
9
+ setup(build) {
10
+ build.onLoad({ filter: /\.gql$/ }, async (args) => {
11
+ const contents = await fs.readFile(args.path, 'utf8');
12
+
13
+ // Simple regex to find all named operations and fragments
14
+ const operationRegex = /(query|mutation|fragment)\s+([a-zA-Z][a-zA-Z0-9_]*)/g;
15
+ const matches = [...contents.matchAll(operationRegex)];
16
+
17
+ const exports = matches
18
+ .map(([, , name]) => `export const ${name} = doc;`)
19
+ .join('\n');
20
+
21
+ return {
22
+ contents: `
23
+ const doc = \`${contents}\`;
24
+ ${exports}
25
+ export default doc;
26
+ `,
27
+ loader: 'js',
28
+ };
29
+ });
30
+ },
31
+ };
@@ -0,0 +1,21 @@
1
+ // SPDX-FileCopyrightText: Copyright Orangebot, Inc. and Medplum contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import mantinePreset from 'postcss-preset-mantine';
4
+ import simpleVars from 'postcss-simple-vars';
5
+
6
+ const config = {
7
+ plugins: [
8
+ mantinePreset(),
9
+ simpleVars({
10
+ variables: {
11
+ 'mantine-breakpoint-xs': '36em',
12
+ 'mantine-breakpoint-sm': '48em',
13
+ 'mantine-breakpoint-md': '62em',
14
+ 'mantine-breakpoint-lg': '75em',
15
+ 'mantine-breakpoint-xl': '88em',
16
+ },
17
+ }),
18
+ ],
19
+ };
20
+
21
+ export default config;
@@ -0,0 +1,162 @@
1
+ # Scripts
2
+
3
+ This directory contains automation scripts for setting up and managing your Medplum environment.
4
+
5
+ ## setup-task-assignment-subscription.ts
6
+
7
+ Creates or updates the FHIR Subscription that triggers the task assignment email bot.
8
+
9
+ ### What it does:
10
+
11
+ 1. **Authenticates** with Medplum using client credentials
12
+ 2. **Creates/finds** the Task Assignment Email Bot resource
13
+ 3. **Creates/updates** a Subscription with criteria: `Task?owner:exists=true`
14
+ 4. **Configures** the subscription to trigger on Task create and update events
15
+
16
+ ### Prerequisites:
17
+
18
+ Create a `.env` file with your Medplum credentials:
19
+
20
+ ```bash
21
+ MEDPLUM_BASE_URL=https://api.medplum.com
22
+ MEDPLUM_CLIENT_ID=your-client-id
23
+ MEDPLUM_CLIENT_SECRET=your-client-secret
24
+ APP_BASE_URL=https://your-app-url.com
25
+ ```
26
+
27
+ ### Usage:
28
+
29
+ ```bash
30
+ npm run setup:subscription
31
+ ```
32
+
33
+ ### Expected Output:
34
+
35
+ ```
36
+ ✅ Successfully authenticated with Medplum
37
+ ✅ Found existing bot: abc-123
38
+ ✅ Updated subscription: def-456
39
+
40
+ 📋 Subscription Details:
41
+ ID: def-456
42
+ Status: active
43
+ Criteria: Task?owner:exists=true
44
+ Bot: abc-123 (Task Assignment Email Bot)
45
+ Triggers: Task create, update (when owner exists)
46
+
47
+ ✅ Setup complete!
48
+
49
+ 📝 Next steps:
50
+ 1. Deploy your bot code: npm run bots:deploy
51
+ 2. Test by creating/updating a Task with an owner
52
+ 3. Check bot logs in Medplum console for execution details
53
+
54
+ ✨ Script completed successfully
55
+ ```
56
+
57
+ ### When to run:
58
+
59
+ - **Initial setup**: When first deploying your application
60
+ - **After bot changes**: If you modify the bot or subscription criteria
61
+ - **Environment changes**: When setting up a new environment (dev, staging, prod)
62
+ - **CI/CD**: Include in your deployment pipeline
63
+
64
+ ### Idempotent Design:
65
+
66
+ This script is safe to run multiple times. It will:
67
+ - Use existing Bot if found (by identifier)
68
+ - Update existing Subscription if found (by identifier)
69
+ - Create new resources only if they don't exist
70
+
71
+ ### Troubleshooting:
72
+
73
+ **Authentication Error:**
74
+ ```
75
+ ❌ Error setting up subscription: Authentication failed
76
+ ```
77
+ - Verify your `MEDPLUM_CLIENT_ID` and `MEDPLUM_CLIENT_SECRET` in `.env`
78
+ - Ensure the client has permission to create Bot and Subscription resources
79
+
80
+ **Resource Creation Failed:**
81
+ ```
82
+ ❌ Error creating Bot: Forbidden
83
+ ```
84
+ - Check that your client has the necessary permissions in Medplum
85
+ - You may need to grant `Bot` and `Subscription` resource creation permissions
86
+
87
+ **Subscription Not Triggering:**
88
+ - Verify the bot code is deployed: `npm run bots:deploy`
89
+ - Check subscription status in Medplum console (should be "active")
90
+ - Review bot logs for execution errors
91
+ - Ensure Task resources have the `owner` field populated
92
+
93
+ ### FHIR Resources Created:
94
+
95
+ #### Bot Resource:
96
+ ```json
97
+ {
98
+ "resourceType": "Bot",
99
+ "identifier": [
100
+ {
101
+ "system": "https://your-domain.com/bot-identifier",
102
+ "value": "task-assignment-email-bot"
103
+ }
104
+ ],
105
+ "name": "Task Assignment Email Bot",
106
+ "description": "Sends email notifications when tasks are assigned to practitioners"
107
+ }
108
+ ```
109
+
110
+ #### Subscription Resource:
111
+ ```json
112
+ {
113
+ "resourceType": "Subscription",
114
+ "identifier": [
115
+ {
116
+ "system": "https://your-domain.com/subscription-identifier",
117
+ "value": "task-assignment-email-subscription"
118
+ }
119
+ ],
120
+ "status": "active",
121
+ "reason": "Trigger email notification when a task is assigned",
122
+ "criteria": "Task?owner:exists=true",
123
+ "channel": {
124
+ "type": "rest-hook",
125
+ "endpoint": "Bot/bot-id-here"
126
+ },
127
+ "extension": [
128
+ {
129
+ "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
130
+ "valueCode": "create"
131
+ },
132
+ {
133
+ "url": "https://medplum.com/fhir/StructureDefinition/subscription-supported-interaction",
134
+ "valueCode": "update"
135
+ }
136
+ ]
137
+ }
138
+ ```
139
+
140
+ ### Understanding the Subscription:
141
+
142
+ - **criteria**: `Task?owner:exists=true` matches any Task with an owner
143
+ - **channel.type**: `rest-hook` invokes a bot endpoint
144
+ - **channel.endpoint**: Points to the Bot resource
145
+ - **extension**: Specifies to trigger on both create and update operations
146
+
147
+ ### Testing the Subscription:
148
+
149
+ After running the setup, test it by creating a Task:
150
+
151
+ ```typescript
152
+ const task = await medplum.createResource({
153
+ resourceType: 'Task',
154
+ status: 'requested',
155
+ intent: 'order',
156
+ code: { text: 'Test task' },
157
+ owner: { reference: 'Practitioner/123' }, // This triggers the subscription
158
+ requester: { reference: 'Practitioner/456' },
159
+ });
160
+ ```
161
+
162
+ Check the bot logs in Medplum console to verify execution.
@@ -0,0 +1,18 @@
1
+ import { MedplumClient } from '@medplum/core';
2
+ import { config } from 'dotenv';
3
+
4
+ // Load environment variables from .env file
5
+ config();
6
+
7
+ export async function getMedplumClient() {
8
+ const medplum = new MedplumClient({
9
+ clientId: process.env.MEDPLUM_CLIENT_ID,
10
+ });
11
+
12
+ await medplum.startClientLogin(
13
+ process.env.MEDPLUM_CLIENT_ID as string,
14
+ process.env.MEDPLUM_CLIENT_SECRET as string
15
+ );
16
+
17
+ return medplum;
18
+ }
@@ -0,0 +1,171 @@
1
+ import { ContentType, getReferenceString, MedplumClient, WithId } from '@medplum/core';
2
+ import { Bot, Bundle, BundleEntry, Questionnaire } from '@medplum/fhirtypes';
3
+ import fs from 'fs';
4
+ import { BotDescription, BOTS } from '../bots/index.js';
5
+ import { BOTS_SYSTEM } from '../lib/constants.js';
6
+ import { getMedplumClient } from './client.js';
7
+
8
+ async function readBotFiles(description: BotDescription, medplum: MedplumClient) {
9
+ const distFile = fs.readFileSync(`dist/bots/handlers/${description.name}.js`, 'utf-8');
10
+
11
+ const [sourceCodeAttachment, executableCodeAttachment] = await Promise.all([
12
+ medplum.createAttachment({
13
+ data: distFile,
14
+ contentType: 'application/javascript',
15
+ }),
16
+ medplum.createAttachment({
17
+ data: distFile,
18
+ contentType: 'application/javascript',
19
+ }),
20
+ ]);
21
+
22
+ return { sourceCodeAttachment, executableCodeAttachment };
23
+ }
24
+
25
+ async function generateBundle(medplum: MedplumClient): Promise<Bundle> {
26
+ const bundle: Bundle = {
27
+ resourceType: 'Bundle',
28
+ type: 'transaction',
29
+ entry: (
30
+ await Promise.all(
31
+ BOTS.map(async (botDescription): Promise<BundleEntry[]> => {
32
+ const botName = botDescription.name;
33
+ const botReferencePlaceholder = `$bot-${botName}-reference`;
34
+ const botIdPlaceholder = `$bot-${botName}-id`;
35
+ const results: BundleEntry[] = [];
36
+ const { cronString, timeout, runAsUser, criteria, extension } = botDescription;
37
+
38
+ const { executableCodeAttachment, sourceCodeAttachment } = await readBotFiles(botDescription, medplum);
39
+
40
+ results.push({
41
+ request: { method: 'PUT', url: botReferencePlaceholder },
42
+ resource: {
43
+ resourceType: 'Bot',
44
+ id: botIdPlaceholder,
45
+ identifier: [{ system: BOTS_SYSTEM, value: botName }],
46
+ name: botName,
47
+ runtimeVersion: 'awslambda',
48
+ sourceCode: sourceCodeAttachment,
49
+ executableCode: executableCodeAttachment,
50
+ runAsUser: runAsUser ?? false,
51
+ ...(cronString && { cronString }),
52
+ ...(timeout && { timeout }),
53
+ },
54
+ });
55
+
56
+ if (criteria) {
57
+ results.push({
58
+ request: {
59
+ method: 'PUT',
60
+ url: `Subscription?url=${botReferencePlaceholder}`,
61
+ },
62
+ resource: {
63
+ resourceType: 'Subscription',
64
+ status: 'active',
65
+ reason: `${botName}-subscription`,
66
+ criteria,
67
+ extension: extension ?? [],
68
+ channel: {
69
+ endpoint: botReferencePlaceholder,
70
+ type: 'rest-hook',
71
+ payload: 'application/fhir+json',
72
+ },
73
+ },
74
+ });
75
+ }
76
+
77
+ return results;
78
+ })
79
+ )
80
+ ).flat(),
81
+ };
82
+
83
+ return bundle;
84
+ }
85
+
86
+ async function deployBots(): Promise<void> {
87
+ // eslint-disable-next-line no-console
88
+ console.log('\nUploading bots...\n');
89
+
90
+ const medplum = await getMedplumClient();
91
+
92
+ const profile = await medplum.getProfile();
93
+ const projectId = profile?.meta?.project;
94
+
95
+ const questionnaires: Questionnaire[] = [];
96
+
97
+ const bundleData = await generateBundle(medplum);
98
+
99
+ let transactionString = JSON.stringify(bundleData);
100
+ const botEntries: BundleEntry[] =
101
+ (bundleData as Bundle).entry?.filter((e) => e.resource?.resourceType === 'Bot') || [];
102
+ const botIds: Record<string, string> = {};
103
+
104
+ for (const botDescription of BOTS) {
105
+ const botName = botDescription.name;
106
+
107
+ let existingBot = await medplum.searchOne('Bot', { name: botName });
108
+ if (!existingBot) {
109
+ const createBotUrl = new URL(`admin/projects/${projectId as string}/bot`, medplum.getBaseUrl());
110
+ existingBot = (await medplum.post(createBotUrl, {
111
+ name: botName,
112
+ })) as WithId<Bot>;
113
+ }
114
+
115
+ if (!existingBot) {
116
+ throw new Error(`Bot ${botName} not found`);
117
+ }
118
+
119
+ const botMembership = await medplum.searchOne('ProjectMembership', { user: getReferenceString(existingBot) });
120
+ if (botMembership && botMembership.admin !== botDescription.needsAdminMembership) {
121
+ await medplum.post(`admin/projects/${projectId as string}/members/${botMembership.id}`, {
122
+ ...botMembership,
123
+ admin: botDescription.needsAdminMembership,
124
+ });
125
+ }
126
+
127
+ botIds[botName] = existingBot.id as string;
128
+
129
+ // Replace the Bot id placeholder in the bundle
130
+ transactionString = transactionString
131
+ .replaceAll(`$bot-${botName}-reference`, getReferenceString(existingBot))
132
+ .replaceAll(`$bot-${botName}-id`, existingBot.id as string);
133
+ }
134
+
135
+ for (const questionnaire of questionnaires) {
136
+ transactionString = transactionString.replaceAll(
137
+ `$${questionnaire.name}`,
138
+ getReferenceString(questionnaire) as string
139
+ );
140
+ }
141
+
142
+ // eslint-disable-next-line no-console
143
+ console.log('\nUploading bots bundle...\n');
144
+
145
+ // Execute the transaction to upload / update the bot
146
+ const transaction = JSON.parse(transactionString);
147
+
148
+ const batchResponse = await medplum.executeBatch(transaction);
149
+ // await medplum.executeBatch(transaction);
150
+
151
+ const errors = batchResponse.entry?.filter((e) => !['200', '201'].includes(e.response?.status ?? ''));
152
+ if (errors && errors.length > 0) {
153
+ throw new Error(`${JSON.stringify(errors, null, 2)}`);
154
+ }
155
+
156
+ // Deploy the bots
157
+ for (const entry of botEntries) {
158
+ const botName = (entry?.resource as Bot)?.name as string;
159
+
160
+ // eslint-disable-next-line no-console
161
+ console.log(`Deploying ${botName}...`);
162
+
163
+ await medplum.post(medplum.fhirUrl('Bot', botIds[botName], '$deploy'));
164
+ }
165
+
166
+ // eslint-disable-next-line no-console
167
+ console.log('\nAll bots deployed!\n');
168
+ }
169
+
170
+ // eslint-disable-next-line no-console
171
+ deployBots().catch(console.error);