@tellescope/sdk 2.0.0-beta.0 → 2.0.0-beta.2

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 (303) hide show
  1. package/CLAUDE.md +24 -0
  2. package/env.example +6 -0
  3. package/lib/cjs/sdk.d.ts +376 -3
  4. package/lib/cjs/sdk.d.ts.map +1 -1
  5. package/lib/cjs/sdk.js +1 -0
  6. package/lib/cjs/sdk.js.map +1 -1
  7. package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts +22 -0
  8. package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts.map +1 -0
  9. package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.js +506 -0
  10. package/lib/cjs/tests/api_tests/booking_prevent_upcoming_duplicate.test.js.map +1 -0
  11. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts +3 -1
  12. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -1
  13. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js +3 -1
  14. package/lib/cjs/tests/api_tests/enduser_fields_sync.test.js.map +1 -1
  15. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts +3 -1
  16. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -1
  17. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js +3 -1
  18. package/lib/cjs/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -1
  19. package/lib/cjs/tests/api_tests/form_vital_reading.test.d.ts +7 -0
  20. package/lib/cjs/tests/api_tests/form_vital_reading.test.d.ts.map +1 -0
  21. package/lib/cjs/tests/api_tests/form_vital_reading.test.js +461 -0
  22. package/lib/cjs/tests/api_tests/form_vital_reading.test.js.map +1 -0
  23. package/lib/cjs/tests/api_tests/journey_statistics_cache.test.d.ts +26 -0
  24. package/lib/cjs/tests/api_tests/journey_statistics_cache.test.d.ts.map +1 -0
  25. package/lib/cjs/tests/api_tests/journey_statistics_cache.test.js +232 -0
  26. package/lib/cjs/tests/api_tests/journey_statistics_cache.test.js.map +1 -0
  27. package/lib/cjs/tests/api_tests/journey_step_manual_count.test.d.ts +34 -0
  28. package/lib/cjs/tests/api_tests/journey_step_manual_count.test.d.ts.map +1 -0
  29. package/lib/cjs/tests/api_tests/journey_step_manual_count.test.js +243 -0
  30. package/lib/cjs/tests/api_tests/journey_step_manual_count.test.js.map +1 -0
  31. package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts +3 -1
  32. package/lib/cjs/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -1
  33. package/lib/cjs/tests/api_tests/load_threads_care_team.test.js +3 -1
  34. package/lib/cjs/tests/api_tests/load_threads_care_team.test.js.map +1 -1
  35. package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -1
  36. package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js +139 -9
  37. package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js.map +1 -1
  38. package/lib/cjs/tests/api_tests/organization_signup.test.d.ts +3 -1
  39. package/lib/cjs/tests/api_tests/organization_signup.test.d.ts.map +1 -1
  40. package/lib/cjs/tests/api_tests/organization_signup.test.js +3 -1
  41. package/lib/cjs/tests/api_tests/organization_signup.test.js.map +1 -1
  42. package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.d.ts +7 -0
  43. package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.d.ts.map +1 -0
  44. package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.js +571 -0
  45. package/lib/cjs/tests/api_tests/phone_embed_leave_message.test.js.map +1 -0
  46. package/lib/cjs/tests/api_tests/programs.test.d.ts +3 -1
  47. package/lib/cjs/tests/api_tests/programs.test.d.ts.map +1 -1
  48. package/lib/cjs/tests/api_tests/programs.test.js +73 -17
  49. package/lib/cjs/tests/api_tests/programs.test.js.map +1 -1
  50. package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.d.ts +7 -0
  51. package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.d.ts.map +1 -0
  52. package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.js +733 -0
  53. package/lib/cjs/tests/api_tests/public_form_case_insensitive_match.test.js.map +1 -0
  54. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +3 -1
  55. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -1
  56. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +58 -48
  57. package/lib/cjs/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
  58. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +3 -1
  59. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -1
  60. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js +3 -1
  61. package/lib/cjs/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -1
  62. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts +3 -1
  63. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -1
  64. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js +3 -1
  65. package/lib/cjs/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -1
  66. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts +3 -1
  67. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -1
  68. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js +3 -1
  69. package/lib/cjs/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -1
  70. package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts.map +1 -1
  71. package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js +424 -39
  72. package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js.map +1 -1
  73. package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.js +2 -2
  74. package/lib/cjs/tests/api_tests/security/register_business_id_injection.test.js.map +1 -1
  75. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +3 -1
  76. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -1
  77. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +3 -1
  78. package/lib/cjs/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -1
  79. package/lib/cjs/tests/api_tests/session_for_join_link.test.d.ts +10 -0
  80. package/lib/cjs/tests/api_tests/session_for_join_link.test.d.ts.map +1 -0
  81. package/lib/cjs/tests/api_tests/session_for_join_link.test.js +147 -0
  82. package/lib/cjs/tests/api_tests/session_for_join_link.test.js.map +1 -0
  83. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -1
  84. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js +191 -88
  85. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js.map +1 -1
  86. package/lib/cjs/tests/api_tests/stripe_checkout_items.test.d.ts +17 -0
  87. package/lib/cjs/tests/api_tests/stripe_checkout_items.test.d.ts.map +1 -0
  88. package/lib/cjs/tests/api_tests/stripe_checkout_items.test.js +219 -0
  89. package/lib/cjs/tests/api_tests/stripe_checkout_items.test.js.map +1 -0
  90. package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.d.ts +5 -0
  91. package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.d.ts.map +1 -0
  92. package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.js +396 -0
  93. package/lib/cjs/tests/api_tests/stripe_multiple_customer_ids.test.js.map +1 -0
  94. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts +3 -1
  95. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts.map +1 -1
  96. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.js +3 -1
  97. package/lib/cjs/tests/api_tests/tickets_bulk_assign_from_queue.test.js.map +1 -1
  98. package/lib/cjs/tests/api_tests/totp_mfa.test.d.ts.map +1 -1
  99. package/lib/cjs/tests/api_tests/totp_mfa.test.js +37 -31
  100. package/lib/cjs/tests/api_tests/totp_mfa.test.js.map +1 -1
  101. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts +3 -1
  102. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -1
  103. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js +3 -1
  104. package/lib/cjs/tests/api_tests/trigger_contains_matching.test.js.map +1 -1
  105. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts +3 -1
  106. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -1
  107. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js +3 -1
  108. package/lib/cjs/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -1
  109. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts +3 -1
  110. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -1
  111. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js +3 -1
  112. package/lib/cjs/tests/api_tests/vital_review_trigger_action.test.js.map +1 -1
  113. package/lib/cjs/tests/api_tests/vitl_push.test.d.ts +7 -0
  114. package/lib/cjs/tests/api_tests/vitl_push.test.d.ts.map +1 -0
  115. package/lib/cjs/tests/api_tests/vitl_push.test.js +341 -0
  116. package/lib/cjs/tests/api_tests/vitl_push.test.js.map +1 -0
  117. package/lib/cjs/tests/setup_isolated.d.ts +48 -0
  118. package/lib/cjs/tests/setup_isolated.d.ts.map +1 -1
  119. package/lib/cjs/tests/setup_isolated.js +119 -1
  120. package/lib/cjs/tests/setup_isolated.js.map +1 -1
  121. package/lib/cjs/tests/tests.d.ts.map +1 -1
  122. package/lib/cjs/tests/tests.js +378 -282
  123. package/lib/cjs/tests/tests.js.map +1 -1
  124. package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.d.ts +2 -0
  125. package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.d.ts.map +1 -0
  126. package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.js +201 -0
  127. package/lib/cjs/tests/unit_tests/isolated_suite_discovery.test.js.map +1 -0
  128. package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.d.ts +3 -0
  129. package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.d.ts.map +1 -0
  130. package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.js +120 -0
  131. package/lib/cjs/tests/unit_tests/programs_conditional_logic.test.js.map +1 -0
  132. package/lib/cjs/tests/webhooks_tests.js +44 -34
  133. package/lib/cjs/tests/webhooks_tests.js.map +1 -1
  134. package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  135. package/lib/esm/sdk.d.ts +376 -3
  136. package/lib/esm/sdk.d.ts.map +1 -1
  137. package/lib/esm/sdk.js +1 -0
  138. package/lib/esm/sdk.js.map +1 -1
  139. package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts +22 -0
  140. package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.d.ts.map +1 -0
  141. package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.js +501 -0
  142. package/lib/esm/tests/api_tests/booking_prevent_upcoming_duplicate.test.js.map +1 -0
  143. package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts +3 -1
  144. package/lib/esm/tests/api_tests/enduser_fields_sync.test.d.ts.map +1 -1
  145. package/lib/esm/tests/api_tests/enduser_fields_sync.test.js +2 -0
  146. package/lib/esm/tests/api_tests/enduser_fields_sync.test.js.map +1 -1
  147. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts +3 -1
  148. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.d.ts.map +1 -1
  149. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js +2 -0
  150. package/lib/esm/tests/api_tests/enduser_observations_auto_review.test.js.map +1 -1
  151. package/lib/esm/tests/api_tests/form_vital_reading.test.d.ts +7 -0
  152. package/lib/esm/tests/api_tests/form_vital_reading.test.d.ts.map +1 -0
  153. package/lib/esm/tests/api_tests/form_vital_reading.test.js +456 -0
  154. package/lib/esm/tests/api_tests/form_vital_reading.test.js.map +1 -0
  155. package/lib/esm/tests/api_tests/journey_statistics_cache.test.d.ts +26 -0
  156. package/lib/esm/tests/api_tests/journey_statistics_cache.test.d.ts.map +1 -0
  157. package/lib/esm/tests/api_tests/journey_statistics_cache.test.js +227 -0
  158. package/lib/esm/tests/api_tests/journey_statistics_cache.test.js.map +1 -0
  159. package/lib/esm/tests/api_tests/journey_step_manual_count.test.d.ts +34 -0
  160. package/lib/esm/tests/api_tests/journey_step_manual_count.test.d.ts.map +1 -0
  161. package/lib/esm/tests/api_tests/journey_step_manual_count.test.js +238 -0
  162. package/lib/esm/tests/api_tests/journey_step_manual_count.test.js.map +1 -0
  163. package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts +3 -1
  164. package/lib/esm/tests/api_tests/load_threads_care_team.test.d.ts.map +1 -1
  165. package/lib/esm/tests/api_tests/load_threads_care_team.test.js +2 -0
  166. package/lib/esm/tests/api_tests/load_threads_care_team.test.js.map +1 -1
  167. package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -1
  168. package/lib/esm/tests/api_tests/mdi_case_offerings.test.js +139 -9
  169. package/lib/esm/tests/api_tests/mdi_case_offerings.test.js.map +1 -1
  170. package/lib/esm/tests/api_tests/organization_signup.test.d.ts +3 -1
  171. package/lib/esm/tests/api_tests/organization_signup.test.d.ts.map +1 -1
  172. package/lib/esm/tests/api_tests/organization_signup.test.js +2 -0
  173. package/lib/esm/tests/api_tests/organization_signup.test.js.map +1 -1
  174. package/lib/esm/tests/api_tests/phone_embed_leave_message.test.d.ts +7 -0
  175. package/lib/esm/tests/api_tests/phone_embed_leave_message.test.d.ts.map +1 -0
  176. package/lib/esm/tests/api_tests/phone_embed_leave_message.test.js +566 -0
  177. package/lib/esm/tests/api_tests/phone_embed_leave_message.test.js.map +1 -0
  178. package/lib/esm/tests/api_tests/programs.test.d.ts +3 -1
  179. package/lib/esm/tests/api_tests/programs.test.d.ts.map +1 -1
  180. package/lib/esm/tests/api_tests/programs.test.js +72 -16
  181. package/lib/esm/tests/api_tests/programs.test.js.map +1 -1
  182. package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.d.ts +7 -0
  183. package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.d.ts.map +1 -0
  184. package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.js +728 -0
  185. package/lib/esm/tests/api_tests/public_form_case_insensitive_match.test.js.map +1 -0
  186. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts +3 -1
  187. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.d.ts.map +1 -1
  188. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js +57 -47
  189. package/lib/esm/tests/api_tests/security/add-to-journey-foreign-enduserid.test.js.map +1 -1
  190. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts +3 -1
  191. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.d.ts.map +1 -1
  192. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js +2 -0
  193. package/lib/esm/tests/api_tests/security/appointment-reschedule-ownership.test.js.map +1 -1
  194. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts +3 -1
  195. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.d.ts.map +1 -1
  196. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js +2 -0
  197. package/lib/esm/tests/api_tests/security/file-link-session-confinement.test.js.map +1 -1
  198. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts +3 -1
  199. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.d.ts.map +1 -1
  200. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js +2 -0
  201. package/lib/esm/tests/api_tests/security/form-logic-js-execution.test.js.map +1 -1
  202. package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts.map +1 -1
  203. package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js +424 -39
  204. package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js.map +1 -1
  205. package/lib/esm/tests/api_tests/security/register_business_id_injection.test.js +2 -2
  206. package/lib/esm/tests/api_tests/security/register_business_id_injection.test.js.map +1 -1
  207. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts +3 -1
  208. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.d.ts.map +1 -1
  209. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js +2 -0
  210. package/lib/esm/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.js.map +1 -1
  211. package/lib/esm/tests/api_tests/session_for_join_link.test.d.ts +10 -0
  212. package/lib/esm/tests/api_tests/session_for_join_link.test.d.ts.map +1 -0
  213. package/lib/esm/tests/api_tests/session_for_join_link.test.js +142 -0
  214. package/lib/esm/tests/api_tests/session_for_join_link.test.js.map +1 -0
  215. package/lib/esm/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -1
  216. package/lib/esm/tests/api_tests/set_fields_order_templates.test.js +191 -88
  217. package/lib/esm/tests/api_tests/set_fields_order_templates.test.js.map +1 -1
  218. package/lib/esm/tests/api_tests/stripe_checkout_items.test.d.ts +17 -0
  219. package/lib/esm/tests/api_tests/stripe_checkout_items.test.d.ts.map +1 -0
  220. package/lib/esm/tests/api_tests/stripe_checkout_items.test.js +214 -0
  221. package/lib/esm/tests/api_tests/stripe_checkout_items.test.js.map +1 -0
  222. package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.d.ts +5 -0
  223. package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.d.ts.map +1 -0
  224. package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.js +388 -0
  225. package/lib/esm/tests/api_tests/stripe_multiple_customer_ids.test.js.map +1 -0
  226. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts +3 -1
  227. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.d.ts.map +1 -1
  228. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.js +2 -0
  229. package/lib/esm/tests/api_tests/tickets_bulk_assign_from_queue.test.js.map +1 -1
  230. package/lib/esm/tests/api_tests/totp_mfa.test.d.ts.map +1 -1
  231. package/lib/esm/tests/api_tests/totp_mfa.test.js +37 -31
  232. package/lib/esm/tests/api_tests/totp_mfa.test.js.map +1 -1
  233. package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts +3 -1
  234. package/lib/esm/tests/api_tests/trigger_contains_matching.test.d.ts.map +1 -1
  235. package/lib/esm/tests/api_tests/trigger_contains_matching.test.js +2 -0
  236. package/lib/esm/tests/api_tests/trigger_contains_matching.test.js.map +1 -1
  237. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts +3 -1
  238. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.d.ts.map +1 -1
  239. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js +2 -0
  240. package/lib/esm/tests/api_tests/user_logs_restore_deleted.test.js.map +1 -1
  241. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts +3 -1
  242. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.d.ts.map +1 -1
  243. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js +2 -0
  244. package/lib/esm/tests/api_tests/vital_review_trigger_action.test.js.map +1 -1
  245. package/lib/esm/tests/api_tests/vitl_push.test.d.ts +7 -0
  246. package/lib/esm/tests/api_tests/vitl_push.test.d.ts.map +1 -0
  247. package/lib/esm/tests/api_tests/vitl_push.test.js +333 -0
  248. package/lib/esm/tests/api_tests/vitl_push.test.js.map +1 -0
  249. package/lib/esm/tests/setup_isolated.d.ts +48 -0
  250. package/lib/esm/tests/setup_isolated.d.ts.map +1 -1
  251. package/lib/esm/tests/setup_isolated.js +114 -0
  252. package/lib/esm/tests/setup_isolated.js.map +1 -1
  253. package/lib/esm/tests/tests.d.ts.map +1 -1
  254. package/lib/esm/tests/tests.js +379 -283
  255. package/lib/esm/tests/tests.js.map +1 -1
  256. package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.d.ts +2 -0
  257. package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.d.ts.map +1 -0
  258. package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.js +174 -0
  259. package/lib/esm/tests/unit_tests/isolated_suite_discovery.test.js.map +1 -0
  260. package/lib/esm/tests/unit_tests/programs_conditional_logic.test.d.ts +3 -0
  261. package/lib/esm/tests/unit_tests/programs_conditional_logic.test.d.ts.map +1 -0
  262. package/lib/esm/tests/unit_tests/programs_conditional_logic.test.js +117 -0
  263. package/lib/esm/tests/unit_tests/programs_conditional_logic.test.js.map +1 -0
  264. package/lib/esm/tests/webhooks_tests.js +44 -34
  265. package/lib/esm/tests/webhooks_tests.js.map +1 -1
  266. package/lib/tsconfig.tsbuildinfo +1 -1
  267. package/package.json +12 -11
  268. package/src/sdk.ts +9 -2
  269. package/src/tests/api_tests/booking_prevent_upcoming_duplicate.test.ts +541 -0
  270. package/src/tests/api_tests/enduser_fields_sync.test.ts +154 -0
  271. package/src/tests/api_tests/enduser_observations_auto_review.test.ts +4 -0
  272. package/src/tests/api_tests/form_vital_reading.test.ts +393 -0
  273. package/src/tests/api_tests/journey_statistics_cache.test.ts +237 -0
  274. package/src/tests/api_tests/journey_step_manual_count.test.ts +220 -0
  275. package/src/tests/api_tests/load_threads_care_team.test.ts +214 -0
  276. package/src/tests/api_tests/mdi_case_offerings.test.ts +138 -0
  277. package/src/tests/api_tests/organization_signup.test.ts +4 -0
  278. package/src/tests/api_tests/phone_embed_leave_message.test.ts +541 -0
  279. package/src/tests/api_tests/programs.test.ts +351 -0
  280. package/src/tests/api_tests/public_form_case_insensitive_match.test.ts +632 -0
  281. package/src/tests/api_tests/security/add-to-journey-foreign-enduserid.test.ts +37 -26
  282. package/src/tests/api_tests/security/appointment-reschedule-ownership.test.ts +436 -0
  283. package/src/tests/api_tests/security/file-link-session-confinement.test.ts +4 -0
  284. package/src/tests/api_tests/security/form-logic-js-execution.test.ts +4 -0
  285. package/src/tests/api_tests/security/formsort_webhook_auth_field_lock.test.ts +225 -0
  286. package/src/tests/api_tests/security/register_business_id_injection.test.ts +2 -2
  287. package/src/tests/api_tests/security/rich-text-answer-sanitized-on-write.test.ts +4 -0
  288. package/src/tests/api_tests/session_for_join_link.test.ts +99 -0
  289. package/src/tests/api_tests/set_fields_order_templates.test.ts +94 -9
  290. package/src/tests/api_tests/stripe_checkout_items.test.ts +186 -0
  291. package/src/tests/api_tests/tickets_bulk_assign_from_queue.test.ts +4 -0
  292. package/src/tests/api_tests/totp_mfa.test.ts +10 -5
  293. package/src/tests/api_tests/trigger_contains_matching.test.ts +349 -0
  294. package/src/tests/api_tests/user_logs_restore_deleted.test.ts +419 -0
  295. package/src/tests/api_tests/vital_review_trigger_action.test.ts +455 -0
  296. package/src/tests/api_tests/vitl_push.test.ts +323 -0
  297. package/src/tests/setup_isolated.ts +140 -0
  298. package/src/tests/tests.ts +126 -20
  299. package/src/tests/unit_tests/isolated_suite_discovery.test.ts +178 -0
  300. package/src/tests/unit_tests/programs_conditional_logic.test.ts +189 -0
  301. package/src/tests/unit_tests/trigger_title_partials.test.ts +174 -0
  302. package/src/tests/webhooks_tests.ts +6 -1
  303. package/test_generated.pdf +0 -0
