magicbell-js 0.0.3 → 0.0.4

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 (292) hide show
  1. package/package.json +2 -1
  2. package/src/project-client/http/client.ts +71 -0
  3. package/src/project-client/http/environment.ts +3 -0
  4. package/src/project-client/http/error.ts +14 -0
  5. package/src/project-client/http/errors/validation-error.ts +25 -0
  6. package/src/project-client/http/handlers/handler-chain.ts +30 -0
  7. package/src/project-client/http/handlers/hook-handler.ts +78 -0
  8. package/src/project-client/http/handlers/request-validation-handler.ts +111 -0
  9. package/src/project-client/http/handlers/response-validation-handler.ts +203 -0
  10. package/src/project-client/http/handlers/retry-handler.ts +60 -0
  11. package/src/project-client/http/handlers/terminating-handler.ts +14 -0
  12. package/src/project-client/http/hooks/custom-hook.ts +25 -0
  13. package/src/project-client/http/hooks/hook.ts +41 -0
  14. package/src/project-client/http/index.ts +11 -0
  15. package/src/project-client/http/serialization/base-serializer.ts +139 -0
  16. package/src/project-client/http/serialization/header-serializer.ts +19 -0
  17. package/src/project-client/http/serialization/path-serializer.ts +12 -0
  18. package/src/project-client/http/serialization/query-serializer.ts +18 -0
  19. package/src/project-client/http/transport/request-builder.ts +242 -0
  20. package/src/project-client/http/transport/request-fetch-adapter.ts +131 -0
  21. package/src/project-client/http/transport/request.ts +222 -0
  22. package/src/project-client/http/transport/transport-hook-adapter.ts +91 -0
  23. package/src/project-client/http/transport/types.ts +50 -0
  24. package/src/project-client/http/types.ts +74 -0
  25. package/src/project-client/http/utils/content-type.ts +33 -0
  26. package/src/project-client/http/utils/line-decoder.ts +35 -0
  27. package/src/project-client/http/utils/response-matcher.ts +25 -0
  28. package/src/project-client/index.ts +94 -0
  29. package/src/project-client/services/base-service.ts +27 -0
  30. package/src/project-client/services/broadcasts/broadcasts-service.ts +115 -0
  31. package/src/project-client/services/broadcasts/index.ts +2 -0
  32. package/src/project-client/services/broadcasts/models/broadcast-collection.ts +54 -0
  33. package/src/project-client/services/broadcasts/models/broadcast-status.ts +60 -0
  34. package/src/project-client/services/broadcasts/models/broadcast.ts +143 -0
  35. package/src/project-client/services/broadcasts/models/email.ts +57 -0
  36. package/src/project-client/services/broadcasts/models/errors.ts +45 -0
  37. package/src/project-client/services/broadcasts/models/in-app.ts +57 -0
  38. package/src/project-client/services/broadcasts/models/index.ts +15 -0
  39. package/src/project-client/services/broadcasts/models/mobile-push.ts +57 -0
  40. package/src/project-client/services/broadcasts/models/overrides-channels.ts +82 -0
  41. package/src/project-client/services/broadcasts/models/overrides.ts +59 -0
  42. package/src/project-client/services/broadcasts/models/providers.ts +81 -0
  43. package/src/project-client/services/broadcasts/models/slack.ts +57 -0
  44. package/src/project-client/services/broadcasts/models/sms.ts +57 -0
  45. package/src/project-client/services/broadcasts/models/status-status.ts +7 -0
  46. package/src/project-client/services/broadcasts/models/summary.ts +51 -0
  47. package/src/project-client/services/broadcasts/models/web-push.ts +57 -0
  48. package/src/project-client/services/broadcasts/request-params.ts +5 -0
  49. package/src/project-client/services/channels/channels-service.ts +1017 -0
  50. package/src/project-client/services/channels/index.ts +2 -0
  51. package/src/project-client/services/channels/models/apns-token-collection.ts +54 -0
  52. package/src/project-client/services/channels/models/apns-token-installation-id.ts +6 -0
  53. package/src/project-client/services/channels/models/apns-token.ts +90 -0
  54. package/src/project-client/services/channels/models/category-delivery-config-channels.ts +57 -0
  55. package/src/project-client/services/channels/models/category-delivery-config.ts +73 -0
  56. package/src/project-client/services/channels/models/channel.ts +11 -0
  57. package/src/project-client/services/channels/models/discard-result.ts +51 -0
  58. package/src/project-client/services/channels/models/expo-token-collection.ts +54 -0
  59. package/src/project-client/services/channels/models/expo-token.ts +69 -0
  60. package/src/project-client/services/channels/models/fcm-token-collection.ts +54 -0
  61. package/src/project-client/services/channels/models/fcm-token-installation-id.ts +6 -0
  62. package/src/project-client/services/channels/models/fcm-token.ts +75 -0
  63. package/src/project-client/services/channels/models/inbox-token-response-collection.ts +59 -0
  64. package/src/project-client/services/channels/models/inbox-token-response.ts +75 -0
  65. package/src/project-client/services/channels/models/index.ts +24 -0
  66. package/src/project-client/services/channels/models/keys.ts +51 -0
  67. package/src/project-client/services/channels/models/oauth.ts +57 -0
  68. package/src/project-client/services/channels/models/slack-token-collection.ts +54 -0
  69. package/src/project-client/services/channels/models/slack-token-webhook.ts +45 -0
  70. package/src/project-client/services/channels/models/slack-token.ts +83 -0
  71. package/src/project-client/services/channels/models/teams-token-collection.ts +54 -0
  72. package/src/project-client/services/channels/models/teams-token-webhook.ts +45 -0
  73. package/src/project-client/services/channels/models/teams-token.ts +76 -0
  74. package/src/project-client/services/channels/models/web-push-token-collection.ts +54 -0
  75. package/src/project-client/services/channels/models/web-push-token.ts +77 -0
  76. package/src/project-client/services/channels/request-params.ts +45 -0
  77. package/src/project-client/services/common/index.ts +1 -0
  78. package/src/project-client/services/common/links.ts +57 -0
  79. package/src/project-client/services/events/events-service.ts +84 -0
  80. package/src/project-client/services/events/index.ts +2 -0
  81. package/src/project-client/services/events/models/event-collection.ts +54 -0
  82. package/src/project-client/services/events/models/event.ts +81 -0
  83. package/src/project-client/services/events/models/index.ts +2 -0
  84. package/src/project-client/services/events/request-params.ts +5 -0
  85. package/src/project-client/services/integrations/index.ts +2 -0
  86. package/src/project-client/services/integrations/integrations-service.ts +1965 -0
  87. package/src/project-client/services/integrations/models/apns-config-collection.ts +54 -0
  88. package/src/project-client/services/integrations/models/apns-config-payload.ts +81 -0
  89. package/src/project-client/services/integrations/models/apns-config.ts +64 -0
  90. package/src/project-client/services/integrations/models/awssns-config-collection.ts +54 -0
  91. package/src/project-client/services/integrations/models/awssns-config-payload.ts +45 -0
  92. package/src/project-client/services/integrations/models/awssns-config.ts +64 -0
  93. package/src/project-client/services/integrations/models/badge.ts +6 -0
  94. package/src/project-client/services/integrations/models/banner.ts +63 -0
  95. package/src/project-client/services/integrations/models/default-hover.ts +45 -0
  96. package/src/project-client/services/integrations/models/default-state.ts +45 -0
  97. package/src/project-client/services/integrations/models/default_.ts +90 -0
  98. package/src/project-client/services/integrations/models/dialog.ts +57 -0
  99. package/src/project-client/services/integrations/models/event-source-config-collection.ts +59 -0
  100. package/src/project-client/services/integrations/models/event-source-config-payload.ts +45 -0
  101. package/src/project-client/services/integrations/models/event-source-config.ts +64 -0
  102. package/src/project-client/services/integrations/models/expo-config-collection.ts +54 -0
  103. package/src/project-client/services/integrations/models/expo-config-payload.ts +45 -0
  104. package/src/project-client/services/integrations/models/expo-config.ts +64 -0
  105. package/src/project-client/services/integrations/models/fcm-config-collection.ts +54 -0
  106. package/src/project-client/services/integrations/models/fcm-config-payload.ts +105 -0
  107. package/src/project-client/services/integrations/models/fcm-config.ts +64 -0
  108. package/src/project-client/services/integrations/models/footer.ts +63 -0
  109. package/src/project-client/services/integrations/models/github-config-collection.ts +54 -0
  110. package/src/project-client/services/integrations/models/github-config-payload.ts +45 -0
  111. package/src/project-client/services/integrations/models/github-config.ts +64 -0
  112. package/src/project-client/services/integrations/models/header.ts +69 -0
  113. package/src/project-client/services/integrations/models/icon.ts +51 -0
  114. package/src/project-client/services/integrations/models/images.ts +45 -0
  115. package/src/project-client/services/integrations/models/inbox-config-collection.ts +54 -0
  116. package/src/project-client/services/integrations/models/inbox-config-payload.ts +60 -0
  117. package/src/project-client/services/integrations/models/inbox-config.ts +64 -0
  118. package/src/project-client/services/integrations/models/index.ts +75 -0
  119. package/src/project-client/services/integrations/models/integration-config-collection.ts +59 -0
  120. package/src/project-client/services/integrations/models/integration-config.ts +57 -0
  121. package/src/project-client/services/integrations/models/mailgun-config-collection.ts +54 -0
  122. package/src/project-client/services/integrations/models/mailgun-config-payload-from.ts +51 -0
  123. package/src/project-client/services/integrations/models/mailgun-config-payload.ts +70 -0
  124. package/src/project-client/services/integrations/models/mailgun-config.ts +64 -0
  125. package/src/project-client/services/integrations/models/notification.ts +61 -0
  126. package/src/project-client/services/integrations/models/payload-version.ts +6 -0
  127. package/src/project-client/services/integrations/models/ping-config-collection.ts +54 -0
  128. package/src/project-client/services/integrations/models/ping-config-payload.ts +45 -0
  129. package/src/project-client/services/integrations/models/ping-config.ts +64 -0
  130. package/src/project-client/services/integrations/models/region.ts +6 -0
  131. package/src/project-client/services/integrations/models/reply-to.ts +51 -0
  132. package/src/project-client/services/integrations/models/sendgrid-config-collection.ts +54 -0
  133. package/src/project-client/services/integrations/models/sendgrid-config-payload-from.ts +51 -0
  134. package/src/project-client/services/integrations/models/sendgrid-config-payload.ts +65 -0
  135. package/src/project-client/services/integrations/models/sendgrid-config.ts +64 -0
  136. package/src/project-client/services/integrations/models/ses-config-collection.ts +54 -0
  137. package/src/project-client/services/integrations/models/ses-config-payload-from.ts +51 -0
  138. package/src/project-client/services/integrations/models/ses-config-payload.ts +70 -0
  139. package/src/project-client/services/integrations/models/ses-config.ts +64 -0
  140. package/src/project-client/services/integrations/models/slack-config-collection.ts +54 -0
  141. package/src/project-client/services/integrations/models/slack-config-payload.ts +63 -0
  142. package/src/project-client/services/integrations/models/slack-config.ts +64 -0
  143. package/src/project-client/services/integrations/models/stripe-config-collection.ts +54 -0
  144. package/src/project-client/services/integrations/models/stripe-config-payload.ts +45 -0
  145. package/src/project-client/services/integrations/models/stripe-config.ts +64 -0
  146. package/src/project-client/services/integrations/models/templates-config-collection.ts +59 -0
  147. package/src/project-client/services/integrations/models/templates-config.ts +57 -0
  148. package/src/project-client/services/integrations/models/theme.ts +89 -0
  149. package/src/project-client/services/integrations/models/twilio-config-collection.ts +54 -0
  150. package/src/project-client/services/integrations/models/twilio-config-payload.ts +75 -0
  151. package/src/project-client/services/integrations/models/twilio-config.ts +64 -0
  152. package/src/project-client/services/integrations/models/type_.ts +5 -0
  153. package/src/project-client/services/integrations/models/unread-hover.ts +45 -0
  154. package/src/project-client/services/integrations/models/unread-state.ts +45 -0
  155. package/src/project-client/services/integrations/models/unread.ts +66 -0
  156. package/src/project-client/services/integrations/models/unseen-badge.ts +45 -0
  157. package/src/project-client/services/integrations/models/unseen-hover.ts +45 -0
  158. package/src/project-client/services/integrations/models/unseen-state.ts +45 -0
  159. package/src/project-client/services/integrations/models/unseen.ts +66 -0
  160. package/src/project-client/services/integrations/models/webpush-config-collection.ts +54 -0
  161. package/src/project-client/services/integrations/models/webpush-config-payload.ts +51 -0
  162. package/src/project-client/services/integrations/models/webpush-config.ts +64 -0
  163. package/src/project-client/services/integrations/request-params.ts +5 -0
  164. package/src/project-client/services/jwt/index.ts +2 -0
  165. package/src/project-client/services/jwt/jwt-service.ts +233 -0
  166. package/src/project-client/services/jwt/models/access-token-collection.ts +54 -0
  167. package/src/project-client/services/jwt/models/access-token.ts +69 -0
  168. package/src/project-client/services/jwt/models/create-project-token-request.ts +51 -0
  169. package/src/project-client/services/jwt/models/create-token-response.ts +63 -0
  170. package/src/project-client/services/jwt/models/create-user-token-request.ts +63 -0
  171. package/src/project-client/services/jwt/models/discard-token-response.ts +51 -0
  172. package/src/project-client/services/jwt/models/index.ts +6 -0
  173. package/src/project-client/services/jwt/request-params.ts +11 -0
  174. package/src/project-client/services/notifications/index.ts +2 -0
  175. package/src/project-client/services/notifications/models/delivery-plan-collection.ts +54 -0
  176. package/src/project-client/services/notifications/models/delivery-plan.ts +93 -0
  177. package/src/project-client/services/notifications/models/index.ts +2 -0
  178. package/src/project-client/services/notifications/notifications-service.ts +44 -0
  179. package/src/project-client/services/users/index.ts +2 -0
  180. package/src/project-client/services/users/models/index.ts +2 -0
  181. package/src/project-client/services/users/models/user-collection.ts +54 -0
  182. package/src/project-client/services/users/models/user.ts +99 -0
  183. package/src/project-client/services/users/request-params.ts +6 -0
  184. package/src/project-client/services/users/users-service.ts +117 -0
  185. package/src/project-client.ts +1 -0
  186. package/src/user-client/http/client.ts +71 -0
  187. package/src/user-client/http/environment.ts +3 -0
  188. package/src/user-client/http/error.ts +14 -0
  189. package/src/user-client/http/errors/validation-error.ts +25 -0
  190. package/src/user-client/http/handlers/handler-chain.ts +30 -0
  191. package/src/user-client/http/handlers/hook-handler.ts +78 -0
  192. package/src/user-client/http/handlers/request-validation-handler.ts +111 -0
  193. package/src/user-client/http/handlers/response-validation-handler.ts +203 -0
  194. package/src/user-client/http/handlers/retry-handler.ts +60 -0
  195. package/src/user-client/http/handlers/terminating-handler.ts +14 -0
  196. package/src/user-client/http/hooks/custom-hook.ts +25 -0
  197. package/src/user-client/http/hooks/hook.ts +41 -0
  198. package/src/user-client/http/index.ts +11 -0
  199. package/src/user-client/http/serialization/base-serializer.ts +139 -0
  200. package/src/user-client/http/serialization/header-serializer.ts +19 -0
  201. package/src/user-client/http/serialization/path-serializer.ts +12 -0
  202. package/src/user-client/http/serialization/query-serializer.ts +18 -0
  203. package/src/user-client/http/transport/request-builder.ts +242 -0
  204. package/src/user-client/http/transport/request-fetch-adapter.ts +131 -0
  205. package/src/user-client/http/transport/request.ts +222 -0
  206. package/src/user-client/http/transport/transport-hook-adapter.ts +91 -0
  207. package/src/user-client/http/transport/types.ts +50 -0
  208. package/src/user-client/http/types.ts +74 -0
  209. package/src/user-client/http/utils/content-type.ts +33 -0
  210. package/src/user-client/http/utils/line-decoder.ts +35 -0
  211. package/src/user-client/http/utils/response-matcher.ts +25 -0
  212. package/src/user-client/index.ts +54 -0
  213. package/src/user-client/services/base-service.ts +27 -0
  214. package/src/user-client/services/channels/channels-service.ts +1020 -0
  215. package/src/user-client/services/channels/index.ts +2 -0
  216. package/src/user-client/services/channels/models/apns-token-collection.ts +54 -0
  217. package/src/user-client/services/channels/models/apns-token-installation-id.ts +6 -0
  218. package/src/user-client/services/channels/models/apns-token-payload-installation-id.ts +6 -0
  219. package/src/user-client/services/channels/models/apns-token-payload.ts +66 -0
  220. package/src/user-client/services/channels/models/apns-token.ts +90 -0
  221. package/src/user-client/services/channels/models/discard-result.ts +51 -0
  222. package/src/user-client/services/channels/models/expo-token-collection.ts +54 -0
  223. package/src/user-client/services/channels/models/expo-token-payload.ts +45 -0
  224. package/src/user-client/services/channels/models/expo-token.ts +69 -0
  225. package/src/user-client/services/channels/models/fcm-token-collection.ts +54 -0
  226. package/src/user-client/services/channels/models/fcm-token-installation-id.ts +6 -0
  227. package/src/user-client/services/channels/models/fcm-token-payload-installation-id.ts +6 -0
  228. package/src/user-client/services/channels/models/fcm-token-payload.ts +51 -0
  229. package/src/user-client/services/channels/models/fcm-token.ts +75 -0
  230. package/src/user-client/services/channels/models/inbox-token-response-collection.ts +59 -0
  231. package/src/user-client/services/channels/models/inbox-token-response.ts +75 -0
  232. package/src/user-client/services/channels/models/inbox-token.ts +51 -0
  233. package/src/user-client/services/channels/models/index.ts +33 -0
  234. package/src/user-client/services/channels/models/slack-token-collection.ts +54 -0
  235. package/src/user-client/services/channels/models/slack-token-oauth.ts +57 -0
  236. package/src/user-client/services/channels/models/slack-token-payload-oauth.ts +57 -0
  237. package/src/user-client/services/channels/models/slack-token-payload-webhook.ts +45 -0
  238. package/src/user-client/services/channels/models/slack-token-payload.ts +64 -0
  239. package/src/user-client/services/channels/models/slack-token-webhook.ts +45 -0
  240. package/src/user-client/services/channels/models/slack-token.ts +88 -0
  241. package/src/user-client/services/channels/models/teams-token-collection.ts +54 -0
  242. package/src/user-client/services/channels/models/teams-token-payload-webhook.ts +45 -0
  243. package/src/user-client/services/channels/models/teams-token-payload.ts +52 -0
  244. package/src/user-client/services/channels/models/teams-token-webhook.ts +45 -0
  245. package/src/user-client/services/channels/models/teams-token.ts +76 -0
  246. package/src/user-client/services/channels/models/web-push-token-collection.ts +54 -0
  247. package/src/user-client/services/channels/models/web-push-token-keys.ts +51 -0
  248. package/src/user-client/services/channels/models/web-push-token-payload-keys.ts +51 -0
  249. package/src/user-client/services/channels/models/web-push-token.ts +82 -0
  250. package/src/user-client/services/channels/request-params.ts +41 -0
  251. package/src/user-client/services/common/index.ts +2 -0
  252. package/src/user-client/services/common/links.ts +57 -0
  253. package/src/user-client/services/common/web-push-token-payload.ts +58 -0
  254. package/src/user-client/services/integrations/index.ts +2 -0
  255. package/src/user-client/services/integrations/integrations-service.ts +278 -0
  256. package/src/user-client/services/integrations/models/authed-user.ts +75 -0
  257. package/src/user-client/services/integrations/models/banner.ts +63 -0
  258. package/src/user-client/services/integrations/models/default-hover.ts +45 -0
  259. package/src/user-client/services/integrations/models/default-state.ts +45 -0
  260. package/src/user-client/services/integrations/models/default_.ts +90 -0
  261. package/src/user-client/services/integrations/models/dialog.ts +57 -0
  262. package/src/user-client/services/integrations/models/enterprise.ts +51 -0
  263. package/src/user-client/services/integrations/models/footer.ts +63 -0
  264. package/src/user-client/services/integrations/models/header.ts +69 -0
  265. package/src/user-client/services/integrations/models/icon.ts +51 -0
  266. package/src/user-client/services/integrations/models/images.ts +45 -0
  267. package/src/user-client/services/integrations/models/inbox-config-payload.ts +60 -0
  268. package/src/user-client/services/integrations/models/incoming-webhook.ts +57 -0
  269. package/src/user-client/services/integrations/models/index.ts +29 -0
  270. package/src/user-client/services/integrations/models/slack-finish-install-response.ts +57 -0
  271. package/src/user-client/services/integrations/models/slack-installation.ts +136 -0
  272. package/src/user-client/services/integrations/models/slack-start-install-response-content.ts +57 -0
  273. package/src/user-client/services/integrations/models/slack-start-install.ts +63 -0
  274. package/src/user-client/services/integrations/models/team.ts +51 -0
  275. package/src/user-client/services/integrations/models/templates-installation.ts +57 -0
  276. package/src/user-client/services/integrations/models/theme-notification.ts +61 -0
  277. package/src/user-client/services/integrations/models/theme.ts +94 -0
  278. package/src/user-client/services/integrations/models/unread-hover.ts +45 -0
  279. package/src/user-client/services/integrations/models/unread-state.ts +45 -0
  280. package/src/user-client/services/integrations/models/unread.ts +66 -0
  281. package/src/user-client/services/integrations/models/unseen-badge.ts +45 -0
  282. package/src/user-client/services/integrations/models/unseen-hover.ts +45 -0
  283. package/src/user-client/services/integrations/models/unseen-state.ts +45 -0
  284. package/src/user-client/services/integrations/models/unseen.ts +66 -0
  285. package/src/user-client/services/integrations/models/web-push-start-installation-response.ts +51 -0
  286. package/src/user-client/services/notifications/index.ts +2 -0
  287. package/src/user-client/services/notifications/models/index.ts +2 -0
  288. package/src/user-client/services/notifications/models/notification-collection.ts +54 -0
  289. package/src/user-client/services/notifications/models/notification.ts +129 -0
  290. package/src/user-client/services/notifications/notifications-service.ts +189 -0
  291. package/src/user-client/services/notifications/request-params.ts +7 -0
  292. package/src/user-client.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "magicbell-js",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "OpenAPI 3.1.0 Specification for MagicBell API.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -40,6 +40,7 @@
