@geekmidas/events 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (251) hide show
  1. package/dist/{BasicConnection-C4_Y0nIj.d.mts → BasicConnection-BTRsXiuH.d.cts} +3 -2
  2. package/dist/BasicConnection-BTRsXiuH.d.cts.map +1 -0
  3. package/dist/{BasicConnection-Bz3F2rXA.cjs → BasicConnection-C-Cg2FJT.cjs} +1 -1
  4. package/dist/BasicConnection-C-Cg2FJT.cjs.map +1 -0
  5. package/dist/{BasicConnection-DOSOFSsW.mjs → BasicConnection-CpwybcC9.mjs} +1 -1
  6. package/dist/BasicConnection-CpwybcC9.mjs.map +1 -0
  7. package/dist/{BasicConnection-CddnULuT.d.cts → BasicConnection-DIxtA7jK.d.mts} +3 -2
  8. package/dist/BasicConnection-DIxtA7jK.d.mts.map +1 -0
  9. package/dist/{BasicPublisher-afwuA4Xp.cjs → BasicPublisher-CXAVKxgq.cjs} +1 -1
  10. package/dist/BasicPublisher-CXAVKxgq.cjs.map +1 -0
  11. package/dist/{BasicPublisher-DCBxaTwC.d.mts → BasicPublisher-CpJFK2oS.d.mts} +5 -3
  12. package/dist/BasicPublisher-CpJFK2oS.d.mts.map +1 -0
  13. package/dist/{BasicPublisher-V5hELHG9.d.cts → BasicPublisher-D1q0a2xp.d.cts} +5 -3
  14. package/dist/BasicPublisher-D1q0a2xp.d.cts.map +1 -0
  15. package/dist/{BasicPublisher-CaX8GCUi.mjs → BasicPublisher-DogbeHAH.mjs} +1 -1
  16. package/dist/BasicPublisher-DogbeHAH.mjs.map +1 -0
  17. package/dist/{BasicSubscriber-BB3aKeph.d.mts → BasicSubscriber-6w0Af4DD.d.mts} +5 -3
  18. package/dist/BasicSubscriber-6w0Af4DD.d.mts.map +1 -0
  19. package/dist/{BasicSubscriber-DPpJNUUY.mjs → BasicSubscriber-BJSZN22M.mjs} +2 -4
  20. package/dist/BasicSubscriber-BJSZN22M.mjs.map +1 -0
  21. package/dist/{BasicSubscriber-DOwgFw5j.d.cts → BasicSubscriber-DXxQewjc.d.cts} +5 -3
  22. package/dist/BasicSubscriber-DXxQewjc.d.cts.map +1 -0
  23. package/dist/{BasicSubscriber-Ckf3BkxS.cjs → BasicSubscriber-mVJRMXhZ.cjs} +2 -4
  24. package/dist/BasicSubscriber-mVJRMXhZ.cjs.map +1 -0
  25. package/dist/{EventConnection-DZhn1Msl.d.cts → EventConnection-BaJRXdg7.d.cts} +2 -2
  26. package/dist/EventConnection-BaJRXdg7.d.cts.map +1 -0
  27. package/dist/EventConnection-ClLMoIUU.mjs.map +1 -1
  28. package/dist/EventConnection-F_N81SXu.cjs.map +1 -1
  29. package/dist/{EventConnection-DeXfLGom.d.mts → EventConnection-SOhtmxib.d.mts} +2 -2
  30. package/dist/EventConnection-SOhtmxib.d.mts.map +1 -0
  31. package/dist/EventConnection.d.cts +2 -2
  32. package/dist/EventConnection.d.mts +2 -2
  33. package/dist/{Publisher-C3m8JFXm.d.mts → Publisher-1CfcYRnm.d.mts} +4 -2
  34. package/dist/Publisher-1CfcYRnm.d.mts.map +1 -0
  35. package/dist/{Publisher-nXNVjL0e.d.cts → Publisher-BfNgvHwQ.d.cts} +4 -2
  36. package/dist/Publisher-BfNgvHwQ.d.cts.map +1 -0
  37. package/dist/Publisher-DS0aOh8r.mjs.map +1 -1
  38. package/dist/Publisher-ceu6OxCj.cjs.map +1 -1
  39. package/dist/Publisher.d.cts +2 -2
  40. package/dist/Publisher.d.mts +2 -2
  41. package/dist/{RabbitMQConnection-BN_GybOv.cjs → RabbitMQConnection-Blj9Lo05.cjs} +2 -2
  42. package/dist/RabbitMQConnection-Blj9Lo05.cjs.map +1 -0
  43. package/dist/{RabbitMQConnection-7cWp_-_Q.d.cts → RabbitMQConnection-Bm8VCI2R.d.cts} +3 -2
  44. package/dist/RabbitMQConnection-Bm8VCI2R.d.cts.map +1 -0
  45. package/dist/{RabbitMQConnection-C2HC7J7K.d.mts → RabbitMQConnection-Ck-ktCp_.d.mts} +3 -2
  46. package/dist/RabbitMQConnection-Ck-ktCp_.d.mts.map +1 -0
  47. package/dist/{RabbitMQConnection-eVOVS4Dl.mjs → RabbitMQConnection-Co7f5Xsx.mjs} +2 -2
  48. package/dist/RabbitMQConnection-Co7f5Xsx.mjs.map +1 -0
  49. package/dist/{RabbitMQPublisher-CSCn6gMA.cjs → RabbitMQPublisher--DL6GM6g.cjs} +1 -1
  50. package/dist/RabbitMQPublisher--DL6GM6g.cjs.map +1 -0
  51. package/dist/{RabbitMQPublisher-CpcbgrXj.d.cts → RabbitMQPublisher-COnxcWEZ.d.mts} +5 -3
  52. package/dist/RabbitMQPublisher-COnxcWEZ.d.mts.map +1 -0
  53. package/dist/{RabbitMQPublisher-BZX0edgL.mjs → RabbitMQPublisher-o_oVI3wr.mjs} +1 -1
  54. package/dist/RabbitMQPublisher-o_oVI3wr.mjs.map +1 -0
  55. package/dist/{RabbitMQPublisher-DDZi15Ro.d.mts → RabbitMQPublisher-qQT7-1-p.d.cts} +5 -3
  56. package/dist/RabbitMQPublisher-qQT7-1-p.d.cts.map +1 -0
  57. package/dist/{RabbitMQSubscriber-Cj7qLIi6.cjs → RabbitMQSubscriber-C8MYAihn.cjs} +2 -3
  58. package/dist/RabbitMQSubscriber-C8MYAihn.cjs.map +1 -0
  59. package/dist/{RabbitMQSubscriber-BJ9PTGny.d.cts → RabbitMQSubscriber-C_sZjDPU.d.mts} +5 -3
  60. package/dist/RabbitMQSubscriber-C_sZjDPU.d.mts.map +1 -0
  61. package/dist/{RabbitMQSubscriber-CIvIw8MG.d.mts → RabbitMQSubscriber-D12sssMb.d.cts} +5 -3
  62. package/dist/RabbitMQSubscriber-D12sssMb.d.cts.map +1 -0
  63. package/dist/{RabbitMQSubscriber-B5I-hBaT.mjs → RabbitMQSubscriber-DlGL0pC2.mjs} +2 -3
  64. package/dist/RabbitMQSubscriber-DlGL0pC2.mjs.map +1 -0
  65. package/dist/{SNSConnection-CAImaMM2.d.mts → SNSConnection-BDfQrVBO.d.cts} +3 -2
  66. package/dist/SNSConnection-BDfQrVBO.d.cts.map +1 -0
  67. package/dist/{SNSConnection-DVEE3XoC.mjs → SNSConnection-D7wCf9Si.mjs} +1 -1
  68. package/dist/SNSConnection-D7wCf9Si.mjs.map +1 -0
  69. package/dist/{SNSConnection-CZz_U56V.cjs → SNSConnection-DVsC_pbB.cjs} +1 -1
  70. package/dist/SNSConnection-DVsC_pbB.cjs.map +1 -0
  71. package/dist/{SNSConnection-Cqbr7-Ho.d.cts → SNSConnection-mHb10nQ6.d.mts} +3 -2
  72. package/dist/SNSConnection-mHb10nQ6.d.mts.map +1 -0
  73. package/dist/{SNSPublisher-DbWVH-g_.cjs → SNSPublisher-BoA8uLnw.cjs} +2 -3
  74. package/dist/SNSPublisher-BoA8uLnw.cjs.map +1 -0
  75. package/dist/{SNSPublisher-Dkhb4LU-.d.mts → SNSPublisher-CM7UAWtf.d.mts} +7 -6
  76. package/dist/SNSPublisher-CM7UAWtf.d.mts.map +1 -0
  77. package/dist/{SNSPublisher-Do-FMUyT.mjs → SNSPublisher-Drr4kHn6.mjs} +2 -3
  78. package/dist/SNSPublisher-Drr4kHn6.mjs.map +1 -0
  79. package/dist/{SNSPublisher-RVZFa7kL.d.cts → SNSPublisher-kpsSlGDn.d.cts} +7 -6
  80. package/dist/SNSPublisher-kpsSlGDn.d.cts.map +1 -0
  81. package/dist/{SNSSubscriber-e7eG48yJ.mjs → SNSSubscriber-CBIvQpqK.mjs} +5 -9
  82. package/dist/SNSSubscriber-CBIvQpqK.mjs.map +1 -0
  83. package/dist/{SNSSubscriber-DpEwQ8Tb.cjs → SNSSubscriber-CWiAJjpU.cjs} +5 -9
  84. package/dist/SNSSubscriber-CWiAJjpU.cjs.map +1 -0
  85. package/dist/{SNSSubscriber-B31JmkAE.d.mts → SNSSubscriber-DDB3--pm.d.cts} +4 -3
  86. package/dist/SNSSubscriber-DDB3--pm.d.cts.map +1 -0
  87. package/dist/{SNSSubscriber-k2UwKUxu.d.cts → SNSSubscriber-Dwo8391f.d.mts} +4 -3
  88. package/dist/SNSSubscriber-Dwo8391f.d.mts.map +1 -0
  89. package/dist/{SQSConnection-C5WFqZW7.d.mts → SQSConnection-B5Ep9Tma.d.cts} +3 -2
  90. package/dist/SQSConnection-B5Ep9Tma.d.cts.map +1 -0
  91. package/dist/{SQSConnection-geav2Rsn.d.cts → SQSConnection-BI_xOzyJ.d.mts} +3 -2
  92. package/dist/SQSConnection-BI_xOzyJ.d.mts.map +1 -0
  93. package/dist/{SQSConnection-DWYDtftQ.cjs → SQSConnection-BwNjUPr4.cjs} +1 -1
  94. package/dist/SQSConnection-BwNjUPr4.cjs.map +1 -0
  95. package/dist/{SQSConnection-BBlDWZLU.mjs → SQSConnection-Eleqqre3.mjs} +1 -1
  96. package/dist/SQSConnection-Eleqqre3.mjs.map +1 -0
  97. package/dist/{SQSPublisher-CdsayOLV.d.mts → SQSPublisher-BN1ds6SN.d.mts} +5 -3
  98. package/dist/SQSPublisher-BN1ds6SN.d.mts.map +1 -0
  99. package/dist/{SQSPublisher-Utb_FTe5.d.cts → SQSPublisher-DFTqwzRW.d.cts} +5 -3
  100. package/dist/SQSPublisher-DFTqwzRW.d.cts.map +1 -0
  101. package/dist/{SQSPublisher-B3lS2zbu.mjs → SQSPublisher-DG9o4ME3.mjs} +1 -1
  102. package/dist/SQSPublisher-DG9o4ME3.mjs.map +1 -0
  103. package/dist/{SQSPublisher-nzbSaXSH.cjs → SQSPublisher-Dq5353oZ.cjs} +1 -1
  104. package/dist/SQSPublisher-Dq5353oZ.cjs.map +1 -0
  105. package/dist/{SQSSubscriber-DcL9BbG1.cjs → SQSSubscriber-B4sRXVl6.cjs} +5 -12
  106. package/dist/SQSSubscriber-B4sRXVl6.cjs.map +1 -0
  107. package/dist/{SQSSubscriber-B6iL1EnX.d.cts → SQSSubscriber-BO2me_gs.d.cts} +4 -3
  108. package/dist/SQSSubscriber-BO2me_gs.d.cts.map +1 -0
  109. package/dist/{SQSSubscriber-84pFnW1z.mjs → SQSSubscriber-CVGhZ8Nr.mjs} +5 -12
  110. package/dist/SQSSubscriber-CVGhZ8Nr.mjs.map +1 -0
  111. package/dist/{SQSSubscriber-DBeE4XAR.d.mts → SQSSubscriber-FyZFfr2-.d.mts} +4 -3
  112. package/dist/SQSSubscriber-FyZFfr2-.d.mts.map +1 -0
  113. package/dist/Subscriber-Bd9hb_jp.mjs.map +1 -1
  114. package/dist/{Subscriber-Cff9EIpv.d.mts → Subscriber-BxT-KzFJ.d.mts} +4 -2
  115. package/dist/Subscriber-BxT-KzFJ.d.mts.map +1 -0
  116. package/dist/{Subscriber-CpAwcUzb.d.cts → Subscriber-DDD_4Nlx.d.cts} +4 -2
  117. package/dist/Subscriber-DDD_4Nlx.d.cts.map +1 -0
  118. package/dist/Subscriber-saVOWuMq.cjs.map +1 -1
  119. package/dist/Subscriber.d.cts +2 -2
  120. package/dist/Subscriber.d.mts +2 -2
  121. package/dist/basic/BasicConnection.cjs +1 -1
  122. package/dist/basic/BasicConnection.d.cts +2 -2
  123. package/dist/basic/BasicConnection.d.mts +2 -2
  124. package/dist/basic/BasicConnection.mjs +1 -1
  125. package/dist/basic/BasicPublisher.cjs +1 -1
  126. package/dist/basic/BasicPublisher.d.cts +3 -3
  127. package/dist/basic/BasicPublisher.d.mts +3 -3
  128. package/dist/basic/BasicPublisher.mjs +1 -1
  129. package/dist/basic/BasicSubscriber.cjs +1 -1
  130. package/dist/basic/BasicSubscriber.d.cts +3 -3
  131. package/dist/basic/BasicSubscriber.d.mts +3 -3
  132. package/dist/basic/BasicSubscriber.mjs +1 -1
  133. package/dist/basic/index.cjs +3 -3
  134. package/dist/basic/index.d.cts +4 -4
  135. package/dist/basic/index.d.mts +4 -4
  136. package/dist/basic/index.mjs +3 -3
  137. package/dist/index.d.cts +4 -4
  138. package/dist/index.d.mts +4 -4
  139. package/dist/rabbitmq/RabbitMQConnection.cjs +1 -1
  140. package/dist/rabbitmq/RabbitMQConnection.d.cts +2 -2
  141. package/dist/rabbitmq/RabbitMQConnection.d.mts +2 -2
  142. package/dist/rabbitmq/RabbitMQConnection.mjs +1 -1
  143. package/dist/rabbitmq/RabbitMQPublisher.cjs +1 -1
  144. package/dist/rabbitmq/RabbitMQPublisher.d.cts +3 -3
  145. package/dist/rabbitmq/RabbitMQPublisher.d.mts +3 -3
  146. package/dist/rabbitmq/RabbitMQPublisher.mjs +1 -1
  147. package/dist/rabbitmq/RabbitMQSubscriber.cjs +1 -1
  148. package/dist/rabbitmq/RabbitMQSubscriber.d.cts +3 -3
  149. package/dist/rabbitmq/RabbitMQSubscriber.d.mts +3 -3
  150. package/dist/rabbitmq/RabbitMQSubscriber.mjs +1 -1
  151. package/dist/rabbitmq/index.cjs +3 -3
  152. package/dist/rabbitmq/index.d.cts +4 -4
  153. package/dist/rabbitmq/index.d.mts +4 -4
  154. package/dist/rabbitmq/index.mjs +3 -3
  155. package/dist/sns/SNSConnection.cjs +1 -1
  156. package/dist/sns/SNSConnection.d.cts +2 -2
  157. package/dist/sns/SNSConnection.d.mts +2 -2
  158. package/dist/sns/SNSConnection.mjs +1 -1
  159. package/dist/sns/SNSPublisher.cjs +1 -1
  160. package/dist/sns/SNSPublisher.d.cts +3 -3
  161. package/dist/sns/SNSPublisher.d.mts +3 -3
  162. package/dist/sns/SNSPublisher.mjs +1 -1
  163. package/dist/sns/SNSSubscriber.cjs +3 -3
  164. package/dist/sns/SNSSubscriber.d.cts +3 -3
  165. package/dist/sns/SNSSubscriber.d.mts +3 -3
  166. package/dist/sns/SNSSubscriber.mjs +3 -3
  167. package/dist/sns/index.cjs +5 -5
  168. package/dist/sns/index.d.cts +4 -4
  169. package/dist/sns/index.d.mts +4 -4
  170. package/dist/sns/index.mjs +5 -5
  171. package/dist/sqs/SQSConnection.cjs +1 -1
  172. package/dist/sqs/SQSConnection.d.cts +2 -2
  173. package/dist/sqs/SQSConnection.d.mts +2 -2
  174. package/dist/sqs/SQSConnection.mjs +1 -1
  175. package/dist/sqs/SQSPublisher.cjs +1 -1
  176. package/dist/sqs/SQSPublisher.d.cts +3 -3
  177. package/dist/sqs/SQSPublisher.d.mts +3 -3
  178. package/dist/sqs/SQSPublisher.mjs +1 -1
  179. package/dist/sqs/SQSSubscriber.cjs +1 -1
  180. package/dist/sqs/SQSSubscriber.d.cts +3 -3
  181. package/dist/sqs/SQSSubscriber.d.mts +3 -3
  182. package/dist/sqs/SQSSubscriber.mjs +1 -1
  183. package/dist/sqs/index.cjs +3 -3
  184. package/dist/sqs/index.d.cts +4 -4
  185. package/dist/sqs/index.d.mts +4 -4
  186. package/dist/sqs/index.mjs +3 -3
  187. package/dist/types-B63qHVOG.mjs.map +1 -1
  188. package/dist/types-CvSMEO5z.cjs.map +1 -1
  189. package/dist/{types-D0g-o6wX.d.mts → types-DSVsPgKd.d.mts} +2 -1
  190. package/dist/types-DSVsPgKd.d.mts.map +1 -0
  191. package/dist/{types-DEGUg5BA.d.cts → types-Dmbp1U-6.d.cts} +2 -1
  192. package/dist/types-Dmbp1U-6.d.cts.map +1 -0
  193. package/dist/types.d.cts +1 -1
  194. package/dist/types.d.mts +1 -1
  195. package/package.json +1 -1
  196. package/src/EventConnection.ts +31 -31
  197. package/src/Publisher.ts +78 -78
  198. package/src/Subscriber.ts +91 -91
  199. package/src/__tests__/EventConnection.spec.ts +42 -0
  200. package/src/__tests__/Publisher.spec.ts +96 -0
  201. package/src/__tests__/Subscriber.spec.ts +91 -23
  202. package/src/basic/BasicConnection.ts +35 -35
  203. package/src/basic/BasicPublisher.ts +8 -8
  204. package/src/basic/BasicSubscriber.ts +13 -16
  205. package/src/basic/__tests__/BasicSubscriber.spec.ts +116 -116
  206. package/src/index.ts +13 -13
  207. package/src/rabbitmq/RabbitMQConnection.ts +139 -139
  208. package/src/rabbitmq/RabbitMQPublisher.ts +48 -48
  209. package/src/rabbitmq/RabbitMQSubscriber.ts +100 -102
  210. package/src/rabbitmq/__tests__/RabbitMQPublisher.spec.ts +364 -364
  211. package/src/rabbitmq/__tests__/RabbitMQSubscriber.spec.ts +204 -204
  212. package/src/rabbitmq/index.ts +3 -3
  213. package/src/sns/SNSConnection.ts +76 -76
  214. package/src/sns/SNSPublisher.ts +54 -56
  215. package/src/sns/SNSSubscriber.ts +187 -191
  216. package/src/sns/__tests__/SNS-SQS-Integration.spec.ts +321 -321
  217. package/src/sns/__tests__/SNSPublisher.spec.ts +449 -0
  218. package/src/sns/__tests__/SNSSubscriber.spec.ts +527 -0
  219. package/src/sns/index.ts +3 -3
  220. package/src/sqs/SQSConnection.ts +75 -75
  221. package/src/sqs/SQSPublisher.ts +93 -93
  222. package/src/sqs/SQSSubscriber.ts +157 -165
  223. package/src/sqs/__tests__/SQSPublisher.spec.ts +178 -178
  224. package/src/sqs/index.ts +3 -3
  225. package/src/types.ts +28 -29
  226. package/tsconfig.json +9 -0
  227. package/tsdown.config.ts +1 -1
  228. package/dist/BasicConnection-Bz3F2rXA.cjs.map +0 -1
  229. package/dist/BasicConnection-DOSOFSsW.mjs.map +0 -1
  230. package/dist/BasicPublisher-CaX8GCUi.mjs.map +0 -1
  231. package/dist/BasicPublisher-afwuA4Xp.cjs.map +0 -1
  232. package/dist/BasicSubscriber-Ckf3BkxS.cjs.map +0 -1
  233. package/dist/BasicSubscriber-DPpJNUUY.mjs.map +0 -1
  234. package/dist/RabbitMQConnection-BN_GybOv.cjs.map +0 -1
  235. package/dist/RabbitMQConnection-eVOVS4Dl.mjs.map +0 -1
  236. package/dist/RabbitMQPublisher-BZX0edgL.mjs.map +0 -1
  237. package/dist/RabbitMQPublisher-CSCn6gMA.cjs.map +0 -1
  238. package/dist/RabbitMQSubscriber-B5I-hBaT.mjs.map +0 -1
  239. package/dist/RabbitMQSubscriber-Cj7qLIi6.cjs.map +0 -1
  240. package/dist/SNSConnection-CZz_U56V.cjs.map +0 -1
  241. package/dist/SNSConnection-DVEE3XoC.mjs.map +0 -1
  242. package/dist/SNSPublisher-DbWVH-g_.cjs.map +0 -1
  243. package/dist/SNSPublisher-Do-FMUyT.mjs.map +0 -1
  244. package/dist/SNSSubscriber-DpEwQ8Tb.cjs.map +0 -1
  245. package/dist/SNSSubscriber-e7eG48yJ.mjs.map +0 -1
  246. package/dist/SQSConnection-BBlDWZLU.mjs.map +0 -1
  247. package/dist/SQSConnection-DWYDtftQ.cjs.map +0 -1
  248. package/dist/SQSPublisher-B3lS2zbu.mjs.map +0 -1
  249. package/dist/SQSPublisher-nzbSaXSH.cjs.map +0 -1
  250. package/dist/SQSSubscriber-84pFnW1z.mjs.map +0 -1
  251. package/dist/SQSSubscriber-DcL9BbG1.cjs.map +0 -1