@@ -0,0 +1,351 @@
1
+ require('source-map-support').install();
2
+
3
+ import { EnduserSession } from "../../enduser"
4
+ import { EnduserProgram } from "@tellescope/types-models"
5
+ import {
6
+ assert_checks,
7
+ Check,
8
+ setup_isolated_tenant,
9
+ IsolatedSuite,
10
+ } from "../setup_isolated"
11
+
12
+ const host = process.env.API_URL || 'http://localhost:8080' as const
13
+
14
+ const RAND = () => Math.random().toString(36).slice(2, 10)
15
+
16
+ /**
17
+ * Coverage for the `programs` field on Enduser / EnduserObservation / EnduserOrder, and for the
18
+ * `programs` filter on the Order Status Equals and Vital Update automation triggers.
19
+ *
20
+ * `EnduserOrder.programs` and `EnduserObservation.programs` are lists of `{ name }` objects; the
21
+ * trigger's `info.programs` is a list of names. A trigger matches when the two overlap, and — the part
22
+ * that matters most — a trigger with NO programs filter must keep matching every record, since that is
23
+ * every trigger that exists today.
24
+ *
25
+ * Both handlers apply the filter in JS after loading candidate triggers:
26
+ * - handle_order_status_equals, api/modules/automation_triggers.ts
27
+ * - handle_vital_create, api/v1/event_handlers_v2/vitals.ts
28
+ *
29
+ * This suite provisions its own throwaway tenant. That is not optional here: `vital_configurations`
30
+ * are business-wide (handle_vital_create reads them with `enduserId: { $exists: false }` across the
31
+ * businessId), so running on the shared fixture would classify other concurrently running suites'
32
+ * readings and theirs would bleed into these checks. It never calls `sdk.reset_db()`, which clears
33
+ * global throttle namespaces shared with other suites.
34
+ *
35
+ * Every check gets its own enduser: triggers are throttled to one fire per trigger per enduser per
36
+ * minute, so reusing a patient across checks would silently swallow the second fire.
37
+ *
38
+ * Triggers fire asynchronously. Each check polls for the unfiltered trigger's tag and uses that as the
39
+ * synchronization barrier, then asserts on the filtered trigger's tag. Without the barrier a negative
40
+ * check would pass merely by reading too early.
41
+ */
42
+
43
+ const poll_for = async <T,>(get: () => Promise<T>, done: (v: T) => boolean, attempts=20): Promise<T> => {
44
+ let value = await get()
45
+ for (let i = 0; i < attempts && !done(value); i++) {
46
+ await new Promise(resolve => setTimeout(resolve, 250))
47
+ value = await get()
48
+ }
49
+ return value
50
+ }
51
+
52
+ export const programs_checks = async (): Promise<Check[]> => {
53
+ const checks: Check[] = []
54
+ const record = (label: string, pass: boolean, detail: string) => checks.push({ label, pass, detail })
55
+
56
+ let tenant: Awaited<ReturnType<typeof setup_isolated_tenant>> | undefined
57
+
58
+ try {
59
+ tenant = await setup_isolated_tenant({
60
+ name: `ProgramFilters ${RAND()}`,
61
+ users: [{ isAdmin: true }],
62
+ apiKeys: 0,
63
+ })
64
+ const { sdk } = tenant
65
+
66
+ /* ===================== Enduser.programs ===================== */
67
+
68
+ const programsEnduser = await sdk.api.endusers.createOne({
69
+ fname: 'Programs',
70
+ lname: 'Field',
71
+ email: `programs-field-${RAND()}@tellescope.example`,
72
+ devices: [{ title: 'Cuff', id: `dev-a-${RAND()}` }, { title: 'Scale', id: `dev-b-${RAND()}` }],
73
+ programs: [
74
+ { name: 'CHF', deviceIds: ['dev-a'], status: 'Active' },
75
+ { name: 'Diabetes' }, // deviceIds and status are optional
76
+ ],
77
+ })
78
+
79
+ const createdPrograms = (await sdk.api.endusers.getOne(programsEnduser.id)).programs
80
+ record(
81
+ 'F: Enduser.programs round-trips on create, with and without deviceIds / status',
82
+ createdPrograms?.length === 2
83
+ && createdPrograms[0].name === 'CHF'
84
+ && JSON.stringify(createdPrograms[0].deviceIds) === JSON.stringify(['dev-a'])
85
+ && createdPrograms[0].status === 'Active'
86
+ && createdPrograms[1].name === 'Diabetes'
87
+ && createdPrograms[1].deviceIds === undefined
88
+ && createdPrograms[1].status === undefined,
89
+ `programs=${JSON.stringify(createdPrograms)}`,
90
+ )
91
+
92
+ await sdk.api.endusers.updateOne(
93
+ programsEnduser.id,
94
+ { programs: [{ name: 'CHF', deviceIds: ['dev-a', 'dev-b'] }] },
95
+ { replaceObjectFields: true },
96
+ )
97
+ const replacedPrograms = (await sdk.api.endusers.getOne(programsEnduser.id)).programs
98
+ record(
99
+ 'G: updating programs with replaceObjectFields replaces the whole list',
100
+ replacedPrograms?.length === 1
101
+ && replacedPrograms[0].name === 'CHF'
102
+ && JSON.stringify(replacedPrograms[0].deviceIds) === JSON.stringify(['dev-a', 'dev-b']),
103
+ `programs=${JSON.stringify(replacedPrograms)}`,
104
+ )
105
+
106
+ // name carries a non-optional validator inside the object validator, so it is required per item
107
+ let missingNameError = ''
108
+ try {
109
+ await sdk.api.endusers.updateOne(programsEnduser.id, { programs: [{ deviceIds: ['dev-a'] } as any] })
110
+ } catch (err: any) { missingNameError = err?.message ?? String(err) }
111
+ record(
112
+ 'H: a program entry without a name is rejected',
113
+ missingNameError.includes('name'),
114
+ `error=${JSON.stringify(missingNameError) || '(none — the write was ACCEPTED)'}`,
115
+ )
116
+
117
+ /* --- programs is staff-only: redacted from enduser sessions, and not enduser-updatable --- */
118
+
119
+ const { authToken } = await sdk.api.endusers.generate_auth_token({ id: programsEnduser.id })
120
+ const enduserSession = new EnduserSession({ host, authToken, businessId: tenant.businessId })
121
+ await enduserSession.refresh_session()
122
+
123
+ const selfRead = await enduserSession.api.endusers.getOne(programsEnduser.id)
124
+ record(
125
+ 'I: Enduser.programs is redacted from the enduser\'s own read of their record',
126
+ selfRead.programs === undefined,
127
+ `enduser-session programs=${JSON.stringify(selfRead.programs)}`,
128
+ )
129
+
130
+ let selfUpdateError = ''
131
+ try {
132
+ await enduserSession.api.endusers.updateOne(programsEnduser.id, { programs: [{ name: 'Self Assigned' }] })
133
+ } catch (err: any) { selfUpdateError = err?.message ?? String(err) }
134
+ const afterSelfUpdate = (await sdk.api.endusers.getOne(programsEnduser.id)).programs
135
+ record(
136
+ 'J: an enduser cannot update their own programs',
137
+ selfUpdateError.includes('cannot be updated by endusers')
138
+ && afterSelfUpdate?.length === 1 && afterSelfUpdate[0].name === 'CHF',
139
+ `error=${JSON.stringify(selfUpdateError) || '(none — the write was ACCEPTED)'}`
140
+ + ` programs=${JSON.stringify(afterSelfUpdate)}`,
141
+ )
142
+
143
+ /* ===================== Order Status Equals ===================== */
144
+
145
+ const ORDER_SOURCE = `ProgramFilterSource${RAND()}`
146
+
147
+ await sdk.api.automation_triggers.createOne({
148
+ event: { type: 'Order Status Equals', info: { source: ORDER_SOURCE, status: 'shipped', programs: ['CHF'] } },
149
+ action: { type: 'Add Tags', info: { tags: ['order-chf'] } },
150
+ status: 'Active',
151
+ title: `Order programs=[CHF] ${RAND()}`,
152
+ })
153
+ // no programs filter — the shape of every trigger that exists today; must match regardless
154
+ await sdk.api.automation_triggers.createOne({
155
+ event: { type: 'Order Status Equals', info: { source: ORDER_SOURCE, status: 'shipped' } },
156
+ action: { type: 'Add Tags', info: { tags: ['order-any'] } },
157
+ status: 'Active',
158
+ title: `Order programs unset ${RAND()}`,
159
+ })
160
+
161
+ const create_order = async (enduserId: string, programs?: { name: string }[]) => (
162
+ sdk.api.enduser_orders.createOne({
163
+ enduserId,
164
+ source: ORDER_SOURCE,
165
+ externalId: `ext-${RAND()}`,
166
+ title: 'Program filter order',
167
+ status: 'shipped',
168
+ ...(programs ? { programs } : {}),
169
+ })
170
+ )
171
+
172
+ const tags_after_order = async (programs: { name: string }[] | undefined) => {
173
+ const enduser = await sdk.api.endusers.createOne({ fname: 'Programs', lname: 'Order' })
174
+ await create_order(enduser.id, programs)
175
+ // the unfiltered trigger always fires, so its tag is the barrier that makes an absence meaningful
176
+ const after = await poll_for(
177
+ () => sdk.api.endusers.getOne(enduser.id),
178
+ e => !!e.tags?.includes('order-any'),
179
+ )
180
+ return after.tags ?? []
181
+ }
182
+
183
+ const orderMatching = await tags_after_order([{ name: 'CHF' }])
184
+ record(
185
+ 'A: Order Status Equals with programs=[CHF] fires for an order in program CHF',
186
+ orderMatching.includes('order-chf') && orderMatching.includes('order-any'),
187
+ `tags=${JSON.stringify(orderMatching)}`,
188
+ )
189
+
190
+ const orderNonMatching = await tags_after_order([{ name: 'Diabetes' }])
191
+ record(
192
+ 'B: Order Status Equals with programs=[CHF] does NOT fire for an order in program Diabetes',
193
+ !orderNonMatching.includes('order-chf') && orderNonMatching.includes('order-any'),
194
+ `tags=${JSON.stringify(orderNonMatching)}`,
195
+ )
196
+
197
+ const orderNoPrograms = await tags_after_order(undefined)
198
+ record(
199
+ 'C: Order Status Equals with programs=[CHF] does NOT fire for an order with no programs,'
200
+ + ' while the unfiltered trigger still does (back-compat)',
201
+ !orderNoPrograms.includes('order-chf') && orderNoPrograms.includes('order-any'),
202
+ `tags=${JSON.stringify(orderNoPrograms)}`,
203
+ )
204
+
205
+ /* ===================== Vital Update ===================== */
206
+
207
+ const configuration = await sdk.api.vital_configurations.createOne({
208
+ title: `Program filter SBP ${RAND()}`,
209
+ unit: 'SBP',
210
+ ranges: [
211
+ {
212
+ classification: 'High',
213
+ comparison: { type: 'Greater Than', value: 200 },
214
+ },
215
+ ],
216
+ })
217
+
218
+ await sdk.api.automation_triggers.createOne({
219
+ event: {
220
+ type: 'Vital Update',
221
+ info: { configurationIds: [configuration.id], classifications: ['High'], programs: ['CHF'] },
222
+ },
223
+ action: { type: 'Add Tags', info: { tags: ['vital-chf'] } },
224
+ status: 'Active',
225
+ title: `Vital programs=[CHF] ${RAND()}`,
226
+ })
227
+ await sdk.api.automation_triggers.createOne({
228
+ event: {
229
+ type: 'Vital Update',
230
+ info: { configurationIds: [configuration.id], classifications: ['High'] },
231
+ },
232
+ action: { type: 'Add Tags', info: { tags: ['vital-any'] } },
233
+ status: 'Active',
234
+ title: `Vital programs unset ${RAND()}`,
235
+ })
236
+
237
+ const tags_after_reading = async (programs: { name: string }[] | undefined) => {
238
+ const enduser = await sdk.api.endusers.createOne({ fname: 'Programs', lname: 'Vital' })
239
+ await sdk.api.enduser_observations.createOne({
240
+ category: 'vital-signs',
241
+ status: 'final',
242
+ enduserId: enduser.id,
243
+ measurement: { unit: 'SBP', value: 250 }, // High
244
+ timestamp: new Date(),
245
+ ...(programs ? { programs } : {}),
246
+ })
247
+ const after = await poll_for(
248
+ () => sdk.api.endusers.getOne(enduser.id),
249
+ e => !!e.tags?.includes('vital-any'),
250
+ )
251
+ return after.tags ?? []
252
+ }
253
+
254
+ const vitalMatching = await tags_after_reading([{ name: 'CHF' }])
255
+ record(
256
+ 'D: Vital Update with programs=[CHF] fires for a reading in program CHF',
257
+ vitalMatching.includes('vital-chf') && vitalMatching.includes('vital-any'),
258
+ `tags=${JSON.stringify(vitalMatching)}`,
259
+ )
260
+
261
+ const vitalNonMatching = await tags_after_reading([{ name: 'Diabetes' }])
262
+ record(
263
+ 'E: Vital Update with programs=[CHF] does NOT fire for a reading in program Diabetes,'
264
+ + ' while the unfiltered trigger still does (back-compat)',
265
+ !vitalNonMatching.includes('vital-chf') && vitalNonMatching.includes('vital-any'),
266
+ `tags=${JSON.stringify(vitalNonMatching)}`,
267
+ )
268
+
269
+ /* =============== Programs as a trigger enduserCondition (conditional logic) =============== */
270
+
271
+ // The `Programs` key is evaluated by evaluate_conditional_logic_for_enduser_fields, which is what
272
+ // handle_actions_for_triggers runs every trigger's enduserCondition through. These two checks are the
273
+ // end-to-end proof that a condition built in the UI actually gates a real trigger fire.
274
+ const CONDITION_FIELD = `ProgramConditionKey${RAND()}`
275
+
276
+ await sdk.api.automation_triggers.createOne({
277
+ event: { type: 'Field Equals', info: { field: CONDITION_FIELD, value: 'go' } },
278
+ action: { type: 'Add Tags', info: { tags: ['condition-chf'] } },
279
+ enduserCondition: { $and: [{ condition: { Programs: { $in: 'CHF' } } }] },
280
+ status: 'Active',
281
+ title: `Programs condition Is In CHF ${RAND()}`,
282
+ })
283
+ // the same event with no enduserCondition — the barrier that makes an absence above meaningful
284
+ await sdk.api.automation_triggers.createOne({
285
+ event: { type: 'Field Equals', info: { field: CONDITION_FIELD, value: 'go' } },
286
+ action: { type: 'Add Tags', info: { tags: ['condition-any'] } },
287
+ status: 'Active',
288
+ title: `Programs condition unset ${RAND()}`,
289
+ })
290
+
291
+ // `waitFor` is the tag that makes the read meaningful. For the positive check that is the
292
+ // conditioned trigger's own tag — the two triggers are dispatched by separate awaited calls, so the
293
+ // unconditioned trigger's tag can land first and polling on it alone would read too early. For the
294
+ // negative check, where there is no tag to wait for, the unconditioned trigger is the barrier.
295
+ const tags_after_create = async (programs: EnduserProgram[] | undefined, waitFor: string) => {
296
+ const enduser = await sdk.api.endusers.createOne({
297
+ fname: 'Programs',
298
+ lname: 'Condition',
299
+ fields: { [CONDITION_FIELD]: 'go' },
300
+ ...(programs ? { programs } : {}),
301
+ })
302
+ const after = await poll_for(
303
+ () => sdk.api.endusers.getOne(enduser.id),
304
+ e => !!e.tags?.includes(waitFor),
305
+ )
306
+ return after.tags ?? []
307
+ }
308
+
309
+ const conditionMatching = await tags_after_create([{ name: 'CHF', status: 'active' }], 'condition-chf')
310
+ record(
311
+ 'K: a trigger with a Programs Is In CHF enduserCondition fires for a patient in program CHF',
312
+ conditionMatching.includes('condition-chf') && conditionMatching.includes('condition-any'),
313
+ `tags=${JSON.stringify(conditionMatching)}`,
314
+ )
315
+
316
+ const conditionNonMatching = await tags_after_create(undefined, 'condition-any')
317
+ record(
318
+ 'L: the same trigger does NOT fire for a patient with no programs,'
319
+ + ' while the unconditioned trigger still does',
320
+ !conditionNonMatching.includes('condition-chf') && conditionNonMatching.includes('condition-any'),
321
+ `tags=${JSON.stringify(conditionNonMatching)}`,
322
+ )
323
+ } finally {
324
+ // Teardown BEFORE anything asserts — assert calls process.exit, which would strand this tenant.
325
+ if (tenant) { try { await tenant.teardown() } catch (e) { console.error('teardown failed', e) } }
326
+ }
327
+
328
+ return checks
329
+ }
330
+
331
+ /** Asserting wrapper, for standalone runs and for sequential use in the suite. */
332
+ export const programs_tests = async () => {
333
+ assert_checks('Programs', await programs_checks())
334
+ }
335
+
336
+ /** Enrolls this suite in the auto-discovered parallel pool — see run_discovered_isolated_suites. */
337
+ export const ISOLATED_SUITE: IsolatedSuite = { name: 'Programs', run: programs_checks }
338
+
339
+ // Allow running this test file independently
340
+ if (require.main === module) {
341
+ console.log(`🌐 Using API URL: ${host}`)
342
+ programs_tests()
343
+ .then(() => {
344
+ console.log("✅ Programs test suite completed successfully")
345
+ process.exit(0)
346
+ })
347
+ .catch((error) => {
348
+ console.error("❌ Programs test suite failed:", error)
349
+ process.exit(1)
350
+ })
351
+ }