40
40
  },
41
41
  "files": [
42
42
  "dist",
43
+ "src",
43
44
  "README.md",
44
45
  "/project-client/package.json",
45
46
  "/user-client/package.json"
@@ -0,0 +1,71 @@
1
+ import { RequestHandlerChain } from './handlers/handler-chain.js';
2
+ import { HookHandler } from './handlers/hook-handler.js';
3
+ import { RequestValidationHandler } from './handlers/request-validation-handler.js';
4
+ import { ResponseValidationHandler } from './handlers/response-validation-handler.js';
5
+ import { RetryHandler } from './handlers/retry-handler.js';
6
+ import { TerminatingHandler } from './handlers/terminating-handler.js';
7
+ import { CustomHook } from './hooks/custom-hook.js';
8
+ import { Request } from './transport/request.js';
9
+ import { HttpResponse, SdkConfig } from './types.js';
10
+
11
+ export class HttpClient {
12
+ private readonly requestHandlerChain = new RequestHandlerChain();
13
+
14
+ constructor(private config: SdkConfig, hook = new CustomHook()) {
15
+ this.requestHandlerChain.addHandler(new ResponseValidationHandler());
16
+ this.requestHandlerChain.addHandler(new RequestValidationHandler());
17
+ this.requestHandlerChain.addHandler(new RetryHandler());
18
+ this.requestHandlerChain.addHandler(new HookHandler(hook));
19
+ this.requestHandlerChain.addHandler(new TerminatingHandler());
20
+ }
21
+
22
+ call<T>(request: Request): Promise<HttpResponse<T>> {
23
+ return this.requestHandlerChain.callChain(request);
24
+ }
25
+
26
+ async *stream<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
27
+ yield* this.requestHandlerChain.streamChain(request);
28
+ }
29
+
30
+ public async callPaginated<FullResponse, Page>(request: Request<Page>): Promise<HttpResponse<Page>> {
31
+ const response = await this.call<FullResponse>(request as any);
32
+
33
+ if (!response.data) {
34
+ throw new Error('no response data to paginate through');
35
+ }
36
+
37
+ return {
38
+ ...response,
39
+ data: this.getPage<FullResponse, Page>(request, response.data),
40
+ };
41
+ }
42
+
43
+ setBaseUrl(url: string): void {
44
+ this.config.baseUrl = url;
45
+ }
46
+
47
+ setConfig(config: SdkConfig): void {
48
+ this.config = config;
49
+ }
50
+
51
+ private getPage<FullResponse, Page>(request: Request<Page>, data: FullResponse): Page {
52
+ if (!request.pagination) {
53
+ throw new Error('getPage called for request without pagination property');
54
+ }
55
+
56
+ let curr: any = data;
57
+ for (const segment of request.pagination?.pagePath || []) {
58
+ curr = curr[segment];
59
+ }
60
+
61
+ const page = request.pagination?.pageSchema?.parse(curr);
62
+ if (!page) {
63
+ throw new Error(
64
+ `error getting page data. Curr: ${JSON.stringify(curr)}. PagePath: ${
65
+ request.pagination?.pagePath
66
+ }. Data: ${JSON.stringify(data)}`,
67
+ );
68
+ }
69
+ return page;
70
+ }
71
+ }
@@ -0,0 +1,3 @@
1
+ export enum Environment {
2
+ DEFAULT = 'https://api.magicbell.com/v2',
3
+ }
@@ -0,0 +1,14 @@
1
+ import { HttpMetadata } from './types.js';
2
+
3
+ export class HttpError extends Error {
4
+ public readonly error: string;
5
+ public readonly metadata: HttpMetadata;
6
+ public readonly raw?: ArrayBuffer;
7
+
8
+ constructor(metadata: HttpMetadata, raw?: ArrayBuffer, error?: string) {
9
+ super(error);
10
+ this.error = metadata.statusText;
11
+ this.metadata = metadata;
12
+ this.raw = raw;
13
+ }
14
+ }
@@ -0,0 +1,25 @@
1
+ import { ZodError } from 'zod';
2
+
3
+ export class ValidationError extends Error {
4
+ public readonly error: string;
5
+
6
+ constructor(zodError: ZodError, object: any) {
7
+ let actual: string;
8
+ try {
9
+ actual = JSON.stringify(object, undefined, 2);
10
+ } catch (err) {
11
+ actual = object;
12
+ }
13
+
14
+ const error = [
15
+ `ValidationError:`,
16
+ ...zodError.issues.map((issue) => ` Property: ${issue.path.join('.')}. Message: ${issue.message}`),
17
+ ' Validated:',
18
+ ...actual.split('\n').map((line) => ` ${line}`),
19
+ ].join('\n');
20
+
21
+ super(error);
22
+
23
+ this.error = error;
24
+ }
25
+ }
@@ -0,0 +1,30 @@
1
+ import { Request } from '../transport/request.js';
2
+ import { HttpResponse, RequestHandler } from '../types.js';
3
+
4
+ export class RequestHandlerChain {
5
+ private readonly handlers: RequestHandler[] = [];
6
+
7
+ addHandler(handler: RequestHandler): void {
8
+ if (this.handlers.length > 0) {
9
+ const previousHandler = this.handlers[this.handlers.length - 1];
10
+ previousHandler.next = handler;
11
+ }
12
+ this.handlers.push(handler);
13
+ }
14
+
15
+ async callChain<T>(request: Request): Promise<HttpResponse<T>> {
16
+ if (!this.handlers.length) {
17
+ throw new Error('No handlers added to the chain');
18
+ }
19
+
20
+ return this.handlers[0].handle<T>(request);
21
+ }
22
+
23
+ async *streamChain<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
24
+ if (!this.handlers.length) {
25
+ throw new Error('No handlers added to the chain');
26
+ }
27
+
28
+ yield* this.handlers[0].stream<T>(request);
29
+ }
30
+ }
@@ -0,0 +1,78 @@
1
+ import { HttpError } from '../error.js';
2
+ import { Hook } from '../hooks/hook.js';
3
+ import { Request } from '../transport/request.js';
4
+ import { TransportHookAdapter } from '../transport/transport-hook-adapter.js';
5
+ import { ContentType, HttpResponse, RequestHandler } from '../types.js';
6
+ import { getContentTypeDefinition } from '../utils/content-type.js';
7
+
8
+ export class HookHandler implements RequestHandler {
9
+ next?: RequestHandler;
10
+
11
+ constructor(private readonly hook: Hook) {}
12
+
13
+ async handle<T>(request: Request): Promise<HttpResponse<T>> {
14
+ if (!this.next) {
15
+ throw new Error('No next handler set in hook handler.');
16
+ }
17
+
18
+ const hook = new TransportHookAdapter<T>();
19
+
20
+ const hookParams = this.getHookParams<T>(request);
21
+
22
+ const nextRequest = await hook.beforeRequest(request, hookParams);
23
+
24
+ const response = await this.next.handle<T>(nextRequest);
25
+
26
+ if (response.metadata.status < 400) {
27
+ return await hook.afterResponse(nextRequest, response, hookParams);
28
+ }
29
+
30
+ const rawContentType = response.metadata.headers['content-type']?.toLocaleLowerCase() || '';
31
+ const contentType = getContentTypeDefinition(rawContentType);
32
+ const statusCode = response.metadata.status;
33
+
34
+ const error = request.errors.find((error) => {
35
+ return error.contentType === contentType && error.status === statusCode;
36
+ });
37
+
38
+ if (error?.error) {
39
+ const decodedBody = new TextDecoder().decode(response.raw);
40
+ const json = JSON.parse(decodedBody);
41
+ throw new error.error((json as any)?.message || '', json);
42
+ }
43
+
44
+ const decodedBody = new TextDecoder().decode(response.raw);
45
+ throw new HttpError(
46
+ response.metadata,
47
+ response.raw,
48
+ `Unexpected response body for error status.\nStatusCode: ${response.metadata.status}\nBody: ${decodedBody}`,
49
+ );
50
+ }
51
+
52
+ async *stream<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
53
+ if (!this.next) {
54
+ throw new Error('No next handler set in hook handler.');
55
+ }
56
+
57
+ const hook = new TransportHookAdapter<T>();
58
+
59
+ const hookParams = this.getHookParams<T>(request);
60
+
61
+ const nextRequest = await hook.beforeRequest(request, hookParams);
62
+
63
+ const stream = this.next.stream<T>(nextRequest);
64
+
65
+ for await (const response of stream) {
66
+ if (response.metadata.status < 400) {
67
+ yield await hook.afterResponse(nextRequest, response, hookParams);
68
+ } else {
69
+ throw await hook.onError(nextRequest, response, hookParams);
70
+ }
71
+ }
72
+ }
73
+
74
+ private getHookParams<T>(_request: Request): Map<string, string> {
75
+ const hookParams: Map<string, string> = new Map();
76
+ return hookParams;
77
+ }
78
+ }
@@ -0,0 +1,111 @@
1
+ import { ZodError } from 'zod';
2
+
3
+ import { ValidationError } from '../errors/validation-error.js';
4
+ import { Request } from '../transport/request.js';
5
+ import { ContentType, HttpResponse, RequestHandler } from '../types.js';
6
+
7
+ export class RequestValidationHandler implements RequestHandler {
8
+ next?: RequestHandler;
9
+
10
+ async handle<T>(request: Request): Promise<HttpResponse<T>> {
11
+ if (!this.next) {
12
+ throw new Error('No next handler set in ContentTypeHandler.');
13
+ }
14
+
15
+ this.validateRequest(request);
16
+
17
+ return this.next.handle<T>(request);
18
+ }
19
+
20
+ async *stream<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
21
+ if (!this.next) {
22
+ throw new Error('No next handler set in ContentTypeHandler.');
23
+ }
24
+
25
+ this.validateRequest(request);
26
+
27
+ yield* this.next.stream<T>(request);
28
+ }
29
+
30
+ validateRequest(request: Request): void {
31
+ if (request.requestContentType === ContentType.Json) {
32
+ try {
33
+ const parsedBody = request.requestSchema?.parse(request.body);
34
+ request.body = JSON.stringify(parsedBody);
35
+ } catch (error) {
36
+ if (error instanceof ZodError) {
37
+ throw new ValidationError(error, request.body);
38
+ }
39
+ throw error;
40
+ }
41
+ } else if (
42
+ request.requestContentType === ContentType.Xml ||
43
+ request.requestContentType === ContentType.Text ||
44
+ request.requestContentType === ContentType.Image ||
45
+ request.requestContentType === ContentType.Binary
46
+ ) {
47
+ request.body = request.body;
48
+ } else if (request.requestContentType === ContentType.FormUrlEncoded) {
49
+ request.body = this.toFormUrlEncoded(request);
50
+ } else if (request.requestContentType === ContentType.MultipartFormData) {
51
+ request.body = this.toFormData(request.body);
52
+ } else {
53
+ request.body = JSON.stringify(request.requestSchema?.parse(request.body));
54
+ }
55
+ }
56
+
57
+ toFormUrlEncoded(request: Request): string {
58
+ if (request.body === undefined) {
59
+ return '';
60
+ }
61
+
62
+ if (typeof request.body === 'string') {
63
+ return request.body;
64
+ }
65
+
66
+ if (request.body instanceof URLSearchParams) {
67
+ return request.body.toString();
68
+ }
69
+
70
+ const validatedBody = request.requestSchema?.parse(request.body);
71
+
72
+ if (validatedBody instanceof FormData) {
73
+ const params = new URLSearchParams();
74
+ validatedBody.forEach((value, key) => {
75
+ if (value != null) {
76
+ params.append(key, value.toString());
77
+ }
78
+ });
79
+ return params.toString();
80
+ }
81
+
82
+ if (typeof validatedBody === 'object' && !Array.isArray(validatedBody)) {
83
+ const params = new URLSearchParams();
84
+ for (const [key, value] of Object.entries(validatedBody)) {
85
+ if (value != null) {
86
+ params.append(key, `${value}`);
87
+ }
88
+ }
89
+ return params.toString();
90
+ }
91
+
92
+ return '';
93
+ }
94
+
95
+ toFormData(body: Record<string, any>): FormData | undefined {
96
+ const formData = new FormData();
97
+
98
+ Object.keys(body).forEach((key: any) => {
99
+ const value: any = body[key];
100
+ if (Array.isArray(value)) {
101
+ value.forEach((v, i) => formData.append(`${key}[${i}]`, v));
102
+ } else if (value instanceof ArrayBuffer) {
103
+ formData.append(key, new Blob([value]));
104
+ } else {
105
+ formData.append(key, value);
106
+ }
107
+ });
108
+
109
+ return formData;
110
+ }
111
+ }
@@ -0,0 +1,203 @@
1
+ import { ZodUndefined } from 'zod';
2
+
3
+ import { Request } from '../transport/request.js';
4
+ import { ResponseDefinition } from '../transport/types.js';
5
+ import { ContentType, HttpResponse, RequestHandler } from '../types.js';
6
+ import { ResponseMatcher } from '../utils/response-matcher.js';
7
+
8
+ export class ResponseValidationHandler implements RequestHandler {
9
+ next?: RequestHandler;
10
+
11
+ async handle<T>(request: Request): Promise<HttpResponse<T>> {
12
+ const response = await this.next!.handle<T>(request);
13
+
14
+ return this.decodeBody<T>(request, response);
15
+ }
16
+
17
+ async *stream<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
18
+ const stream = this.next!.stream<T>(request);
19
+
20
+ for await (const response of stream) {
21
+ const responseChunks = this.splitByDataChunks<T>(response);
22
+ for (const chunk of responseChunks) {
23
+ yield this.decodeBody<T>(request, chunk);
24
+ }
25
+ }
26
+ }
27
+
28
+ private splitByDataChunks<T>(response: HttpResponse<T>): HttpResponse<T>[] {
29
+ if (!response.metadata.headers['content-type'].includes('text/event-stream')) {
30
+ return [response];
31
+ }
32
+
33
+ const text = new TextDecoder().decode(response.raw);
34
+ const encoder = new TextEncoder();
35
+ return text
36
+ .split('\n')
37
+ .filter((line) => line.startsWith('data: '))
38
+ .map((part) => ({
39
+ ...response,
40
+ raw: encoder.encode(part),
41
+ }));
42
+ }
43
+
44
+ private decodeBody<T>(request: Request, response: HttpResponse<T>): HttpResponse<T> {
45
+ const responseMatcher = new ResponseMatcher(request.responses);
46
+ const responseDefinition = responseMatcher.getResponseDefinition(response);
47
+
48
+ if (!responseDefinition || !this.hasContent(responseDefinition, response)) {
49
+ return response;
50
+ }
51
+
52
+ const contentType = responseDefinition.contentType;
53
+ const contentTypeHandlers: {
54
+ [key: string]: (req: Request, resDef: ResponseDefinition, res: HttpResponse<T>) => HttpResponse<T>;
55
+ } = {
56
+ [ContentType.Binary]: this.decodeFile,
57
+ [ContentType.Image]: this.decodeFile,
58
+ [ContentType.MultipartFormData]: this.decodeMultipartFormData,
59
+ [ContentType.Text]: this.decodeText,
60
+ [ContentType.Xml]: this.decodeText,
61
+ [ContentType.FormUrlEncoded]: this.decodeFormUrlEncoded,
62
+ [ContentType.EventStream]: this.decodeEventStream,
63
+ };
64
+
65
+ if (contentTypeHandlers[contentType]) {
66
+ return contentTypeHandlers[contentType].call(this, request, responseDefinition, response);
67
+ }
68
+
69
+ if (response.metadata.headers['content-type']?.includes('text/event-stream')) {
70
+ return this.decodeEventStream(request, responseDefinition, response);
71
+ }
72
+
73
+ return this.decodeJson(request, responseDefinition, response);
74
+ }
75
+
76
+ private decodeFile<T>(
77
+ request: Request,
78
+ responseDefinition: ResponseDefinition,
79
+ response: HttpResponse<T>,
80
+ ): HttpResponse<T> {
81
+ return {
82
+ ...response,
83
+ data: this.validate<T>(request, responseDefinition, response.raw),
84
+ };
85
+ }
86
+
87
+ private decodeMultipartFormData<T>(
88
+ request: Request,
89
+ responseDefinition: ResponseDefinition,
90
+ response: HttpResponse<T>,
91
+ ): HttpResponse<T> {
92
+ const formData = this.fromFormData(response.raw);
93
+ return {
94
+ ...response,
95
+ data: this.validate<T>(request, responseDefinition, formData),
96
+ };
97
+ }
98
+
99
+ private decodeText<T>(
100
+ request: Request,
101
+ responseDefinition: ResponseDefinition,
102
+ response: HttpResponse<T>,
103
+ ): HttpResponse<T> {
104
+ const decodedBody = new TextDecoder().decode(response.raw);
105
+ return {
106
+ ...response,
107
+ data: this.validate<T>(request, responseDefinition, decodedBody),
108
+ };
109
+ }
110
+
111
+ private decodeFormUrlEncoded<T>(
112
+ request: Request,
113
+ responseDefinition: ResponseDefinition,
114
+ response: HttpResponse<T>,
115
+ ): HttpResponse<T> {
116
+ const decodedBody = new TextDecoder().decode(response.raw);
117
+ const urlEncoded = this.fromUrlEncoded(decodedBody);
118
+ return {
119
+ ...response,
120
+ data: this.validate<T>(request, responseDefinition, urlEncoded),
121
+ };
122
+ }
123
+
124
+ private decodeEventStream<T>(
125
+ request: Request,
126
+ responseDefinition: ResponseDefinition,
127
+ response: HttpResponse<T>,
128
+ ): HttpResponse<T> {
129
+ let decodedBody = new TextDecoder().decode(response.raw);
130
+ if (decodedBody.startsWith('data: ')) {
131
+ decodedBody = decodedBody.substring(6);
132
+ }
133
+ // Note: this assumes that the content of data is a valid JSON string
134
+ const json = JSON.parse(decodedBody);
135
+ return {
136
+ ...response,
137
+ data: this.validate<T>(request, responseDefinition, json),
138
+ };
139
+ }
140
+
141
+ private decodeJson<T>(
142
+ request: Request,
143
+ responseDefinition: ResponseDefinition,
144
+ response: HttpResponse<T>,
145
+ ): HttpResponse<T> {
146
+ const decodedBody = new TextDecoder().decode(response.raw);
147
+ const json = JSON.parse(decodedBody);
148
+ return {
149
+ ...response,
150
+ data: this.validate<T>(request, responseDefinition, json),
151
+ };
152
+ }
153
+
154
+ private validate<T>(request: Request, response: ResponseDefinition, data: any): T {
155
+ if (request.validation?.responseValidation) {
156
+ return response.schema.parse(data);
157
+ }
158
+ return data;
159
+ }
160
+
161
+ private hasContent<T>(responseDefinition: ResponseDefinition, response: HttpResponse<T>): boolean {
162
+ return (
163
+ !!responseDefinition.schema &&
164
+ !(responseDefinition.schema instanceof ZodUndefined) &&
165
+ response.metadata.status !== 204
166
+ );
167
+ }
168
+
169
+ private fromUrlEncoded(urlEncodedData: string): object {
170
+ const pairs = urlEncodedData.split('&');
171
+ const result: Record<string, string> = {};
172
+
173
+ pairs.forEach((pair) => {
174
+ const [key, value] = pair.split('=');
175
+ if (key && value !== undefined) {
176
+ result[decodeURIComponent(key)] = decodeURIComponent(value);
177
+ }
178
+ });
179
+
180
+ return result;
181
+ }
182
+
183
+ private fromFormData(arrayBuffer: ArrayBuffer): Record<string, string> {
184
+ const decoder = new TextDecoder();
185
+ const text = decoder.decode(arrayBuffer);
186
+
187
+ const boundary = text.split('\r\n')[0];
188
+ const parts = text.split(boundary).slice(1, -1);
189
+
190
+ const formDataObj: Record<string, string> = {};
191
+
192
+ parts.forEach((part) => {
193
+ const [header, value] = part.split('\r\n\r\n');
194
+ const nameMatch = header.match(/name="([^"]+)"/);
195
+ if (nameMatch) {
196
+ const name = nameMatch[1].trim();
197
+ formDataObj[name] = value?.trim() || '';
198
+ }
199
+ });
200
+
201
+ return formDataObj;
202
+ }
203
+ }
@@ -0,0 +1,60 @@
1
+ import { HttpError } from '../error.js';
2
+ import { Request } from '../transport/request.js';
3
+ import { HttpResponse, RequestHandler } from '../types.js';
4
+
5
+ export class RetryHandler implements RequestHandler {
6
+ next?: RequestHandler;
7
+
8
+ async handle<T>(request: Request): Promise<HttpResponse<T>> {
9
+ if (!this.next) {
10
+ throw new Error('No next handler set in retry handler.');
11
+ }
12
+
13
+ for (let attempt = 1; attempt <= request.retry.attempts; attempt++) {
14
+ try {
15
+ return await this.next.handle<T>(request);
16
+ } catch (error: any) {
17
+ if (!this.shouldRetry(error) || attempt === request.retry.attempts) {
18
+ throw error;
19
+ }
20
+ await this.delay(request.retry.delayMs);
21
+ }
22
+ }
23
+
24
+ throw new Error('Error retrying request.');
25
+ }
26
+
27
+ async *stream<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
28
+ if (!this.next) {
29
+ throw new Error('No next handler set in retry handler.');
30
+ }
31
+
32
+ for (let attempt = 1; attempt <= request.retry.attempts; attempt++) {
33
+ try {
34
+ yield* this.next.stream<T>(request);
35
+ return;
36
+ } catch (error: any) {
37
+ if (!this.shouldRetry(error) || attempt === request.retry.attempts) {
38
+ throw error;
39
+ }
40
+ await this.delay(request.retry.delayMs);
41
+ }
42
+ }
43
+
44
+ throw new Error('Error retrying request.');
45
+ }
46
+
47
+ private shouldRetry(error: Error): boolean {
48
+ return error instanceof HttpError && (error.metadata.status >= 500 || error.metadata.status === 408);
49
+ }
50
+
51
+ private delay(delayMs: number | undefined): Promise<void> {
52
+ if (!delayMs) {
53
+ return Promise.resolve();
54
+ }
55
+
56
+ return new Promise((resolve, reject) => {
57
+ setTimeout(() => resolve(), delayMs);
58
+ });
59
+ }
60
+ }
@@ -0,0 +1,14 @@
1
+ import { HttpError } from '../error.js';
2
+ import { Request } from '../transport/request.js';
3
+ import { RequestFetchAdapter } from '../transport/request-fetch-adapter.js';
4
+ import { HttpResponse, RequestHandler } from '../types.js';
5
+
6
+ export class TerminatingHandler implements RequestHandler {
7
+ async handle<T>(request: Request): Promise<HttpResponse<T>> {
8
+ return new RequestFetchAdapter<T>(request).send();
9
+ }
10
+
11
+ async *stream<T>(request: Request): AsyncGenerator<HttpResponse<T>> {
12
+ yield* new RequestFetchAdapter<T>(request).stream();
13
+ }
14
+ }
@@ -0,0 +1,25 @@
1
+ import { HttpError } from '../error.js';
2
+ import { HttpMetadata } from '../types.js';
3
+ import { Hook, HttpRequest, HttpResponse } from './hook.js';
4
+
5
+ export class CustomHook implements Hook {
6
+ public async beforeRequest(request: HttpRequest, params: Map<string, string>): Promise<HttpRequest> {
7
+ return request;
8
+ }
9
+
10
+ public async afterResponse(
11
+ request: HttpRequest,
12
+ response: HttpResponse<any>,
13
+ params: Map<string, string>,
14
+ ): Promise<HttpResponse<any>> {
15
+ return response;
16
+ }
17
+
18
+ public async onError(
19
+ request: HttpRequest,
20
+ response: HttpResponse<any>,
21
+ params: Map<string, string>,
22
+ ): Promise<HttpError> {
23
+ return new HttpError(response.metadata, response.raw);
24
+ }
25
+ }