@@ -1,105 +1,105 @@
1
1
  import {
2
- SendMessageBatchCommand,
3
- type SendMessageBatchCommandInput,
4
- type SendMessageBatchRequestEntry,
2
+ SendMessageBatchCommand,
3
+ type SendMessageBatchCommandInput,
4
+ type SendMessageBatchRequestEntry,
5
5
  } from '@aws-sdk/client-sqs';
6
6
  import chunk from 'lodash.chunk';
7
7
  import type { EventPublisher, PublishableMessage } from '../types';
8
8
  import type { SQSConnection } from './SQSConnection';
9
9
 
10
10
  export interface SQSPublisherOptions {
11
- maxBatchSize?: number; // Default: 10 (SQS limit)
11
+ maxBatchSize?: number; // Default: 10 (SQS limit)
12
12
  }
13
13
 
14
14
  export class SQSPublisher<TMessage extends PublishableMessage<string, any>>
15
- implements EventPublisher<TMessage>
15
+ implements EventPublisher<TMessage>
16
16
  {
17
- readonly options: Required<SQSPublisherOptions>;
18
-
19
- constructor(
20
- readonly connection: SQSConnection,
21
- options: SQSPublisherOptions = {},
22
- ) {
23
- this.options = {
24
- maxBatchSize: options.maxBatchSize ?? 10, // SQS limit
25
- };
26
- }
27
-
28
- /**
29
- * Create an SQSPublisher from a connection string
30
- * Format: sqs://?queueUrl=https://sqs.region.amazonaws.com/accountId/queueName&region=us-east-1&endpoint=http://localhost:4566&maxBatchSize=10
31
- */
32
- static async fromConnectionString<
33
- TMessage extends PublishableMessage<string, any>,
34
- >(connectionString: string): Promise<SQSPublisher<TMessage>> {
35
- const url = new URL(connectionString);
36
- const params = url.searchParams;
37
-
38
- const { SQSConnection } = await import('./SQSConnection');
39
- const connection =
40
- await SQSConnection.fromConnectionString(connectionString);
41
-
42
- const options: SQSPublisherOptions = {
43
- maxBatchSize: params.get('maxBatchSize')
44
- ? Number.parseInt(params.get('maxBatchSize')!, 10)
45
- : undefined,
46
- };
47
-
48
- return new SQSPublisher<TMessage>(connection, options);
49
- }
50
-
51
- async publish(messages: TMessage[]): Promise<void> {
52
- if (messages.length === 0) return;
53
-
54
- if (!this.connection.isConnected()) {
55
- await this.connection.connect();
56
- }
57
-
58
- // Split messages into batches (SQS limit is 10 messages per batch)
59
- const batches = chunk(messages, this.options.maxBatchSize);
60
-
61
- // Send all batches
62
- await Promise.all(batches.map((batch) => this.sendBatch(batch)));
63
- }
64
-
65
- private async sendBatch(messages: TMessage[]): Promise<void> {
66
- const entries: SendMessageBatchRequestEntry[] = messages.map(
67
- (message, index) => ({
68
- Id: `${index}`,
69
- MessageBody: JSON.stringify({
70
- type: message.type,
71
- payload: message.payload,
72
- }),
73
- MessageAttributes: {
74
- type: {
75
- DataType: 'String',
76
- StringValue: message.type,
77
- },
78
- },
79
- }),
80
- );
81
-
82
- const input: SendMessageBatchCommandInput = {
83
- QueueUrl: this.connection.queueUrl,
84
- Entries: entries,
85
- };
86
-
87
- const command = new SendMessageBatchCommand(input);
88
- const response = await this.connection.sqsClient.send(command);
89
-
90
- // Check for failures
91
- if (response.Failed && response.Failed.length > 0) {
92
- const errors = response.Failed.map(
93
- (f) => `${f.Id}: ${f.Code} - ${f.Message}`,
94
- ).join(', ');
95
- throw new Error(
96
- `Failed to send ${response.Failed.length} messages: ${errors}`,
97
- );
98
- }
99
- }
100
-
101
- async close(): Promise<void> {
102
- // Publisher doesn't own the connection
103
- // Connection should be closed by whoever created it
104
- }
17
+ readonly options: Required<SQSPublisherOptions>;
18
+
19
+ constructor(
20
+ readonly connection: SQSConnection,
21
+ options: SQSPublisherOptions = {},
22
+ ) {
23
+ this.options = {
24
+ maxBatchSize: options.maxBatchSize ?? 10, // SQS limit
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Create an SQSPublisher from a connection string
30
+ * Format: sqs://?queueUrl=https://sqs.region.amazonaws.com/accountId/queueName&region=us-east-1&endpoint=http://localhost:4566&maxBatchSize=10
31
+ */
32
+ static async fromConnectionString<
33
+ TMessage extends PublishableMessage<string, any>,
34
+ >(connectionString: string): Promise<SQSPublisher<TMessage>> {
35
+ const url = new URL(connectionString);
36
+ const params = url.searchParams;
37
+
38
+ const { SQSConnection } = await import('./SQSConnection');
39
+ const connection =
40
+ await SQSConnection.fromConnectionString(connectionString);
41
+
42
+ const options: SQSPublisherOptions = {
43
+ maxBatchSize: params.get('maxBatchSize')
44
+ ? Number.parseInt(params.get('maxBatchSize')!, 10)
45
+ : undefined,
46
+ };
47
+
48
+ return new SQSPublisher<TMessage>(connection, options);
49
+ }
50
+
51
+ async publish(messages: TMessage[]): Promise<void> {
52
+ if (messages.length === 0) return;
53
+
54
+ if (!this.connection.isConnected()) {
55
+ await this.connection.connect();
56
+ }
57
+
58
+ // Split messages into batches (SQS limit is 10 messages per batch)
59
+ const batches = chunk(messages, this.options.maxBatchSize);
60
+
61
+ // Send all batches
62
+ await Promise.all(batches.map((batch) => this.sendBatch(batch)));
63
+ }
64
+
65
+ private async sendBatch(messages: TMessage[]): Promise<void> {
66
+ const entries: SendMessageBatchRequestEntry[] = messages.map(
67
+ (message, index) => ({
68
+ Id: `${index}`,
69
+ MessageBody: JSON.stringify({
70
+ type: message.type,
71
+ payload: message.payload,
72
+ }),
73
+ MessageAttributes: {
74
+ type: {
75
+ DataType: 'String',
76
+ StringValue: message.type,
77
+ },
78
+ },
79
+ }),
80
+ );
81
+
82
+ const input: SendMessageBatchCommandInput = {
83
+ QueueUrl: this.connection.queueUrl,
84
+ Entries: entries,
85
+ };
86
+
87
+ const command = new SendMessageBatchCommand(input);
88
+ const response = await this.connection.sqsClient.send(command);
89
+
90
+ // Check for failures
91
+ if (response.Failed && response.Failed.length > 0) {
92
+ const errors = response.Failed.map(
93
+ (f) => `${f.Id}: ${f.Code} - ${f.Message}`,
94
+ ).join(', ');
95
+ throw new Error(
96
+ `Failed to send ${response.Failed.length} messages: ${errors}`,
97
+ );
98
+ }
99
+ }
100
+
101
+ async close(): Promise<void> {
102
+ // Publisher doesn't own the connection
103
+ // Connection should be closed by whoever created it
104
+ }
105
105
  }
@@ -1,15 +1,15 @@
1
1
  import {
2
- DeleteMessageCommand,
3
- type Message,
4
- ReceiveMessageCommand,
2
+ DeleteMessageCommand,
3
+ type Message,
4
+ ReceiveMessageCommand,
5
5
  } from '@aws-sdk/client-sqs';
6
6
  import type { EventSubscriber, PublishableMessage } from '../types';
7
7
  import type { SQSConnection } from './SQSConnection';
8
8
 
9
9
  export interface SQSSubscriberOptions {
10
- waitTimeSeconds?: number; // SQS long polling (default: 20)
11
- maxMessages?: number; // Max messages per poll (default: 10)
12
- expectedTopicArn?: string; // Optional: verify messages are from specific SNS topic
10
+ waitTimeSeconds?: number; // SQS long polling (default: 20)
11
+ maxMessages?: number; // Max messages per poll (default: 10)
12
+ expectedTopicArn?: string; // Optional: verify messages are from specific SNS topic
13
13
  }
14
14
 
15
15
  /**
@@ -26,164 +26,156 @@ export interface SQSSubscriberOptions {
26
26
  * - Processes the actual message payload
27
27
  */
28
28
  export class SQSSubscriber<TMessage extends PublishableMessage<string, any>>
29
- implements EventSubscriber<TMessage>
29
+ implements EventSubscriber<TMessage>
30
30
  {
31
- private polling = false;
32
- private messageTypes: Set<TMessage['type']> = new Set();
33
- private listener?: (payload: TMessage) => Promise<void>;
34
- private options: Required<SQSSubscriberOptions>;
35
-
36
- constructor(
37
- private connection: SQSConnection,
38
- options: SQSSubscriberOptions = {},
39
- ) {
40
- this.options = {
41
- waitTimeSeconds: options.waitTimeSeconds ?? 20,
42
- maxMessages: options.maxMessages ?? 10,
43
- expectedTopicArn: options.expectedTopicArn ?? '',
44
- };
45
- }
46
-
47
- async subscribe(
48
- messages: TMessage['type'][],
49
- listener: (payload: TMessage) => Promise<void>,
50
- ): Promise<void> {
51
- this.messageTypes = new Set(messages);
52
- this.listener = listener;
53
-
54
- if (!this.connection.isConnected()) {
55
- await this.connection.connect();
56
- }
57
-
58
- this.polling = true;
59
- this.poll();
60
- }
61
-
62
- stop(): void {
63
- this.polling = false;
64
- }
65
-
66
- private async poll(): Promise<void> {
67
- while (this.polling) {
68
- try {
69
- const command = new ReceiveMessageCommand({
70
- QueueUrl: this.connection.queueUrl,
71
- MaxNumberOfMessages: this.options.maxMessages,
72
- WaitTimeSeconds: this.options.waitTimeSeconds,
73
- MessageAttributeNames: ['All'],
74
- });
75
-
76
- const response = await this.connection.sqsClient.send(command);
77
-
78
- if (response.Messages && response.Messages.length > 0) {
79
- await this.processMessages(response.Messages);
80
- }
81
- } catch (error) {
82
- console.error('Error receiving messages from SQS:', error);
83
- await this.sleep(1000);
84
- }
85
- }
86
- }
87
-
88
- private async processMessages(messages: Message[]): Promise<void> {
89
- for (const message of messages) {
90
- try {
91
- if (!message.Body) continue;
92
-
93
- // Try to parse as SNS message first
94
- const parsedMessage = this.parseMessage(message.Body);
95
-
96
- if (!parsedMessage) {
97
- // Not a valid message format
98
- await this.deleteMessage(message.ReceiptHandle!);
99
- continue;
100
- }
101
-
102
- const { payload, messageType, topicArn } = parsedMessage;
103
-
104
- // If expectedTopicArn is set, verify the message is from that topic
105
- if (this.options.expectedTopicArn && topicArn) {
106
- if (topicArn !== this.options.expectedTopicArn) {
107
- console.warn(
108
- `Received message from unexpected topic: ${topicArn}, expected: ${this.options.expectedTopicArn}`,
109
- );
110
- await this.deleteMessage(message.ReceiptHandle!);
111
- continue;
112
- }
113
- }
114
-
115
- // Check if we're subscribed to this message type
116
- if (
117
- messageType &&
118
- this.messageTypes.has(messageType as TMessage['type'])
119
- ) {
120
- // Call listener
121
- if (this.listener) {
122
- await this.listener(payload as TMessage);
123
- }
124
-
125
- // Delete message after successful processing
126
- await this.deleteMessage(message.ReceiptHandle!);
127
- } else {
128
- // Delete messages we're not subscribed to
129
- await this.deleteMessage(message.ReceiptHandle!);
130
- }
131
- } catch (error) {
132
- console.error('Error processing message:', error);
133
- // Message will become visible again
134
- }
135
- }
136
- }
137
-
138
- /**
139
- * Parse message body - handles both direct SQS messages and SNS-wrapped messages
140
- */
141
- private parseMessage(body: string): {
142
- payload: unknown;
143
- messageType: string | undefined;
144
- topicArn?: string;
145
- } | null {
146
- try {
147
- const parsed = JSON.parse(body);
148
-
149
- // Check if this is an SNS notification wrapper
150
- if (parsed.Type === 'Notification' && parsed.Message) {
151
- // This is an SNS message
152
- const snsMessage = JSON.parse(parsed.Message);
153
- const messageType =
154
- parsed.MessageAttributes?.type?.Value || snsMessage.type;
155
-
156
- return {
157
- payload: snsMessage,
158
- messageType,
159
- topicArn: parsed.TopicArn,
160
- };
161
- }
162
-
163
- // This is a direct SQS message
164
- return {
165
- payload: parsed,
166
- messageType: parsed.type,
167
- };
168
- } catch (error) {
169
- console.error('Failed to parse message:', error);
170
- return null;
171
- }
172
- }
173
-
174
- private async deleteMessage(receiptHandle: string): Promise<void> {
175
- try {
176
- const command = new DeleteMessageCommand({
177
- QueueUrl: this.connection.queueUrl,
178
- ReceiptHandle: receiptHandle,
179
- });
180
- await this.connection.sqsClient.send(command);
181
- } catch (error) {
182
- console.error('Error deleting message:', error);
183
- }
184
- }
185
-
186
- private sleep(ms: number): Promise<void> {
187
- return new Promise((resolve) => setTimeout(resolve, ms));
188
- }
31
+ private polling = false;
32
+ private messageTypes: Set<TMessage['type']> = new Set();
33
+ private listener?: (payload: TMessage) => Promise<void>;
34
+ private options: Required<SQSSubscriberOptions>;
35
+
36
+ constructor(
37
+ private connection: SQSConnection,
38
+ options: SQSSubscriberOptions = {},
39
+ ) {
40
+ this.options = {
41
+ waitTimeSeconds: options.waitTimeSeconds ?? 20,
42
+ maxMessages: options.maxMessages ?? 10,
43
+ expectedTopicArn: options.expectedTopicArn ?? '',
44
+ };
45
+ }
46
+
47
+ async subscribe(
48
+ messages: TMessage['type'][],
49
+ listener: (payload: TMessage) => Promise<void>,
50
+ ): Promise<void> {
51
+ this.messageTypes = new Set(messages);
52
+ this.listener = listener;
53
+
54
+ if (!this.connection.isConnected()) {
55
+ await this.connection.connect();
56
+ }
57
+
58
+ this.polling = true;
59
+ this.poll();
60
+ }
61
+
62
+ stop(): void {
63
+ this.polling = false;
64
+ }
65
+
66
+ private async poll(): Promise<void> {
67
+ while (this.polling) {
68
+ try {
69
+ const command = new ReceiveMessageCommand({
70
+ QueueUrl: this.connection.queueUrl,
71
+ MaxNumberOfMessages: this.options.maxMessages,
72
+ WaitTimeSeconds: this.options.waitTimeSeconds,
73
+ MessageAttributeNames: ['All'],
74
+ });
75
+
76
+ const response = await this.connection.sqsClient.send(command);
77
+
78
+ if (response.Messages && response.Messages.length > 0) {
79
+ await this.processMessages(response.Messages);
80
+ }
81
+ } catch (_error) {
82
+ await this.sleep(1000);
83
+ }
84
+ }
85
+ }
86
+
87
+ private async processMessages(messages: Message[]): Promise<void> {
88
+ for (const message of messages) {
89
+ try {
90
+ if (!message.Body) continue;
91
+
92
+ // Try to parse as SNS message first
93
+ const parsedMessage = this.parseMessage(message.Body);
94
+
95
+ if (!parsedMessage) {
96
+ // Not a valid message format
97
+ await this.deleteMessage(message.ReceiptHandle!);
98
+ continue;
99
+ }
100
+
101
+ const { payload, messageType, topicArn } = parsedMessage;
102
+
103
+ // If expectedTopicArn is set, verify the message is from that topic
104
+ if (this.options.expectedTopicArn && topicArn) {
105
+ if (topicArn !== this.options.expectedTopicArn) {
106
+ await this.deleteMessage(message.ReceiptHandle!);
107
+ continue;
108
+ }
109
+ }
110
+
111
+ // Check if we're subscribed to this message type
112
+ if (
113
+ messageType &&
114
+ this.messageTypes.has(messageType as TMessage['type'])
115
+ ) {
116
+ // Call listener
117
+ if (this.listener) {
118
+ await this.listener(payload as TMessage);
119
+ }
120
+
121
+ // Delete message after successful processing
122
+ await this.deleteMessage(message.ReceiptHandle!);
123
+ } else {
124
+ // Delete messages we're not subscribed to
125
+ await this.deleteMessage(message.ReceiptHandle!);
126
+ }
127
+ } catch (_error) {
128
+ // Message will become visible again
129
+ }
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Parse message body - handles both direct SQS messages and SNS-wrapped messages
135
+ */
136
+ private parseMessage(body: string): {
137
+ payload: unknown;
138
+ messageType: string | undefined;
139
+ topicArn?: string;
140
+ } | null {
141
+ try {
142
+ const parsed = JSON.parse(body);
143
+
144
+ // Check if this is an SNS notification wrapper
145
+ if (parsed.Type === 'Notification' && parsed.Message) {
146
+ // This is an SNS message
147
+ const snsMessage = JSON.parse(parsed.Message);
148
+ const messageType =
149
+ parsed.MessageAttributes?.type?.Value || snsMessage.type;
150
+
151
+ return {
152
+ payload: snsMessage,
153
+ messageType,
154
+ topicArn: parsed.TopicArn,
155
+ };
156
+ }
157
+
158
+ // This is a direct SQS message
159
+ return {
160
+ payload: parsed,
161
+ messageType: parsed.type,
162
+ };
163
+ } catch (_error) {
164
+ return null;
165
+ }
166
+ }
167
+
168
+ private async deleteMessage(receiptHandle: string): Promise<void> {
169
+ try {
170
+ const command = new DeleteMessageCommand({
171
+ QueueUrl: this.connection.queueUrl,
172
+ ReceiptHandle: receiptHandle,
173
+ });
174
+ await this.connection.sqsClient.send(command);
175
+ } catch (_error) {}
176
+ }
177
+
178
+ private sleep(ms: number): Promise<void> {
179
+ return new Promise((resolve) => setTimeout(resolve, ms));
180
+ }
189
181
  }