@adtrackify/at-service-common 3.18.11 → 3.18.13

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 (577) hide show
  1. package/dist/cjs/__tests__/clients/acuity-client.spec.d.ts +1 -0
  2. package/dist/cjs/__tests__/clients/acuity-client.spec.js +34 -0
  3. package/dist/cjs/__tests__/clients/acuity-client.spec.js.map +1 -0
  4. package/dist/cjs/__tests__/clients/cross-platform-compression.spec.d.ts +1 -0
  5. package/dist/cjs/__tests__/clients/cross-platform-compression.spec.js +355 -0
  6. package/dist/cjs/__tests__/clients/cross-platform-compression.spec.js.map +1 -0
  7. package/dist/cjs/__tests__/clients/sqs-bundled-client.spec.d.ts +1 -1
  8. package/dist/cjs/__tests__/clients/sqs-bundled-client.spec.js +921 -921
  9. package/dist/cjs/__tests__/clients/sqs-bundling-contracts.spec.d.ts +1 -0
  10. package/dist/cjs/__tests__/clients/sqs-bundling-contracts.spec.js +576 -0
  11. package/dist/cjs/__tests__/clients/sqs-bundling-contracts.spec.js.map +1 -0
  12. package/dist/cjs/__tests__/clients/sqs-client.spec.d.ts +1 -1
  13. package/dist/cjs/__tests__/clients/sqs-client.spec.js +191 -191
  14. package/dist/cjs/__tests__/clients/sqs-unbundle.spec.d.ts +1 -1
  15. package/dist/cjs/__tests__/clients/sqs-unbundle.spec.js +1357 -1228
  16. package/dist/cjs/__tests__/clients/sqs-unbundle.spec.js.map +1 -1
  17. package/dist/cjs/__tests__/db/shared-read-db-services.spec.d.ts +1 -1
  18. package/dist/cjs/__tests__/db/shared-read-db-services.spec.js +89 -89
  19. package/dist/cjs/__tests__/helpers/account-users-helper.spec.d.ts +1 -1
  20. package/dist/cjs/__tests__/helpers/account-users-helper.spec.js +220 -220
  21. package/dist/cjs/__tests__/helpers/acuity-helper.spec.d.ts +1 -0
  22. package/dist/cjs/__tests__/helpers/acuity-helper.spec.js +26 -0
  23. package/dist/cjs/__tests__/helpers/acuity-helper.spec.js.map +1 -0
  24. package/dist/cjs/__tests__/helpers/api-key-auth-helper.spec.d.ts +1 -1
  25. package/dist/cjs/__tests__/helpers/api-key-auth-helper.spec.js +82 -82
  26. package/dist/cjs/__tests__/identity-cache/identity-cache-db-service.spec.d.ts +1 -1
  27. package/dist/cjs/__tests__/identity-cache/identity-cache-db-service.spec.js +674 -674
  28. package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.d.ts +1 -1
  29. package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js +588 -588
  30. package/dist/cjs/__tests__/integration/sqs-bundling-roundtrip.spec.d.ts +1 -1
  31. package/dist/cjs/__tests__/integration/sqs-bundling-roundtrip.spec.js +584 -584
  32. package/dist/cjs/__tests__/libs/compress-decompress.spec.d.ts +1 -1
  33. package/dist/cjs/__tests__/libs/compress-decompress.spec.js +16 -16
  34. package/dist/cjs/__tests__/libs/currency.spec.d.ts +1 -1
  35. package/dist/cjs/__tests__/libs/currency.spec.js +220 -220
  36. package/dist/cjs/__tests__/libs/dates.spec.d.ts +1 -1
  37. package/dist/cjs/__tests__/libs/dates.spec.js +130 -130
  38. package/dist/cjs/__tests__/libs/domain.spec.d.ts +1 -1
  39. package/dist/cjs/__tests__/libs/domain.spec.js +107 -107
  40. package/dist/cjs/__tests__/libs/numbers.spec.d.ts +1 -1
  41. package/dist/cjs/__tests__/libs/numbers.spec.js +261 -261
  42. package/dist/cjs/__tests__/s3-client/s3-client.spec.d.ts +1 -1
  43. package/dist/cjs/__tests__/s3-client/s3-client.spec.js +33 -33
  44. package/dist/cjs/__tests__/services/acuity-api-service.spec.d.ts +1 -0
  45. package/dist/cjs/__tests__/services/acuity-api-service.spec.js +52 -0
  46. package/dist/cjs/__tests__/services/acuity-api-service.spec.js.map +1 -0
  47. package/dist/cjs/__tests__/shopify/shopify-graphql-transformer.spec.d.ts +1 -1
  48. package/dist/cjs/__tests__/shopify/shopify-graphql-transformer.spec.js +35 -35
  49. package/dist/cjs/__tests__/unit/libs/api-router/public-api-router.spec.d.ts +1 -1
  50. package/dist/cjs/__tests__/unit/libs/api-router/public-api-router.spec.js +181 -181
  51. package/dist/cjs/__tests__/unit/libs/api-router/route-matcher.spec.d.ts +1 -1
  52. package/dist/cjs/__tests__/unit/libs/api-router/route-matcher.spec.js +69 -69
  53. package/dist/cjs/clients/generic/cognito-client.d.ts +23 -23
  54. package/dist/cjs/clients/generic/cognito-client.js +209 -209
  55. package/dist/cjs/clients/generic/dynamodb-client.d.ts +18 -18
  56. package/dist/cjs/clients/generic/dynamodb-client.js +172 -172
  57. package/dist/cjs/clients/generic/eventbridge-client.d.ts +14 -14
  58. package/dist/cjs/clients/generic/eventbridge-client.js +51 -51
  59. package/dist/cjs/clients/generic/http-client.d.ts +14 -14
  60. package/dist/cjs/clients/generic/http-client.js +61 -61
  61. package/dist/cjs/clients/generic/index.d.ts +13 -13
  62. package/dist/cjs/clients/generic/index.js +29 -29
  63. package/dist/cjs/clients/generic/lambda-invoke-client.d.ts +10 -10
  64. package/dist/cjs/clients/generic/lambda-invoke-client.js +39 -39
  65. package/dist/cjs/clients/generic/location-client.d.ts +8 -8
  66. package/dist/cjs/clients/generic/location-client.js +31 -31
  67. package/dist/cjs/clients/generic/redis-client.d.ts +33 -33
  68. package/dist/cjs/clients/generic/redis-client.js +191 -191
  69. package/dist/cjs/clients/generic/s3-client.d.ts +23 -23
  70. package/dist/cjs/clients/generic/s3-client.js +216 -216
  71. package/dist/cjs/clients/generic/singlestore-db-client.d.ts +14 -14
  72. package/dist/cjs/clients/generic/singlestore-db-client.js +67 -67
  73. package/dist/cjs/clients/generic/sqs-bundled-client.d.ts +15 -15
  74. package/dist/cjs/clients/generic/sqs-bundled-client.js +311 -311
  75. package/dist/cjs/clients/generic/sqs-bundled-client.types.d.ts +53 -53
  76. package/dist/cjs/clients/generic/sqs-bundled-client.types.js +17 -17
  77. package/dist/cjs/clients/generic/sqs-client.d.ts +53 -53
  78. package/dist/cjs/clients/generic/sqs-client.js +285 -285
  79. package/dist/cjs/clients/generic/sqs-unbundle.d.ts +32 -32
  80. package/dist/cjs/clients/generic/sqs-unbundle.js +144 -144
  81. package/dist/cjs/clients/index.d.ts +3 -3
  82. package/dist/cjs/clients/index.js +19 -19
  83. package/dist/cjs/clients/internal-api/accounts-client.d.ts +91 -91
  84. package/dist/cjs/clients/internal-api/accounts-client.js +129 -129
  85. package/dist/cjs/clients/internal-api/cache-lambda-client.d.ts +26 -26
  86. package/dist/cjs/clients/internal-api/cache-lambda-client.js +89 -89
  87. package/dist/cjs/clients/internal-api/db-management-client.d.ts +18 -18
  88. package/dist/cjs/clients/internal-api/db-management-client.js +36 -36
  89. package/dist/cjs/clients/internal-api/destinations-client.d.ts +34 -34
  90. package/dist/cjs/clients/internal-api/destinations-client.js +79 -79
  91. package/dist/cjs/clients/internal-api/event-collector-client.d.ts +20 -20
  92. package/dist/cjs/clients/internal-api/event-collector-client.js +36 -36
  93. package/dist/cjs/clients/internal-api/identity-client.d.ts +31 -31
  94. package/dist/cjs/clients/internal-api/identity-client.js +91 -91
  95. package/dist/cjs/clients/internal-api/index.d.ts +9 -9
  96. package/dist/cjs/clients/internal-api/index.js +25 -25
  97. package/dist/cjs/clients/internal-api/shopify-app-install-client.d.ts +37 -37
  98. package/dist/cjs/clients/internal-api/shopify-app-install-client.js +81 -81
  99. package/dist/cjs/clients/internal-api/subscriptions-client.d.ts +26 -26
  100. package/dist/cjs/clients/internal-api/subscriptions-client.js +77 -77
  101. package/dist/cjs/clients/internal-api/users-auth-client.d.ts +35 -35
  102. package/dist/cjs/clients/internal-api/users-auth-client.js +110 -110
  103. package/dist/cjs/clients/third-party/acuity-client.d.ts +9 -0
  104. package/dist/cjs/clients/third-party/acuity-client.js +35 -0
  105. package/dist/cjs/clients/third-party/acuity-client.js.map +1 -0
  106. package/dist/cjs/clients/third-party/emailable-client.d.ts +7 -7
  107. package/dist/cjs/clients/third-party/emailable-client.js +25 -25
  108. package/dist/cjs/clients/third-party/exchange-rate-api-client.d.ts +17 -17
  109. package/dist/cjs/clients/third-party/exchange-rate-api-client.js +19 -19
  110. package/dist/cjs/clients/third-party/index.d.ts +5 -4
  111. package/dist/cjs/clients/third-party/index.js +21 -20
  112. package/dist/cjs/clients/third-party/index.js.map +1 -1
  113. package/dist/cjs/clients/third-party/loops-client.d.ts +10 -10
  114. package/dist/cjs/clients/third-party/loops-client.js +30 -30
  115. package/dist/cjs/clients/third-party/shopify/graphql-order-queries.d.ts +25 -25
  116. package/dist/cjs/clients/third-party/shopify/graphql-order-queries.js +4 -4
  117. package/dist/cjs/clients/third-party/shopify/graphql-product-queries.d.ts +2 -2
  118. package/dist/cjs/clients/third-party/shopify/graphql-product-queries.js +5 -5
  119. package/dist/cjs/clients/third-party/shopify/shopify-graphql-client.d.ts +10 -10
  120. package/dist/cjs/clients/third-party/shopify/shopify-graphql-client.js +161 -161
  121. package/dist/cjs/clients/third-party/shopify-client.d.ts +29 -29
  122. package/dist/cjs/clients/third-party/shopify-client.js +146 -146
  123. package/dist/cjs/constants/index.d.ts +1 -1
  124. package/dist/cjs/constants/index.js +17 -17
  125. package/dist/cjs/constants/sqs.d.ts +20 -20
  126. package/dist/cjs/constants/sqs.js +26 -26
  127. package/dist/cjs/helpers/account-users-helper.d.ts +2 -2
  128. package/dist/cjs/helpers/account-users-helper.js +22 -22
  129. package/dist/cjs/helpers/acuity-helper.d.ts +2 -0
  130. package/dist/cjs/helpers/acuity-helper.js +23 -0
  131. package/dist/cjs/helpers/acuity-helper.js.map +1 -0
  132. package/dist/cjs/helpers/api-key-auth-helper.d.ts +9 -9
  133. package/dist/cjs/helpers/api-key-auth-helper.js +40 -40
  134. package/dist/cjs/helpers/api-key-authorizer-helper.d.ts +36 -36
  135. package/dist/cjs/helpers/api-key-authorizer-helper.js +87 -87
  136. package/dist/cjs/helpers/identity-cache-helper.d.ts +21 -21
  137. package/dist/cjs/helpers/identity-cache-helper.js +156 -156
  138. package/dist/cjs/helpers/index.d.ts +10 -9
  139. package/dist/cjs/helpers/index.js +26 -25
  140. package/dist/cjs/helpers/index.js.map +1 -1
  141. package/dist/cjs/helpers/input-validation-helper.d.ts +3 -3
  142. package/dist/cjs/helpers/input-validation-helper.js +22 -22
  143. package/dist/cjs/helpers/logging-helper.d.ts +16 -16
  144. package/dist/cjs/helpers/logging-helper.js +84 -84
  145. package/dist/cjs/helpers/response-helper.d.ts +18 -18
  146. package/dist/cjs/helpers/response-helper.js +43 -43
  147. package/dist/cjs/helpers/shopify-helper.d.ts +9 -9
  148. package/dist/cjs/helpers/shopify-helper.js +26 -26
  149. package/dist/cjs/helpers/sqs-utils.d.ts +6 -6
  150. package/dist/cjs/helpers/sqs-utils.js +14 -14
  151. package/dist/cjs/index.d.ts +7 -7
  152. package/dist/cjs/index.js +23 -23
  153. package/dist/cjs/libs/api-router/index.d.ts +2 -2
  154. package/dist/cjs/libs/api-router/index.js +18 -18
  155. package/dist/cjs/libs/api-router/public-api-router.d.ts +3 -3
  156. package/dist/cjs/libs/api-router/public-api-router.js +36 -36
  157. package/dist/cjs/libs/api-router/route-matcher.d.ts +21 -21
  158. package/dist/cjs/libs/api-router/route-matcher.js +36 -36
  159. package/dist/cjs/libs/click-id-parser.d.ts +23 -23
  160. package/dist/cjs/libs/click-id-parser.js +49 -49
  161. package/dist/cjs/libs/compression.d.ts +2 -2
  162. package/dist/cjs/libs/compression.js +33 -33
  163. package/dist/cjs/libs/cookie.d.ts +17 -17
  164. package/dist/cjs/libs/cookie.js +76 -76
  165. package/dist/cjs/libs/crypto.d.ts +4 -4
  166. package/dist/cjs/libs/crypto.js +25 -25
  167. package/dist/cjs/libs/csv.d.ts +2 -2
  168. package/dist/cjs/libs/csv.js +35 -35
  169. package/dist/cjs/libs/currency.d.ts +1 -1
  170. package/dist/cjs/libs/currency.js +29 -29
  171. package/dist/cjs/libs/dates.d.ts +12 -12
  172. package/dist/cjs/libs/dates.js +96 -96
  173. package/dist/cjs/libs/domain.d.ts +2 -2
  174. package/dist/cjs/libs/domain.js +38 -38
  175. package/dist/cjs/libs/emails.d.ts +6 -6
  176. package/dist/cjs/libs/emails.js +122 -122
  177. package/dist/cjs/libs/http-error.d.ts +21 -21
  178. package/dist/cjs/libs/http-error.js +63 -63
  179. package/dist/cjs/libs/http-status-codes.d.ts +58 -58
  180. package/dist/cjs/libs/http-status-codes.js +62 -62
  181. package/dist/cjs/libs/index.d.ts +18 -18
  182. package/dist/cjs/libs/index.js +34 -34
  183. package/dist/cjs/libs/numbers.d.ts +1 -1
  184. package/dist/cjs/libs/numbers.js +15 -15
  185. package/dist/cjs/libs/referrer-parser/index.d.ts +2 -2
  186. package/dist/cjs/libs/referrer-parser/index.js +18 -18
  187. package/dist/cjs/libs/referrer-parser/referrer-data.d.ts +9 -9
  188. package/dist/cjs/libs/referrer-parser/referrer-data.js +3307 -3307
  189. package/dist/cjs/libs/referrer-parser/referrer-parser-util.d.ts +20 -20
  190. package/dist/cjs/libs/referrer-parser/referrer-parser-util.js +131 -131
  191. package/dist/cjs/libs/strings.d.ts +3 -3
  192. package/dist/cjs/libs/strings.js +46 -46
  193. package/dist/cjs/libs/traits.d.ts +6 -6
  194. package/dist/cjs/libs/traits.js +65 -65
  195. package/dist/cjs/libs/url.d.ts +1 -1
  196. package/dist/cjs/libs/url.js +13 -13
  197. package/dist/cjs/services/acuity-api-service.d.ts +8 -0
  198. package/dist/cjs/services/acuity-api-service.js +55 -0
  199. package/dist/cjs/services/acuity-api-service.js.map +1 -0
  200. package/dist/cjs/services/cache/generic-cached-object.d.ts +5 -5
  201. package/dist/cjs/services/cache/generic-cached-object.js +2 -2
  202. package/dist/cjs/services/cache/index.d.ts +1 -1
  203. package/dist/cjs/services/cache/index.js +17 -17
  204. package/dist/cjs/services/cache/product-cache-service.d.ts +21 -21
  205. package/dist/cjs/services/cache/product-cache-service.js +76 -76
  206. package/dist/cjs/services/currency-exchange-rate-lookup-service.d.ts +11 -11
  207. package/dist/cjs/services/currency-exchange-rate-lookup-service.js +66 -66
  208. package/dist/cjs/services/db/accounts-db-service.d.ts +9 -9
  209. package/dist/cjs/services/db/accounts-db-service.js +33 -33
  210. package/dist/cjs/services/db/api-keys-db-service.d.ts +10 -10
  211. package/dist/cjs/services/db/api-keys-db-service.js +36 -36
  212. package/dist/cjs/services/db/currency-exchange-rates-db-service.d.ts +21 -21
  213. package/dist/cjs/services/db/currency-exchange-rates-db-service.js +39 -39
  214. package/dist/cjs/services/db/destinations-db-service.d.ts +12 -12
  215. package/dist/cjs/services/db/destinations-db-service.js +76 -76
  216. package/dist/cjs/services/db/identity-cache-db-service.d.ts +28 -28
  217. package/dist/cjs/services/db/identity-cache-db-service.js +320 -320
  218. package/dist/cjs/services/db/index.d.ts +13 -13
  219. package/dist/cjs/services/db/index.js +29 -29
  220. package/dist/cjs/services/db/log-events-db-service.d.ts +11 -11
  221. package/dist/cjs/services/db/log-events-db-service.js +181 -181
  222. package/dist/cjs/services/db/pixels-db-service.d.ts +8 -8
  223. package/dist/cjs/services/db/pixels-db-service.js +35 -35
  224. package/dist/cjs/services/db/purchasable-contacts-db-service.d.ts +9 -9
  225. package/dist/cjs/services/db/purchasable-contacts-db-service.js +43 -43
  226. package/dist/cjs/services/db/purchased-contacts-db-service.d.ts +17 -17
  227. package/dist/cjs/services/db/purchased-contacts-db-service.js +143 -143
  228. package/dist/cjs/services/db/shopify-app-installs-db-service.d.ts +8 -8
  229. package/dist/cjs/services/db/shopify-app-installs-db-service.js +51 -51
  230. package/dist/cjs/services/db/shopify-products-cache-db-service.d.ts +16 -16
  231. package/dist/cjs/services/db/shopify-products-cache-db-service.js +73 -73
  232. package/dist/cjs/services/db/subscriptions-db-service.d.ts +10 -10
  233. package/dist/cjs/services/db/subscriptions-db-service.js +34 -34
  234. package/dist/cjs/services/db/tracking-events-db-service.d.ts +20 -20
  235. package/dist/cjs/services/db/tracking-events-db-service.js +165 -165
  236. package/dist/cjs/services/eventbridge-integration-service.d.ts +9 -9
  237. package/dist/cjs/services/eventbridge-integration-service.js +28 -28
  238. package/dist/cjs/services/events/index.d.ts +3 -3
  239. package/dist/cjs/services/events/index.js +19 -19
  240. package/dist/cjs/services/events/log-event-service.d.ts +19 -19
  241. package/dist/cjs/services/events/log-event-service.js +77 -77
  242. package/dist/cjs/services/events/metric-event-service.d.ts +9 -9
  243. package/dist/cjs/services/events/metric-event-service.js +49 -49
  244. package/dist/cjs/services/events/tracking-event-sqs-service.d.ts +8 -8
  245. package/dist/cjs/services/events/tracking-event-sqs-service.js +34 -34
  246. package/dist/cjs/services/generic-cache-service.d.ts +7 -7
  247. package/dist/cjs/services/generic-cache-service.js +33 -33
  248. package/dist/cjs/services/index.d.ts +9 -8
  249. package/dist/cjs/services/index.js +25 -24
  250. package/dist/cjs/services/index.js.map +1 -1
  251. package/dist/cjs/services/ipdata-lookup-service.d.ts +20 -20
  252. package/dist/cjs/services/ipdata-lookup-service.js +112 -112
  253. package/dist/cjs/services/shopify/index.d.ts +2 -2
  254. package/dist/cjs/services/shopify/index.js +18 -18
  255. package/dist/cjs/services/shopify/products/index.d.ts +1 -1
  256. package/dist/cjs/services/shopify/products/index.js +17 -17
  257. package/dist/cjs/services/shopify/products/shopify-products-serviceV2.d.ts +17 -17
  258. package/dist/cjs/services/shopify/products/shopify-products-serviceV2.js +112 -112
  259. package/dist/cjs/services/shopify/shopify-graphql-transformer.d.ts +8 -8
  260. package/dist/cjs/services/shopify/shopify-graphql-transformer.js +141 -141
  261. package/dist/cjs/types/acuity-types.d.ts +74 -0
  262. package/dist/cjs/types/acuity-types.js +3 -0
  263. package/dist/cjs/types/acuity-types.js.map +1 -0
  264. package/dist/cjs/types/api-response.d.ts +6 -6
  265. package/dist/cjs/types/api-response.js +2 -2
  266. package/dist/cjs/types/index.d.ts +4 -3
  267. package/dist/cjs/types/index.js +33 -32
  268. package/dist/cjs/types/index.js.map +1 -1
  269. package/dist/cjs/types/internal-events/event-detail-types.d.ts +20 -20
  270. package/dist/cjs/types/internal-events/event-detail-types.js +27 -27
  271. package/dist/cjs/types/internal-events/index.d.ts +1 -1
  272. package/dist/cjs/types/internal-events/index.js +17 -17
  273. package/dist/cjs/types/shopify-graphql-types/admin.generated.d.ts +123 -123
  274. package/dist/cjs/types/shopify-graphql-types/admin.generated.js +2 -2
  275. package/dist/cjs/types/shopify-graphql-types/admin.types.d.ts +26289 -26289
  276. package/dist/cjs/types/shopify-graphql-types/admin.types.js +5311 -5311
  277. package/dist/cjs/types/shopify-graphql-types/index.d.ts +2 -2
  278. package/dist/cjs/types/shopify-graphql-types/index.js +18 -18
  279. package/dist/cjs/types/shopify-rest-types.d.ts +767 -767
  280. package/dist/cjs/types/shopify-rest-types.js +2 -2
  281. package/dist/cjs/utils/compression.d.ts +36 -36
  282. package/dist/cjs/utils/compression.js +198 -198
  283. package/dist/cjs/utils/index.d.ts +3 -3
  284. package/dist/cjs/utils/index.js +19 -19
  285. package/dist/cjs/utils/retry-envelope.d.ts +12 -12
  286. package/dist/cjs/utils/retry-envelope.js +28 -28
  287. package/dist/cjs/utils/size.d.ts +2 -2
  288. package/dist/cjs/utils/size.js +49 -49
  289. package/dist/esm/__tests__/clients/acuity-client.spec.d.ts +1 -0
  290. package/dist/esm/__tests__/clients/acuity-client.spec.js +32 -0
  291. package/dist/esm/__tests__/clients/acuity-client.spec.js.map +1 -0
  292. package/dist/esm/__tests__/clients/cross-platform-compression.spec.d.ts +1 -0
  293. package/dist/esm/__tests__/clients/cross-platform-compression.spec.js +330 -0
  294. package/dist/esm/__tests__/clients/cross-platform-compression.spec.js.map +1 -0
  295. package/dist/esm/__tests__/clients/sqs-bundled-client.spec.d.ts +1 -1
  296. package/dist/esm/__tests__/clients/sqs-bundled-client.spec.js +896 -896
  297. package/dist/esm/__tests__/clients/sqs-bundling-contracts.spec.d.ts +1 -0
  298. package/dist/esm/__tests__/clients/sqs-bundling-contracts.spec.js +551 -0
  299. package/dist/esm/__tests__/clients/sqs-bundling-contracts.spec.js.map +1 -0
  300. package/dist/esm/__tests__/clients/sqs-client.spec.d.ts +1 -1
  301. package/dist/esm/__tests__/clients/sqs-client.spec.js +189 -189
  302. package/dist/esm/__tests__/clients/sqs-unbundle.spec.d.ts +1 -1
  303. package/dist/esm/__tests__/clients/sqs-unbundle.spec.js +1355 -1226
  304. package/dist/esm/__tests__/clients/sqs-unbundle.spec.js.map +1 -1
  305. package/dist/esm/__tests__/db/shared-read-db-services.spec.d.ts +1 -1
  306. package/dist/esm/__tests__/db/shared-read-db-services.spec.js +87 -87
  307. package/dist/esm/__tests__/helpers/account-users-helper.spec.d.ts +1 -1
  308. package/dist/esm/__tests__/helpers/account-users-helper.spec.js +218 -218
  309. package/dist/esm/__tests__/helpers/acuity-helper.spec.d.ts +1 -0
  310. package/dist/esm/__tests__/helpers/acuity-helper.spec.js +24 -0
  311. package/dist/esm/__tests__/helpers/acuity-helper.spec.js.map +1 -0
  312. package/dist/esm/__tests__/helpers/api-key-auth-helper.spec.d.ts +1 -1
  313. package/dist/esm/__tests__/helpers/api-key-auth-helper.spec.js +80 -80
  314. package/dist/esm/__tests__/identity-cache/identity-cache-db-service.spec.d.ts +1 -1
  315. package/dist/esm/__tests__/identity-cache/identity-cache-db-service.spec.js +672 -672
  316. package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.d.ts +1 -1
  317. package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js +586 -586
  318. package/dist/esm/__tests__/integration/sqs-bundling-roundtrip.spec.d.ts +1 -1
  319. package/dist/esm/__tests__/integration/sqs-bundling-roundtrip.spec.js +582 -582
  320. package/dist/esm/__tests__/libs/compress-decompress.spec.d.ts +1 -1
  321. package/dist/esm/__tests__/libs/compress-decompress.spec.js +14 -14
  322. package/dist/esm/__tests__/libs/currency.spec.d.ts +1 -1
  323. package/dist/esm/__tests__/libs/currency.spec.js +218 -218
  324. package/dist/esm/__tests__/libs/dates.spec.d.ts +1 -1
  325. package/dist/esm/__tests__/libs/dates.spec.js +128 -128
  326. package/dist/esm/__tests__/libs/domain.spec.d.ts +1 -1
  327. package/dist/esm/__tests__/libs/domain.spec.js +105 -105
  328. package/dist/esm/__tests__/libs/numbers.spec.d.ts +1 -1
  329. package/dist/esm/__tests__/libs/numbers.spec.js +259 -259
  330. package/dist/esm/__tests__/s3-client/s3-client.spec.d.ts +1 -1
  331. package/dist/esm/__tests__/s3-client/s3-client.spec.js +31 -31
  332. package/dist/esm/__tests__/services/acuity-api-service.spec.d.ts +1 -0
  333. package/dist/esm/__tests__/services/acuity-api-service.spec.js +50 -0
  334. package/dist/esm/__tests__/services/acuity-api-service.spec.js.map +1 -0
  335. package/dist/esm/__tests__/shopify/shopify-graphql-transformer.spec.d.ts +1 -1
  336. package/dist/esm/__tests__/shopify/shopify-graphql-transformer.spec.js +33 -33
  337. package/dist/esm/__tests__/unit/libs/api-router/public-api-router.spec.d.ts +1 -1
  338. package/dist/esm/__tests__/unit/libs/api-router/public-api-router.spec.js +156 -156
  339. package/dist/esm/__tests__/unit/libs/api-router/route-matcher.spec.d.ts +1 -1
  340. package/dist/esm/__tests__/unit/libs/api-router/route-matcher.spec.js +67 -67
  341. package/dist/esm/clients/generic/cognito-client.d.ts +23 -23
  342. package/dist/esm/clients/generic/cognito-client.js +204 -204
  343. package/dist/esm/clients/generic/dynamodb-client.d.ts +18 -18
  344. package/dist/esm/clients/generic/dynamodb-client.js +168 -168
  345. package/dist/esm/clients/generic/eventbridge-client.d.ts +14 -14
  346. package/dist/esm/clients/generic/eventbridge-client.js +47 -47
  347. package/dist/esm/clients/generic/http-client.d.ts +14 -14
  348. package/dist/esm/clients/generic/http-client.js +53 -53
  349. package/dist/esm/clients/generic/index.d.ts +13 -13
  350. package/dist/esm/clients/generic/index.js +13 -13
  351. package/dist/esm/clients/generic/lambda-invoke-client.d.ts +10 -10
  352. package/dist/esm/clients/generic/lambda-invoke-client.js +35 -35
  353. package/dist/esm/clients/generic/location-client.d.ts +8 -8
  354. package/dist/esm/clients/generic/location-client.js +27 -27
  355. package/dist/esm/clients/generic/redis-client.d.ts +33 -33
  356. package/dist/esm/clients/generic/redis-client.js +184 -184
  357. package/dist/esm/clients/generic/s3-client.d.ts +23 -23
  358. package/dist/esm/clients/generic/s3-client.js +209 -209
  359. package/dist/esm/clients/generic/singlestore-db-client.d.ts +14 -14
  360. package/dist/esm/clients/generic/singlestore-db-client.js +40 -40
  361. package/dist/esm/clients/generic/sqs-bundled-client.d.ts +15 -15
  362. package/dist/esm/clients/generic/sqs-bundled-client.js +307 -307
  363. package/dist/esm/clients/generic/sqs-bundled-client.types.d.ts +53 -53
  364. package/dist/esm/clients/generic/sqs-bundled-client.types.js +14 -14
  365. package/dist/esm/clients/generic/sqs-client.d.ts +53 -53
  366. package/dist/esm/clients/generic/sqs-client.js +281 -281
  367. package/dist/esm/clients/generic/sqs-unbundle.d.ts +32 -32
  368. package/dist/esm/clients/generic/sqs-unbundle.js +137 -137
  369. package/dist/esm/clients/index.d.ts +3 -3
  370. package/dist/esm/clients/index.js +3 -3
  371. package/dist/esm/clients/internal-api/accounts-client.d.ts +91 -91
  372. package/dist/esm/clients/internal-api/accounts-client.js +125 -125
  373. package/dist/esm/clients/internal-api/cache-lambda-client.d.ts +26 -26
  374. package/dist/esm/clients/internal-api/cache-lambda-client.js +85 -85
  375. package/dist/esm/clients/internal-api/db-management-client.d.ts +18 -18
  376. package/dist/esm/clients/internal-api/db-management-client.js +32 -32
  377. package/dist/esm/clients/internal-api/destinations-client.d.ts +34 -34
  378. package/dist/esm/clients/internal-api/destinations-client.js +75 -75
  379. package/dist/esm/clients/internal-api/event-collector-client.d.ts +20 -20
  380. package/dist/esm/clients/internal-api/event-collector-client.js +32 -32
  381. package/dist/esm/clients/internal-api/identity-client.d.ts +31 -31
  382. package/dist/esm/clients/internal-api/identity-client.js +87 -87
  383. package/dist/esm/clients/internal-api/index.d.ts +9 -9
  384. package/dist/esm/clients/internal-api/index.js +9 -9
  385. package/dist/esm/clients/internal-api/shopify-app-install-client.d.ts +37 -37
  386. package/dist/esm/clients/internal-api/shopify-app-install-client.js +77 -77
  387. package/dist/esm/clients/internal-api/subscriptions-client.d.ts +26 -26
  388. package/dist/esm/clients/internal-api/subscriptions-client.js +73 -73
  389. package/dist/esm/clients/internal-api/users-auth-client.d.ts +35 -35
  390. package/dist/esm/clients/internal-api/users-auth-client.js +106 -106
  391. package/dist/esm/clients/third-party/acuity-client.d.ts +9 -0
  392. package/dist/esm/clients/third-party/acuity-client.js +31 -0
  393. package/dist/esm/clients/third-party/acuity-client.js.map +1 -0
  394. package/dist/esm/clients/third-party/emailable-client.d.ts +7 -7
  395. package/dist/esm/clients/third-party/emailable-client.js +21 -21
  396. package/dist/esm/clients/third-party/exchange-rate-api-client.d.ts +17 -17
  397. package/dist/esm/clients/third-party/exchange-rate-api-client.js +15 -15
  398. package/dist/esm/clients/third-party/index.d.ts +5 -4
  399. package/dist/esm/clients/third-party/index.js +5 -4
  400. package/dist/esm/clients/third-party/index.js.map +1 -1
  401. package/dist/esm/clients/third-party/loops-client.d.ts +10 -10
  402. package/dist/esm/clients/third-party/loops-client.js +26 -26
  403. package/dist/esm/clients/third-party/shopify/graphql-order-queries.d.ts +25 -25
  404. package/dist/esm/clients/third-party/shopify/graphql-order-queries.js +1 -1
  405. package/dist/esm/clients/third-party/shopify/graphql-product-queries.d.ts +2 -2
  406. package/dist/esm/clients/third-party/shopify/graphql-product-queries.js +2 -2
  407. package/dist/esm/clients/third-party/shopify/shopify-graphql-client.d.ts +10 -10
  408. package/dist/esm/clients/third-party/shopify/shopify-graphql-client.js +157 -157
  409. package/dist/esm/clients/third-party/shopify-client.d.ts +29 -29
  410. package/dist/esm/clients/third-party/shopify-client.js +142 -142
  411. package/dist/esm/constants/index.d.ts +1 -1
  412. package/dist/esm/constants/index.js +1 -1
  413. package/dist/esm/constants/sqs.d.ts +20 -20
  414. package/dist/esm/constants/sqs.js +22 -22
  415. package/dist/esm/helpers/account-users-helper.d.ts +2 -2
  416. package/dist/esm/helpers/account-users-helper.js +18 -18
  417. package/dist/esm/helpers/acuity-helper.d.ts +2 -0
  418. package/dist/esm/helpers/acuity-helper.js +19 -0
  419. package/dist/esm/helpers/acuity-helper.js.map +1 -0
  420. package/dist/esm/helpers/api-key-auth-helper.d.ts +9 -9
  421. package/dist/esm/helpers/api-key-auth-helper.js +35 -35
  422. package/dist/esm/helpers/api-key-authorizer-helper.d.ts +36 -36
  423. package/dist/esm/helpers/api-key-authorizer-helper.js +83 -83
  424. package/dist/esm/helpers/identity-cache-helper.d.ts +21 -21
  425. package/dist/esm/helpers/identity-cache-helper.js +151 -151
  426. package/dist/esm/helpers/index.d.ts +10 -9
  427. package/dist/esm/helpers/index.js +10 -9
  428. package/dist/esm/helpers/index.js.map +1 -1
  429. package/dist/esm/helpers/input-validation-helper.d.ts +3 -3
  430. package/dist/esm/helpers/input-validation-helper.js +18 -18
  431. package/dist/esm/helpers/logging-helper.d.ts +16 -16
  432. package/dist/esm/helpers/logging-helper.js +56 -56
  433. package/dist/esm/helpers/response-helper.d.ts +18 -18
  434. package/dist/esm/helpers/response-helper.js +37 -37
  435. package/dist/esm/helpers/shopify-helper.d.ts +9 -9
  436. package/dist/esm/helpers/shopify-helper.js +21 -21
  437. package/dist/esm/helpers/sqs-utils.d.ts +6 -6
  438. package/dist/esm/helpers/sqs-utils.js +9 -9
  439. package/dist/esm/index.d.ts +7 -7
  440. package/dist/esm/index.js +7 -7
  441. package/dist/esm/libs/api-router/index.d.ts +2 -2
  442. package/dist/esm/libs/api-router/index.js +2 -2
  443. package/dist/esm/libs/api-router/public-api-router.d.ts +3 -3
  444. package/dist/esm/libs/api-router/public-api-router.js +32 -32
  445. package/dist/esm/libs/api-router/route-matcher.d.ts +21 -21
  446. package/dist/esm/libs/api-router/route-matcher.js +30 -30
  447. package/dist/esm/libs/click-id-parser.d.ts +23 -23
  448. package/dist/esm/libs/click-id-parser.js +45 -45
  449. package/dist/esm/libs/compression.d.ts +2 -2
  450. package/dist/esm/libs/compression.js +25 -25
  451. package/dist/esm/libs/cookie.d.ts +17 -17
  452. package/dist/esm/libs/cookie.js +70 -70
  453. package/dist/esm/libs/crypto.d.ts +4 -4
  454. package/dist/esm/libs/crypto.js +15 -15
  455. package/dist/esm/libs/csv.d.ts +2 -2
  456. package/dist/esm/libs/csv.js +30 -30
  457. package/dist/esm/libs/currency.d.ts +1 -1
  458. package/dist/esm/libs/currency.js +22 -22
  459. package/dist/esm/libs/dates.d.ts +12 -12
  460. package/dist/esm/libs/dates.js +83 -83
  461. package/dist/esm/libs/domain.d.ts +2 -2
  462. package/dist/esm/libs/domain.js +33 -33
  463. package/dist/esm/libs/emails.d.ts +6 -6
  464. package/dist/esm/libs/emails.js +115 -115
  465. package/dist/esm/libs/http-error.d.ts +21 -21
  466. package/dist/esm/libs/http-error.js +59 -59
  467. package/dist/esm/libs/http-status-codes.d.ts +58 -58
  468. package/dist/esm/libs/http-status-codes.js +59 -59
  469. package/dist/esm/libs/index.d.ts +18 -18
  470. package/dist/esm/libs/index.js +18 -18
  471. package/dist/esm/libs/numbers.d.ts +1 -1
  472. package/dist/esm/libs/numbers.js +11 -11
  473. package/dist/esm/libs/referrer-parser/index.d.ts +2 -2
  474. package/dist/esm/libs/referrer-parser/index.js +2 -2
  475. package/dist/esm/libs/referrer-parser/referrer-data.d.ts +9 -9
  476. package/dist/esm/libs/referrer-parser/referrer-data.js +3304 -3304
  477. package/dist/esm/libs/referrer-parser/referrer-parser-util.d.ts +20 -20
  478. package/dist/esm/libs/referrer-parser/referrer-parser-util.js +124 -124
  479. package/dist/esm/libs/strings.d.ts +3 -3
  480. package/dist/esm/libs/strings.js +40 -40
  481. package/dist/esm/libs/traits.d.ts +6 -6
  482. package/dist/esm/libs/traits.js +54 -54
  483. package/dist/esm/libs/url.d.ts +1 -1
  484. package/dist/esm/libs/url.js +9 -9
  485. package/dist/esm/services/acuity-api-service.d.ts +8 -0
  486. package/dist/esm/services/acuity-api-service.js +51 -0
  487. package/dist/esm/services/acuity-api-service.js.map +1 -0
  488. package/dist/esm/services/cache/generic-cached-object.d.ts +5 -5
  489. package/dist/esm/services/cache/generic-cached-object.js +1 -1
  490. package/dist/esm/services/cache/index.d.ts +1 -1
  491. package/dist/esm/services/cache/index.js +1 -1
  492. package/dist/esm/services/cache/product-cache-service.d.ts +21 -21
  493. package/dist/esm/services/cache/product-cache-service.js +68 -68
  494. package/dist/esm/services/currency-exchange-rate-lookup-service.d.ts +11 -11
  495. package/dist/esm/services/currency-exchange-rate-lookup-service.js +62 -62
  496. package/dist/esm/services/db/accounts-db-service.d.ts +9 -9
  497. package/dist/esm/services/db/accounts-db-service.js +29 -29
  498. package/dist/esm/services/db/api-keys-db-service.d.ts +10 -10
  499. package/dist/esm/services/db/api-keys-db-service.js +32 -32
  500. package/dist/esm/services/db/currency-exchange-rates-db-service.d.ts +21 -21
  501. package/dist/esm/services/db/currency-exchange-rates-db-service.js +35 -35
  502. package/dist/esm/services/db/destinations-db-service.d.ts +12 -12
  503. package/dist/esm/services/db/destinations-db-service.js +72 -72
  504. package/dist/esm/services/db/identity-cache-db-service.d.ts +28 -28
  505. package/dist/esm/services/db/identity-cache-db-service.js +313 -313
  506. package/dist/esm/services/db/index.d.ts +13 -13
  507. package/dist/esm/services/db/index.js +13 -13
  508. package/dist/esm/services/db/log-events-db-service.d.ts +11 -11
  509. package/dist/esm/services/db/log-events-db-service.js +177 -177
  510. package/dist/esm/services/db/pixels-db-service.d.ts +8 -8
  511. package/dist/esm/services/db/pixels-db-service.js +31 -31
  512. package/dist/esm/services/db/purchasable-contacts-db-service.d.ts +9 -9
  513. package/dist/esm/services/db/purchasable-contacts-db-service.js +39 -39
  514. package/dist/esm/services/db/purchased-contacts-db-service.d.ts +17 -17
  515. package/dist/esm/services/db/purchased-contacts-db-service.js +139 -139
  516. package/dist/esm/services/db/shopify-app-installs-db-service.d.ts +8 -8
  517. package/dist/esm/services/db/shopify-app-installs-db-service.js +47 -47
  518. package/dist/esm/services/db/shopify-products-cache-db-service.d.ts +16 -16
  519. package/dist/esm/services/db/shopify-products-cache-db-service.js +66 -66
  520. package/dist/esm/services/db/subscriptions-db-service.d.ts +10 -10
  521. package/dist/esm/services/db/subscriptions-db-service.js +30 -30
  522. package/dist/esm/services/db/tracking-events-db-service.d.ts +20 -20
  523. package/dist/esm/services/db/tracking-events-db-service.js +161 -161
  524. package/dist/esm/services/eventbridge-integration-service.d.ts +9 -9
  525. package/dist/esm/services/eventbridge-integration-service.js +24 -24
  526. package/dist/esm/services/events/index.d.ts +3 -3
  527. package/dist/esm/services/events/index.js +3 -3
  528. package/dist/esm/services/events/log-event-service.d.ts +19 -19
  529. package/dist/esm/services/events/log-event-service.js +73 -73
  530. package/dist/esm/services/events/metric-event-service.d.ts +9 -9
  531. package/dist/esm/services/events/metric-event-service.js +45 -45
  532. package/dist/esm/services/events/tracking-event-sqs-service.d.ts +8 -8
  533. package/dist/esm/services/events/tracking-event-sqs-service.js +30 -30
  534. package/dist/esm/services/generic-cache-service.d.ts +7 -7
  535. package/dist/esm/services/generic-cache-service.js +29 -29
  536. package/dist/esm/services/index.d.ts +9 -8
  537. package/dist/esm/services/index.js +9 -8
  538. package/dist/esm/services/index.js.map +1 -1
  539. package/dist/esm/services/ipdata-lookup-service.d.ts +20 -20
  540. package/dist/esm/services/ipdata-lookup-service.js +108 -108
  541. package/dist/esm/services/shopify/index.d.ts +2 -2
  542. package/dist/esm/services/shopify/index.js +2 -2
  543. package/dist/esm/services/shopify/products/index.d.ts +1 -1
  544. package/dist/esm/services/shopify/products/index.js +1 -1
  545. package/dist/esm/services/shopify/products/shopify-products-serviceV2.d.ts +17 -17
  546. package/dist/esm/services/shopify/products/shopify-products-serviceV2.js +108 -108
  547. package/dist/esm/services/shopify/shopify-graphql-transformer.d.ts +8 -8
  548. package/dist/esm/services/shopify/shopify-graphql-transformer.js +138 -138
  549. package/dist/esm/types/acuity-types.d.ts +74 -0
  550. package/dist/esm/types/acuity-types.js +2 -0
  551. package/dist/esm/types/acuity-types.js.map +1 -0
  552. package/dist/esm/types/api-response.d.ts +6 -6
  553. package/dist/esm/types/api-response.js +1 -1
  554. package/dist/esm/types/index.d.ts +4 -3
  555. package/dist/esm/types/index.js +4 -3
  556. package/dist/esm/types/index.js.map +1 -1
  557. package/dist/esm/types/internal-events/event-detail-types.d.ts +20 -20
  558. package/dist/esm/types/internal-events/event-detail-types.js +24 -24
  559. package/dist/esm/types/internal-events/index.d.ts +1 -1
  560. package/dist/esm/types/internal-events/index.js +1 -1
  561. package/dist/esm/types/shopify-graphql-types/admin.generated.d.ts +123 -123
  562. package/dist/esm/types/shopify-graphql-types/admin.generated.js +1 -1
  563. package/dist/esm/types/shopify-graphql-types/admin.types.d.ts +26289 -26289
  564. package/dist/esm/types/shopify-graphql-types/admin.types.js +5299 -5299
  565. package/dist/esm/types/shopify-graphql-types/index.d.ts +2 -2
  566. package/dist/esm/types/shopify-graphql-types/index.js +2 -2
  567. package/dist/esm/types/shopify-rest-types.d.ts +767 -767
  568. package/dist/esm/types/shopify-rest-types.js +1 -1
  569. package/dist/esm/utils/compression.d.ts +36 -36
  570. package/dist/esm/utils/compression.js +187 -187
  571. package/dist/esm/utils/index.d.ts +3 -3
  572. package/dist/esm/utils/index.js +3 -3
  573. package/dist/esm/utils/retry-envelope.d.ts +12 -12
  574. package/dist/esm/utils/retry-envelope.js +22 -22
  575. package/dist/esm/utils/size.d.ts +2 -2
  576. package/dist/esm/utils/size.js +44 -44
  577. package/package.json +134 -134
@@ -1,585 +1,585 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const sqs_bundled_client_1 = require("../../clients/generic/sqs-bundled-client");
4
- const sqs_bundled_client_types_1 = require("../../clients/generic/sqs-bundled-client.types");
5
- const sqs_unbundle_1 = require("../../clients/generic/sqs-unbundle");
6
- const compression_1 = require("../../utils/compression");
7
- const sqs_1 = require("../../constants/sqs");
8
- jest.mock('../../helpers/logging-helper', () => ({
9
- Logger: {
10
- debug: jest.fn(),
11
- info: jest.fn(),
12
- warn: jest.fn(),
13
- error: jest.fn(),
14
- },
15
- }));
16
- function makeTestEvent(id, name = 'test', value, metadata) {
17
- return { id, name, value, metadata };
18
- }
19
- function makeRealisticTrackingEvent(index) {
20
- return {
21
- anonymousId: `anon-${index}-${Math.random().toString(36).substring(7)}`,
22
- accountId: `acc-${index % 10}`,
23
- pixelId: `pixel-${index % 5}`,
24
- eventType: ['track', 'identify', 'page'][index % 3] ?? 'track',
25
- eventName: ['purchase', 'add_to_cart', 'page_view', 'begin_checkout'][index % 4] ?? 'track',
26
- timestamp: new Date(Date.now() - index * 1000).toISOString(),
27
- context: {
28
- page: {
29
- url: `https://example.com/product/${index}`,
30
- path: `/product/${index}`,
31
- title: `Product ${index} - Example Store`,
32
- referrer: index % 3 === 0 ? 'https://google.com' : '',
33
- },
34
- userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
35
- ip: `192.168.${index % 256}.${(index * 7) % 256}`,
36
- locale: ['en-US', 'en-GB', 'de-DE', 'fr-FR'][index % 4] ?? 'en-US',
37
- timezone: 'America/New_York',
38
- },
39
- properties: {
40
- productId: `prod-${index}`,
41
- productName: `Amazing Product ${index}`,
42
- price: 29.99 + (index % 100),
43
- currency: 'USD',
44
- quantity: (index % 5) + 1,
45
- category: ['Electronics', 'Clothing', 'Home', 'Sports'][index % 4],
46
- customFields: {
47
- brand: `Brand${index % 20}`,
48
- sku: `SKU-${index}-${Date.now()}`,
49
- inStock: index % 2 === 0,
50
- },
51
- },
52
- shopifyData: index % 3 === 0
53
- ? {
54
- checkoutToken: `checkout-${index}`,
55
- orderId: index % 5 === 0 ? `order-${index}` : undefined,
56
- customerEmail: `customer${index}@example.com`,
57
- lineItems: Array.from({ length: (index % 3) + 1 }, (_, j) => ({
58
- variantId: `variant-${index}-${j}`,
59
- title: `Line Item ${j}`,
60
- price: 19.99 + j * 10,
61
- quantity: j + 1,
62
- })),
63
- }
64
- : undefined,
65
- };
66
- }
67
- function simulateSqsDelivery(envelopes) {
68
- return envelopes.map((env, i) => ({
69
- messageId: `msg-${i}-${Date.now()}`,
70
- body: JSON.stringify({ messageBody: env }),
71
- }));
72
- }
73
- describe('Full Round-Trip: Producer → Consumer', () => {
74
- let mockSqsClient;
75
- let capturedEnvelopes;
76
- beforeEach(() => {
77
- capturedEnvelopes = [];
78
- mockSqsClient = {
79
- buildAndSendMessagesV2: jest.fn(async (_type, envelopes) => {
80
- capturedEnvelopes.push(...envelopes);
81
- return {
82
- successCount: envelopes.length,
83
- failedCount: 0,
84
- batchCount: 1,
85
- failedMessages: [],
86
- };
87
- }),
88
- queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/test-queue',
89
- limits: (0, sqs_1.createSqsLimits)(sqs_1.SQS_1MB),
90
- };
91
- });
92
- describe('1. Basic round-trip test (100 items)', () => {
93
- it('100 items survive complete round-trip with deep equality', async () => {
94
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
95
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
96
- compressionLevel: 3,
97
- });
98
- const originalItems = Array.from({ length: 100 }, (_, i) => ({
99
- id: `event-${i}`,
100
- name: 'purchase',
101
- value: i * 99.99,
102
- metadata: { source: 'test', index: i },
103
- }));
104
- await bundledClient.sendBundled('test', originalItems);
105
- expect(capturedEnvelopes.length).toBeGreaterThanOrEqual(1);
106
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
107
- const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
108
- expect(recoveredItems).toHaveLength(100);
109
- expect(recoveredItems).toEqual(originalItems);
110
- expect(stats.bundledSqsRecords).toBe(capturedEnvelopes.length);
111
- expect(stats.failedRecords).toBe(0);
112
- });
113
- it('preserves all primitive types correctly', async () => {
114
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
115
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
116
- });
117
- const originalItems = [
118
- { id: 'str', name: 'string-test', value: undefined },
119
- { id: 'num', name: 'number-test', value: 123.456 },
120
- { id: 'zero', name: 'zero-test', value: 0 },
121
- { id: 'neg', name: 'negative-test', value: -999.99 },
122
- { id: 'big', name: 'big-number', value: Number.MAX_SAFE_INTEGER },
123
- ];
124
- await bundledClient.sendBundled('test', originalItems);
125
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
126
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
127
- expect(recoveredItems).toEqual(originalItems);
128
- });
129
- });
130
- describe('2. Large scale round-trip (1000 items)', () => {
131
- it('1000 items survive round-trip with no data loss', async () => {
132
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
133
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
134
- compressionLevel: 3,
135
- });
136
- const originalItems = Array.from({ length: 1000 }, (_, i) => ({
137
- id: `event-${i.toString().padStart(4, '0')}`,
138
- name: `type-${i % 10}`,
139
- value: i * 1.5,
140
- metadata: {
141
- batch: Math.floor(i / 100),
142
- position: i % 100,
143
- timestamp: Date.now() + i,
144
- },
145
- }));
146
- await bundledClient.sendBundled('test', originalItems);
147
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
148
- const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
149
- expect(recoveredItems).toHaveLength(1000);
150
- expect(stats.totalItems).toBe(1000);
151
- expect(stats.failedRecords).toBe(0);
152
- const recoveredIds = recoveredItems.map((item) => item.id);
153
- const originalIds = originalItems.map((item) => item.id);
154
- expect(new Set(recoveredIds)).toEqual(new Set(originalIds));
155
- expect(recoveredItems).toEqual(originalItems);
156
- });
157
- it('preserves order within each bundle', async () => {
158
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
159
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
160
- maxItemsPerBundle: 100,
161
- });
162
- const originalItems = Array.from({ length: 500 }, (_, i) => makeTestEvent(`seq-${i}`, 'ordered', i));
163
- await bundledClient.sendBundled('test', originalItems);
164
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
165
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
166
- let currentBundleStart = 0;
167
- for (const envelope of capturedEnvelopes) {
168
- const bundleSize = envelope.n;
169
- const bundleItems = recoveredItems.slice(currentBundleStart, currentBundleStart + bundleSize);
170
- for (let j = 1; j < bundleItems.length; j++) {
171
- const prevValue = bundleItems[j - 1]?.value ?? 0;
172
- const currValue = bundleItems[j]?.value ?? 0;
173
- expect(currValue).toBeGreaterThan(prevValue);
174
- }
175
- currentBundleStart += bundleSize;
176
- }
177
- });
178
- });
179
- describe('3. Compression round-trip verification', () => {
180
- it('ZSTD compressed data decompresses to byte-exact JSON', async () => {
181
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
182
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
183
- compressionLevel: 5,
184
- });
185
- const originalItems = Array.from({ length: 50 }, (_, i) => ({
186
- id: `compress-test-${i}`,
187
- name: 'compression-verification',
188
- value: i * 123.456789,
189
- metadata: {
190
- unicode: '日本語テスト',
191
- emoji: '🚀✨🎉',
192
- special: 'line\nbreak\ttab\r\nwindows',
193
- quotes: '"double" and \'single\'',
194
- },
195
- }));
196
- const originalJson = JSON.stringify(originalItems);
197
- await bundledClient.sendBundled('test', originalItems);
198
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
199
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
200
- const recoveredJson = JSON.stringify(recoveredItems);
201
- expect(recoveredJson).toBe(originalJson);
202
- expect(recoveredItems).toEqual(originalItems);
203
- });
204
- it('verifies actual compression occurred', async () => {
205
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
206
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
207
- compressionLevel: 3,
208
- });
209
- const originalItems = Array.from({ length: 200 }, (_, i) => ({
210
- id: `item-${i}`,
211
- name: 'repetitive-data-for-compression',
212
- value: i,
213
- metadata: {
214
- commonField1: 'this is repeated many times',
215
- commonField2: 'another repeated value',
216
- },
217
- }));
218
- const originalSizeBytes = Buffer.byteLength(JSON.stringify(originalItems), 'utf8');
219
- await bundledClient.sendBundled('test', originalItems);
220
- for (const envelope of capturedEnvelopes) {
221
- expect(envelope.c).toBe(sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD);
222
- expect(typeof envelope.p).toBe('string');
223
- const compressedSizeBytes = Buffer.byteLength(envelope.p, 'utf8');
224
- expect(compressedSizeBytes).toBeLessThan(originalSizeBytes);
225
- }
226
- });
227
- });
228
- describe('4. Mixed message types round-trip', () => {
229
- it('handles mix of NONE and ZSTD compression in same batch', async () => {
230
- const zstdClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
231
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
232
- });
233
- const noneClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
234
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.NONE,
235
- });
236
- const zstdItems = [
237
- makeTestEvent('zstd-1', 'compressed', 100),
238
- makeTestEvent('zstd-2', 'compressed', 200),
239
- ];
240
- const noneItems = [
241
- makeTestEvent('none-1', 'uncompressed', 300),
242
- makeTestEvent('none-2', 'uncompressed', 400),
243
- ];
244
- await zstdClient.sendBundled('test', zstdItems);
245
- const zstdEnvelopes = [...capturedEnvelopes];
246
- capturedEnvelopes = [];
247
- await noneClient.sendBundled('test', noneItems);
248
- const noneEnvelopes = [...capturedEnvelopes];
249
- const allEnvelopes = [...zstdEnvelopes, ...noneEnvelopes];
250
- const sqsRecords = simulateSqsDelivery(allEnvelopes);
251
- const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
252
- expect(recoveredItems).toHaveLength(4);
253
- expect(stats.bundledSqsRecords).toBe(2);
254
- expect(stats.failedRecords).toBe(0);
255
- const zstdRecovered = recoveredItems.filter((item) => item.name === 'compressed');
256
- const noneRecovered = recoveredItems.filter((item) => item.name === 'uncompressed');
257
- expect(zstdRecovered).toHaveLength(2);
258
- expect(noneRecovered).toHaveLength(2);
259
- expect(zstdRecovered).toEqual(zstdItems);
260
- expect(noneRecovered).toEqual(noneItems);
261
- });
262
- it('handles mixed bundled and legacy messages', async () => {
263
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
264
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
265
- });
266
- const bundledItems = [
267
- makeTestEvent('bundled-1', 'bundled', 100),
268
- makeTestEvent('bundled-2', 'bundled', 200),
269
- ];
270
- await bundledClient.sendBundled('test', bundledItems);
271
- const legacyRecord = {
272
- messageId: 'legacy-msg-1',
273
- body: JSON.stringify(makeTestEvent('legacy-1', 'legacy', 999)),
274
- };
275
- const wrappedLegacyRecord = {
276
- messageId: 'legacy-msg-2',
277
- body: JSON.stringify({ messageBody: makeTestEvent('legacy-2', 'wrapped-legacy', 888) }),
278
- };
279
- const bundledRecords = simulateSqsDelivery(capturedEnvelopes);
280
- const allRecords = [...bundledRecords, legacyRecord, wrappedLegacyRecord];
281
- const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(allRecords);
282
- expect(recoveredItems).toHaveLength(4);
283
- expect(stats.bundledSqsRecords).toBe(1);
284
- expect(stats.legacySqsRecords).toBe(2);
285
- expect(stats.failedRecords).toBe(0);
286
- });
287
- });
288
- describe('5. Error injection round-trip', () => {
289
- it('recovers valid bundles while reporting corrupted bundle in failedMessageIds', async () => {
290
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
291
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
292
- });
293
- const validItems1 = [makeTestEvent('valid-1', 'first-batch', 100)];
294
- const validItems2 = [makeTestEvent('valid-2', 'second-batch', 200)];
295
- await bundledClient.sendBundled('test', validItems1);
296
- const envelope1 = { ...capturedEnvelopes[0] };
297
- capturedEnvelopes = [];
298
- await bundledClient.sendBundled('test', validItems2);
299
- const envelope2 = { ...capturedEnvelopes[0] };
300
- const corruptedEnvelope = {
301
- v: 1,
302
- c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
303
- n: 10,
304
- s: 1000,
305
- p: 'dGhpcyBpcyBub3QgdmFsaWQgenN0ZA==',
306
- };
307
- const records = [
308
- { messageId: 'valid-1', body: JSON.stringify({ messageBody: envelope1 }) },
309
- { messageId: 'corrupted', body: JSON.stringify({ messageBody: corruptedEnvelope }) },
310
- { messageId: 'valid-2', body: JSON.stringify({ messageBody: envelope2 }) },
311
- ];
312
- const { items: recoveredItems, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
313
- expect(recoveredItems).toHaveLength(2);
314
- expect(recoveredItems[0]?.id).toBe('valid-1');
315
- expect(recoveredItems[1]?.id).toBe('valid-2');
316
- expect(failedMessageIds).toContain('corrupted');
317
- expect(failedMessageIds).toHaveLength(1);
318
- expect(stats.bundledSqsRecords).toBe(2);
319
- expect(stats.failedRecords).toBe(1);
320
- expect(stats.totalItems).toBe(2);
321
- });
322
- it('handles invalid JSON gracefully', async () => {
323
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
324
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
325
- });
326
- const validItems = [makeTestEvent('valid', 'test', 100)];
327
- await bundledClient.sendBundled('test', validItems);
328
- const records = [
329
- ...simulateSqsDelivery(capturedEnvelopes),
330
- { messageId: 'invalid-json-1', body: 'not-valid-json{{{' },
331
- { messageId: 'invalid-json-2', body: '{"incomplete":' },
332
- { messageId: 'empty', body: '' },
333
- ];
334
- const { items: recoveredItems, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
335
- expect(recoveredItems).toHaveLength(1);
336
- expect(recoveredItems[0]?.id).toBe('valid');
337
- expect(failedMessageIds).toContain('invalid-json-1');
338
- expect(failedMessageIds).toContain('invalid-json-2');
339
- expect(failedMessageIds).toContain('empty');
340
- expect(failedMessageIds).toHaveLength(3);
341
- expect(stats.failedRecords).toBe(3);
342
- });
343
- it('handles decompression bomb protection', async () => {
344
- const largeItems = Array.from({ length: 1000 }, (_, i) => ({
345
- id: `item-${i}`,
346
- data: 'x'.repeat(1000),
347
- }));
348
- const json = JSON.stringify(largeItems);
349
- const compressed = await (0, compression_1.compress)(Buffer.from(json, 'utf8'), sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD, 3);
350
- const base64 = compressed.toString('base64');
351
- const bigEnvelope = {
352
- v: 1,
353
- c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
354
- n: 1000,
355
- s: json.length,
356
- p: base64,
357
- };
358
- const records = [{ messageId: 'too-large', body: JSON.stringify({ messageBody: bigEnvelope }) }];
359
- const { failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records, {
360
- maxDecompressedSizeBytes: 100 * 1024,
361
- });
362
- expect(failedMessageIds).toContain('too-large');
363
- expect(stats.failedRecords).toBe(1);
364
- });
365
- });
366
- describe('6. Realistic event types round-trip', () => {
367
- it('TrackingEvent-like structures survive round-trip exactly', async () => {
368
- const realisticMockSqs = {
369
- buildAndSendMessagesV2: jest.fn(async (_type, envelopes) => {
370
- capturedEnvelopes = [];
371
- capturedEnvelopes.push(...envelopes);
372
- return {
373
- successCount: envelopes.length,
374
- failedCount: 0,
375
- batchCount: 1,
376
- failedMessages: [],
377
- };
378
- }),
379
- queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/test-queue',
380
- limits: (0, sqs_1.createSqsLimits)(sqs_1.SQS_1MB),
381
- };
382
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(realisticMockSqs, {
383
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
384
- compressionLevel: 3,
385
- });
386
- const originalEvents = Array.from({ length: 100 }, (_, i) => makeRealisticTrackingEvent(i));
387
- await bundledClient.sendBundled('tracking-events', originalEvents);
388
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
389
- const { items: recoveredEvents, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
390
- expect(recoveredEvents).toHaveLength(100);
391
- expect(stats.failedRecords).toBe(0);
392
- expect(recoveredEvents).toEqual(originalEvents);
393
- for (let i = 0; i < originalEvents.length; i++) {
394
- const original = originalEvents[i];
395
- const recovered = recoveredEvents[i];
396
- expect(recovered?.anonymousId).toBe(original?.anonymousId);
397
- expect(recovered?.context.page.url).toBe(original?.context.page.url);
398
- expect(recovered?.properties.price).toBe(original?.properties.price);
399
- if (original?.shopifyData) {
400
- expect(recovered?.shopifyData).toEqual(original.shopifyData);
401
- }
402
- }
403
- });
404
- it('preserves nested object structures exactly', async () => {
405
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
406
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
407
- });
408
- const deeplyNestedItems = [
409
- {
410
- id: 'nested-1',
411
- name: 'deep-nesting',
412
- nested: {
413
- level1: {
414
- level2: {
415
- deep: 'very deep value',
416
- },
417
- },
418
- },
419
- },
420
- {
421
- id: 'nested-2',
422
- name: 'with-arrays',
423
- tags: ['tag1', 'tag2', 'tag3'],
424
- metadata: {
425
- array: [1, 2, 3],
426
- object: { a: 1, b: 2 },
427
- mixed: [{ key: 'value' }, [1, 2, 3]],
428
- },
429
- },
430
- ];
431
- await bundledClient.sendBundled('test', deeplyNestedItems);
432
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
433
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
434
- expect(recoveredItems).toEqual(deeplyNestedItems);
435
- expect(recoveredItems[0]?.nested?.level1.level2.deep).toBe('very deep value');
436
- expect(recoveredItems[1]?.tags).toEqual(['tag1', 'tag2', 'tag3']);
437
- });
438
- });
439
- describe('7. High compression ratio round-trip', () => {
440
- it('highly repetitive data compresses and decompresses correctly', async () => {
441
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
442
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
443
- compressionLevel: 3,
444
- });
445
- const repetitiveString = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
446
- const originalItems = Array.from({ length: 200 }, (_, i) => ({
447
- id: `repetitive-${i}`,
448
- name: repetitiveString,
449
- value: 42,
450
- metadata: {
451
- field1: repetitiveString,
452
- field2: repetitiveString,
453
- field3: repetitiveString,
454
- field4: repetitiveString,
455
- field5: repetitiveString,
456
- },
457
- }));
458
- const originalSizeBytes = Buffer.byteLength(JSON.stringify(originalItems), 'utf8');
459
- await bundledClient.sendBundled('test', originalItems);
460
- let totalCompressedSize = 0;
461
- for (const envelope of capturedEnvelopes) {
462
- expect(typeof envelope.p).toBe('string');
463
- totalCompressedSize += Buffer.byteLength(envelope.p, 'utf8');
464
- }
465
- const compressionRatio = originalSizeBytes / totalCompressedSize;
466
- expect(compressionRatio).toBeGreaterThan(5);
467
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
468
- const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
469
- expect(recoveredItems).toHaveLength(200);
470
- expect(recoveredItems).toEqual(originalItems);
471
- expect(stats.failedRecords).toBe(0);
472
- for (const item of recoveredItems) {
473
- expect(item.name).toBe(repetitiveString);
474
- expect(item.value).toBe(42);
475
- expect(item.metadata?.field1).toBe(repetitiveString);
476
- }
477
- });
478
- it('varying compression levels all round-trip correctly', async () => {
479
- const items = Array.from({ length: 50 }, (_, i) => makeTestEvent(`level-test-${i}`, 'compression-level', i));
480
- for (const level of [1, 3, 9, 15]) {
481
- capturedEnvelopes = [];
482
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
483
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
484
- compressionLevel: level,
485
- });
486
- await bundledClient.sendBundled('test', items);
487
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
488
- const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
489
- expect(recoveredItems).toEqual(items);
490
- expect(stats.failedRecords).toBe(0);
491
- }
492
- });
493
- });
494
- describe('8. Edge cases', () => {
495
- it('empty arrays survive round-trip', async () => {
496
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
497
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
498
- });
499
- const result = await bundledClient.sendBundled('test', []);
500
- expect(result.totalItems).toBe(0);
501
- expect(capturedEnvelopes).toHaveLength(0);
502
- });
503
- it('single item survives round-trip', async () => {
504
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
505
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
506
- });
507
- const singleItem = [makeTestEvent('single', 'lone-wolf', 999)];
508
- await bundledClient.sendBundled('test', singleItem);
509
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
510
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
511
- expect(recoveredItems).toHaveLength(1);
512
- expect(recoveredItems).toEqual(singleItem);
513
- });
514
- it('special characters survive round-trip', async () => {
515
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
516
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
517
- });
518
- const specialCharsItems = [
519
- {
520
- id: 'unicode-日本語',
521
- name: '中文测试',
522
- metadata: {
523
- emoji: '🎉🚀✨💯',
524
- rtl: 'مرحبا بالعالم',
525
- escape: '\\n\\t\\r',
526
- quotes: '"double" \'single\' `backtick`',
527
- angle: '<script>alert("xss")</script>',
528
- null_char: 'before\x00after',
529
- },
530
- },
531
- ];
532
- await bundledClient.sendBundled('test', specialCharsItems);
533
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
534
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
535
- expect(recoveredItems).toEqual(specialCharsItems);
536
- });
537
- it('null and undefined values are handled correctly', async () => {
538
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
539
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
540
- });
541
- const itemsWithNulls = [
542
- { id: 'null-test', name: 'test', value: undefined },
543
- {
544
- id: 'explicit-null',
545
- name: 'test',
546
- metadata: { key: null },
547
- },
548
- ];
549
- await bundledClient.sendBundled('test', itemsWithNulls);
550
- const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
551
- const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
552
- expect(recoveredItems[0]?.value).toBeUndefined();
553
- expect(recoveredItems[1]?.metadata?.key).toBeNull();
554
- });
555
- it('recordMap correctly tracks items back to SQS messages', async () => {
556
- const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
557
- compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
558
- maxItemsPerBundle: 3,
559
- });
560
- const items = Array.from({ length: 10 }, (_, i) => makeTestEvent(`item-${i}`, 'tracking', i));
561
- await bundledClient.sendBundled('test', items);
562
- const sqsRecords = capturedEnvelopes.map((env, i) => ({
563
- messageId: `bundle-${i}`,
564
- body: JSON.stringify({ messageBody: env }),
565
- }));
566
- const { items: recoveredItems, recordMap, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
567
- expect(recoveredItems).toHaveLength(10);
568
- const messageIdCounts = new Map();
569
- for (const item of recoveredItems) {
570
- const messageId = recordMap.get(item);
571
- expect(messageId).toBeDefined();
572
- if (messageId) {
573
- messageIdCounts.set(messageId, (messageIdCounts.get(messageId) ?? 0) + 1);
574
- }
575
- }
576
- expect(messageIdCounts.size).toBe(capturedEnvelopes.length);
577
- for (const [messageId, count] of messageIdCounts) {
578
- expect(count).toBeLessThanOrEqual(3);
579
- expect(messageId).toMatch(/^bundle-\d+$/);
580
- }
581
- expect(stats.bundledSqsRecords).toBe(capturedEnvelopes.length);
582
- });
583
- });
584
- });
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const sqs_bundled_client_1 = require("../../clients/generic/sqs-bundled-client");
4
+ const sqs_bundled_client_types_1 = require("../../clients/generic/sqs-bundled-client.types");
5
+ const sqs_unbundle_1 = require("../../clients/generic/sqs-unbundle");
6
+ const compression_1 = require("../../utils/compression");
7
+ const sqs_1 = require("../../constants/sqs");
8
+ jest.mock('../../helpers/logging-helper', () => ({
9
+ Logger: {
10
+ debug: jest.fn(),
11
+ info: jest.fn(),
12
+ warn: jest.fn(),
13
+ error: jest.fn(),
14
+ },
15
+ }));
16
+ function makeTestEvent(id, name = 'test', value, metadata) {
17
+ return { id, name, value, metadata };
18
+ }
19
+ function makeRealisticTrackingEvent(index) {
20
+ return {
21
+ anonymousId: `anon-${index}-${Math.random().toString(36).substring(7)}`,
22
+ accountId: `acc-${index % 10}`,
23
+ pixelId: `pixel-${index % 5}`,
24
+ eventType: ['track', 'identify', 'page'][index % 3] ?? 'track',
25
+ eventName: ['purchase', 'add_to_cart', 'page_view', 'begin_checkout'][index % 4] ?? 'track',
26
+ timestamp: new Date(Date.now() - index * 1000).toISOString(),
27
+ context: {
28
+ page: {
29
+ url: `https://example.com/product/${index}`,
30
+ path: `/product/${index}`,
31
+ title: `Product ${index} - Example Store`,
32
+ referrer: index % 3 === 0 ? 'https://google.com' : '',
33
+ },
34
+ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
35
+ ip: `192.168.${index % 256}.${(index * 7) % 256}`,
36
+ locale: ['en-US', 'en-GB', 'de-DE', 'fr-FR'][index % 4] ?? 'en-US',
37
+ timezone: 'America/New_York',
38
+ },
39
+ properties: {
40
+ productId: `prod-${index}`,
41
+ productName: `Amazing Product ${index}`,
42
+ price: 29.99 + (index % 100),
43
+ currency: 'USD',
44
+ quantity: (index % 5) + 1,
45
+ category: ['Electronics', 'Clothing', 'Home', 'Sports'][index % 4],
46
+ customFields: {
47
+ brand: `Brand${index % 20}`,
48
+ sku: `SKU-${index}-${Date.now()}`,
49
+ inStock: index % 2 === 0,
50
+ },
51
+ },
52
+ shopifyData: index % 3 === 0
53
+ ? {
54
+ checkoutToken: `checkout-${index}`,
55
+ orderId: index % 5 === 0 ? `order-${index}` : undefined,
56
+ customerEmail: `customer${index}@example.com`,
57
+ lineItems: Array.from({ length: (index % 3) + 1 }, (_, j) => ({
58
+ variantId: `variant-${index}-${j}`,
59
+ title: `Line Item ${j}`,
60
+ price: 19.99 + j * 10,
61
+ quantity: j + 1,
62
+ })),
63
+ }
64
+ : undefined,
65
+ };
66
+ }
67
+ function simulateSqsDelivery(envelopes) {
68
+ return envelopes.map((env, i) => ({
69
+ messageId: `msg-${i}-${Date.now()}`,
70
+ body: JSON.stringify({ messageBody: env }),
71
+ }));
72
+ }
73
+ describe('Full Round-Trip: Producer → Consumer', () => {
74
+ let mockSqsClient;
75
+ let capturedEnvelopes;
76
+ beforeEach(() => {
77
+ capturedEnvelopes = [];
78
+ mockSqsClient = {
79
+ buildAndSendMessagesV2: jest.fn(async (_type, envelopes) => {
80
+ capturedEnvelopes.push(...envelopes);
81
+ return {
82
+ successCount: envelopes.length,
83
+ failedCount: 0,
84
+ batchCount: 1,
85
+ failedMessages: [],
86
+ };
87
+ }),
88
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/test-queue',
89
+ limits: (0, sqs_1.createSqsLimits)(sqs_1.SQS_1MB),
90
+ };
91
+ });
92
+ describe('1. Basic round-trip test (100 items)', () => {
93
+ it('100 items survive complete round-trip with deep equality', async () => {
94
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
95
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
96
+ compressionLevel: 3,
97
+ });
98
+ const originalItems = Array.from({ length: 100 }, (_, i) => ({
99
+ id: `event-${i}`,
100
+ name: 'purchase',
101
+ value: i * 99.99,
102
+ metadata: { source: 'test', index: i },
103
+ }));
104
+ await bundledClient.sendBundled('test', originalItems);
105
+ expect(capturedEnvelopes.length).toBeGreaterThanOrEqual(1);
106
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
107
+ const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
108
+ expect(recoveredItems).toHaveLength(100);
109
+ expect(recoveredItems).toEqual(originalItems);
110
+ expect(stats.bundledSqsRecords).toBe(capturedEnvelopes.length);
111
+ expect(stats.failedRecords).toBe(0);
112
+ });
113
+ it('preserves all primitive types correctly', async () => {
114
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
115
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
116
+ });
117
+ const originalItems = [
118
+ { id: 'str', name: 'string-test', value: undefined },
119
+ { id: 'num', name: 'number-test', value: 123.456 },
120
+ { id: 'zero', name: 'zero-test', value: 0 },
121
+ { id: 'neg', name: 'negative-test', value: -999.99 },
122
+ { id: 'big', name: 'big-number', value: Number.MAX_SAFE_INTEGER },
123
+ ];
124
+ await bundledClient.sendBundled('test', originalItems);
125
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
126
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
127
+ expect(recoveredItems).toEqual(originalItems);
128
+ });
129
+ });
130
+ describe('2. Large scale round-trip (1000 items)', () => {
131
+ it('1000 items survive round-trip with no data loss', async () => {
132
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
133
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
134
+ compressionLevel: 3,
135
+ });
136
+ const originalItems = Array.from({ length: 1000 }, (_, i) => ({
137
+ id: `event-${i.toString().padStart(4, '0')}`,
138
+ name: `type-${i % 10}`,
139
+ value: i * 1.5,
140
+ metadata: {
141
+ batch: Math.floor(i / 100),
142
+ position: i % 100,
143
+ timestamp: Date.now() + i,
144
+ },
145
+ }));
146
+ await bundledClient.sendBundled('test', originalItems);
147
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
148
+ const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
149
+ expect(recoveredItems).toHaveLength(1000);
150
+ expect(stats.totalItems).toBe(1000);
151
+ expect(stats.failedRecords).toBe(0);
152
+ const recoveredIds = recoveredItems.map((item) => item.id);
153
+ const originalIds = originalItems.map((item) => item.id);
154
+ expect(new Set(recoveredIds)).toEqual(new Set(originalIds));
155
+ expect(recoveredItems).toEqual(originalItems);
156
+ });
157
+ it('preserves order within each bundle', async () => {
158
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
159
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
160
+ maxItemsPerBundle: 100,
161
+ });
162
+ const originalItems = Array.from({ length: 500 }, (_, i) => makeTestEvent(`seq-${i}`, 'ordered', i));
163
+ await bundledClient.sendBundled('test', originalItems);
164
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
165
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
166
+ let currentBundleStart = 0;
167
+ for (const envelope of capturedEnvelopes) {
168
+ const bundleSize = envelope.n;
169
+ const bundleItems = recoveredItems.slice(currentBundleStart, currentBundleStart + bundleSize);
170
+ for (let j = 1; j < bundleItems.length; j++) {
171
+ const prevValue = bundleItems[j - 1]?.value ?? 0;
172
+ const currValue = bundleItems[j]?.value ?? 0;
173
+ expect(currValue).toBeGreaterThan(prevValue);
174
+ }
175
+ currentBundleStart += bundleSize;
176
+ }
177
+ });
178
+ });
179
+ describe('3. Compression round-trip verification', () => {
180
+ it('ZSTD compressed data decompresses to byte-exact JSON', async () => {
181
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
182
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
183
+ compressionLevel: 5,
184
+ });
185
+ const originalItems = Array.from({ length: 50 }, (_, i) => ({
186
+ id: `compress-test-${i}`,
187
+ name: 'compression-verification',
188
+ value: i * 123.456789,
189
+ metadata: {
190
+ unicode: '日本語テスト',
191
+ emoji: '🚀✨🎉',
192
+ special: 'line\nbreak\ttab\r\nwindows',
193
+ quotes: '"double" and \'single\'',
194
+ },
195
+ }));
196
+ const originalJson = JSON.stringify(originalItems);
197
+ await bundledClient.sendBundled('test', originalItems);
198
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
199
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
200
+ const recoveredJson = JSON.stringify(recoveredItems);
201
+ expect(recoveredJson).toBe(originalJson);
202
+ expect(recoveredItems).toEqual(originalItems);
203
+ });
204
+ it('verifies actual compression occurred', async () => {
205
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
206
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
207
+ compressionLevel: 3,
208
+ });
209
+ const originalItems = Array.from({ length: 200 }, (_, i) => ({
210
+ id: `item-${i}`,
211
+ name: 'repetitive-data-for-compression',
212
+ value: i,
213
+ metadata: {
214
+ commonField1: 'this is repeated many times',
215
+ commonField2: 'another repeated value',
216
+ },
217
+ }));
218
+ const originalSizeBytes = Buffer.byteLength(JSON.stringify(originalItems), 'utf8');
219
+ await bundledClient.sendBundled('test', originalItems);
220
+ for (const envelope of capturedEnvelopes) {
221
+ expect(envelope.c).toBe(sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD);
222
+ expect(typeof envelope.p).toBe('string');
223
+ const compressedSizeBytes = Buffer.byteLength(envelope.p, 'utf8');
224
+ expect(compressedSizeBytes).toBeLessThan(originalSizeBytes);
225
+ }
226
+ });
227
+ });
228
+ describe('4. Mixed message types round-trip', () => {
229
+ it('handles mix of NONE and ZSTD compression in same batch', async () => {
230
+ const zstdClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
231
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
232
+ });
233
+ const noneClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
234
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.NONE,
235
+ });
236
+ const zstdItems = [
237
+ makeTestEvent('zstd-1', 'compressed', 100),
238
+ makeTestEvent('zstd-2', 'compressed', 200),
239
+ ];
240
+ const noneItems = [
241
+ makeTestEvent('none-1', 'uncompressed', 300),
242
+ makeTestEvent('none-2', 'uncompressed', 400),
243
+ ];
244
+ await zstdClient.sendBundled('test', zstdItems);
245
+ const zstdEnvelopes = [...capturedEnvelopes];
246
+ capturedEnvelopes = [];
247
+ await noneClient.sendBundled('test', noneItems);
248
+ const noneEnvelopes = [...capturedEnvelopes];
249
+ const allEnvelopes = [...zstdEnvelopes, ...noneEnvelopes];
250
+ const sqsRecords = simulateSqsDelivery(allEnvelopes);
251
+ const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
252
+ expect(recoveredItems).toHaveLength(4);
253
+ expect(stats.bundledSqsRecords).toBe(2);
254
+ expect(stats.failedRecords).toBe(0);
255
+ const zstdRecovered = recoveredItems.filter((item) => item.name === 'compressed');
256
+ const noneRecovered = recoveredItems.filter((item) => item.name === 'uncompressed');
257
+ expect(zstdRecovered).toHaveLength(2);
258
+ expect(noneRecovered).toHaveLength(2);
259
+ expect(zstdRecovered).toEqual(zstdItems);
260
+ expect(noneRecovered).toEqual(noneItems);
261
+ });
262
+ it('handles mixed bundled and legacy messages', async () => {
263
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
264
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
265
+ });
266
+ const bundledItems = [
267
+ makeTestEvent('bundled-1', 'bundled', 100),
268
+ makeTestEvent('bundled-2', 'bundled', 200),
269
+ ];
270
+ await bundledClient.sendBundled('test', bundledItems);
271
+ const legacyRecord = {
272
+ messageId: 'legacy-msg-1',
273
+ body: JSON.stringify(makeTestEvent('legacy-1', 'legacy', 999)),
274
+ };
275
+ const wrappedLegacyRecord = {
276
+ messageId: 'legacy-msg-2',
277
+ body: JSON.stringify({ messageBody: makeTestEvent('legacy-2', 'wrapped-legacy', 888) }),
278
+ };
279
+ const bundledRecords = simulateSqsDelivery(capturedEnvelopes);
280
+ const allRecords = [...bundledRecords, legacyRecord, wrappedLegacyRecord];
281
+ const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(allRecords);
282
+ expect(recoveredItems).toHaveLength(4);
283
+ expect(stats.bundledSqsRecords).toBe(1);
284
+ expect(stats.legacySqsRecords).toBe(2);
285
+ expect(stats.failedRecords).toBe(0);
286
+ });
287
+ });
288
+ describe('5. Error injection round-trip', () => {
289
+ it('recovers valid bundles while reporting corrupted bundle in failedMessageIds', async () => {
290
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
291
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
292
+ });
293
+ const validItems1 = [makeTestEvent('valid-1', 'first-batch', 100)];
294
+ const validItems2 = [makeTestEvent('valid-2', 'second-batch', 200)];
295
+ await bundledClient.sendBundled('test', validItems1);
296
+ const envelope1 = { ...capturedEnvelopes[0] };
297
+ capturedEnvelopes = [];
298
+ await bundledClient.sendBundled('test', validItems2);
299
+ const envelope2 = { ...capturedEnvelopes[0] };
300
+ const corruptedEnvelope = {
301
+ v: 1,
302
+ c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
303
+ n: 10,
304
+ s: 1000,
305
+ p: 'dGhpcyBpcyBub3QgdmFsaWQgenN0ZA==',
306
+ };
307
+ const records = [
308
+ { messageId: 'valid-1', body: JSON.stringify({ messageBody: envelope1 }) },
309
+ { messageId: 'corrupted', body: JSON.stringify({ messageBody: corruptedEnvelope }) },
310
+ { messageId: 'valid-2', body: JSON.stringify({ messageBody: envelope2 }) },
311
+ ];
312
+ const { items: recoveredItems, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
313
+ expect(recoveredItems).toHaveLength(2);
314
+ expect(recoveredItems[0]?.id).toBe('valid-1');
315
+ expect(recoveredItems[1]?.id).toBe('valid-2');
316
+ expect(failedMessageIds).toContain('corrupted');
317
+ expect(failedMessageIds).toHaveLength(1);
318
+ expect(stats.bundledSqsRecords).toBe(2);
319
+ expect(stats.failedRecords).toBe(1);
320
+ expect(stats.totalItems).toBe(2);
321
+ });
322
+ it('handles invalid JSON gracefully', async () => {
323
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
324
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
325
+ });
326
+ const validItems = [makeTestEvent('valid', 'test', 100)];
327
+ await bundledClient.sendBundled('test', validItems);
328
+ const records = [
329
+ ...simulateSqsDelivery(capturedEnvelopes),
330
+ { messageId: 'invalid-json-1', body: 'not-valid-json{{{' },
331
+ { messageId: 'invalid-json-2', body: '{"incomplete":' },
332
+ { messageId: 'empty', body: '' },
333
+ ];
334
+ const { items: recoveredItems, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
335
+ expect(recoveredItems).toHaveLength(1);
336
+ expect(recoveredItems[0]?.id).toBe('valid');
337
+ expect(failedMessageIds).toContain('invalid-json-1');
338
+ expect(failedMessageIds).toContain('invalid-json-2');
339
+ expect(failedMessageIds).toContain('empty');
340
+ expect(failedMessageIds).toHaveLength(3);
341
+ expect(stats.failedRecords).toBe(3);
342
+ });
343
+ it('handles decompression bomb protection', async () => {
344
+ const largeItems = Array.from({ length: 1000 }, (_, i) => ({
345
+ id: `item-${i}`,
346
+ data: 'x'.repeat(1000),
347
+ }));
348
+ const json = JSON.stringify(largeItems);
349
+ const compressed = await (0, compression_1.compress)(Buffer.from(json, 'utf8'), sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD, 3);
350
+ const base64 = compressed.toString('base64');
351
+ const bigEnvelope = {
352
+ v: 1,
353
+ c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
354
+ n: 1000,
355
+ s: json.length,
356
+ p: base64,
357
+ };
358
+ const records = [{ messageId: 'too-large', body: JSON.stringify({ messageBody: bigEnvelope }) }];
359
+ const { failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records, {
360
+ maxDecompressedSizeBytes: 100 * 1024,
361
+ });
362
+ expect(failedMessageIds).toContain('too-large');
363
+ expect(stats.failedRecords).toBe(1);
364
+ });
365
+ });
366
+ describe('6. Realistic event types round-trip', () => {
367
+ it('TrackingEvent-like structures survive round-trip exactly', async () => {
368
+ const realisticMockSqs = {
369
+ buildAndSendMessagesV2: jest.fn(async (_type, envelopes) => {
370
+ capturedEnvelopes = [];
371
+ capturedEnvelopes.push(...envelopes);
372
+ return {
373
+ successCount: envelopes.length,
374
+ failedCount: 0,
375
+ batchCount: 1,
376
+ failedMessages: [],
377
+ };
378
+ }),
379
+ queueUrl: 'https://sqs.us-east-1.amazonaws.com/123456789/test-queue',
380
+ limits: (0, sqs_1.createSqsLimits)(sqs_1.SQS_1MB),
381
+ };
382
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(realisticMockSqs, {
383
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
384
+ compressionLevel: 3,
385
+ });
386
+ const originalEvents = Array.from({ length: 100 }, (_, i) => makeRealisticTrackingEvent(i));
387
+ await bundledClient.sendBundled('tracking-events', originalEvents);
388
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
389
+ const { items: recoveredEvents, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
390
+ expect(recoveredEvents).toHaveLength(100);
391
+ expect(stats.failedRecords).toBe(0);
392
+ expect(recoveredEvents).toEqual(originalEvents);
393
+ for (let i = 0; i < originalEvents.length; i++) {
394
+ const original = originalEvents[i];
395
+ const recovered = recoveredEvents[i];
396
+ expect(recovered?.anonymousId).toBe(original?.anonymousId);
397
+ expect(recovered?.context.page.url).toBe(original?.context.page.url);
398
+ expect(recovered?.properties.price).toBe(original?.properties.price);
399
+ if (original?.shopifyData) {
400
+ expect(recovered?.shopifyData).toEqual(original.shopifyData);
401
+ }
402
+ }
403
+ });
404
+ it('preserves nested object structures exactly', async () => {
405
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
406
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
407
+ });
408
+ const deeplyNestedItems = [
409
+ {
410
+ id: 'nested-1',
411
+ name: 'deep-nesting',
412
+ nested: {
413
+ level1: {
414
+ level2: {
415
+ deep: 'very deep value',
416
+ },
417
+ },
418
+ },
419
+ },
420
+ {
421
+ id: 'nested-2',
422
+ name: 'with-arrays',
423
+ tags: ['tag1', 'tag2', 'tag3'],
424
+ metadata: {
425
+ array: [1, 2, 3],
426
+ object: { a: 1, b: 2 },
427
+ mixed: [{ key: 'value' }, [1, 2, 3]],
428
+ },
429
+ },
430
+ ];
431
+ await bundledClient.sendBundled('test', deeplyNestedItems);
432
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
433
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
434
+ expect(recoveredItems).toEqual(deeplyNestedItems);
435
+ expect(recoveredItems[0]?.nested?.level1.level2.deep).toBe('very deep value');
436
+ expect(recoveredItems[1]?.tags).toEqual(['tag1', 'tag2', 'tag3']);
437
+ });
438
+ });
439
+ describe('7. High compression ratio round-trip', () => {
440
+ it('highly repetitive data compresses and decompresses correctly', async () => {
441
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
442
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
443
+ compressionLevel: 3,
444
+ });
445
+ const repetitiveString = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA';
446
+ const originalItems = Array.from({ length: 200 }, (_, i) => ({
447
+ id: `repetitive-${i}`,
448
+ name: repetitiveString,
449
+ value: 42,
450
+ metadata: {
451
+ field1: repetitiveString,
452
+ field2: repetitiveString,
453
+ field3: repetitiveString,
454
+ field4: repetitiveString,
455
+ field5: repetitiveString,
456
+ },
457
+ }));
458
+ const originalSizeBytes = Buffer.byteLength(JSON.stringify(originalItems), 'utf8');
459
+ await bundledClient.sendBundled('test', originalItems);
460
+ let totalCompressedSize = 0;
461
+ for (const envelope of capturedEnvelopes) {
462
+ expect(typeof envelope.p).toBe('string');
463
+ totalCompressedSize += Buffer.byteLength(envelope.p, 'utf8');
464
+ }
465
+ const compressionRatio = originalSizeBytes / totalCompressedSize;
466
+ expect(compressionRatio).toBeGreaterThan(5);
467
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
468
+ const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
469
+ expect(recoveredItems).toHaveLength(200);
470
+ expect(recoveredItems).toEqual(originalItems);
471
+ expect(stats.failedRecords).toBe(0);
472
+ for (const item of recoveredItems) {
473
+ expect(item.name).toBe(repetitiveString);
474
+ expect(item.value).toBe(42);
475
+ expect(item.metadata?.field1).toBe(repetitiveString);
476
+ }
477
+ });
478
+ it('varying compression levels all round-trip correctly', async () => {
479
+ const items = Array.from({ length: 50 }, (_, i) => makeTestEvent(`level-test-${i}`, 'compression-level', i));
480
+ for (const level of [1, 3, 9, 15]) {
481
+ capturedEnvelopes = [];
482
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
483
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
484
+ compressionLevel: level,
485
+ });
486
+ await bundledClient.sendBundled('test', items);
487
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
488
+ const { items: recoveredItems, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
489
+ expect(recoveredItems).toEqual(items);
490
+ expect(stats.failedRecords).toBe(0);
491
+ }
492
+ });
493
+ });
494
+ describe('8. Edge cases', () => {
495
+ it('empty arrays survive round-trip', async () => {
496
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
497
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
498
+ });
499
+ const result = await bundledClient.sendBundled('test', []);
500
+ expect(result.totalItems).toBe(0);
501
+ expect(capturedEnvelopes).toHaveLength(0);
502
+ });
503
+ it('single item survives round-trip', async () => {
504
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
505
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
506
+ });
507
+ const singleItem = [makeTestEvent('single', 'lone-wolf', 999)];
508
+ await bundledClient.sendBundled('test', singleItem);
509
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
510
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
511
+ expect(recoveredItems).toHaveLength(1);
512
+ expect(recoveredItems).toEqual(singleItem);
513
+ });
514
+ it('special characters survive round-trip', async () => {
515
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
516
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
517
+ });
518
+ const specialCharsItems = [
519
+ {
520
+ id: 'unicode-日本語',
521
+ name: '中文测试',
522
+ metadata: {
523
+ emoji: '🎉🚀✨💯',
524
+ rtl: 'مرحبا بالعالم',
525
+ escape: '\\n\\t\\r',
526
+ quotes: '"double" \'single\' `backtick`',
527
+ angle: '<script>alert("xss")</script>',
528
+ null_char: 'before\x00after',
529
+ },
530
+ },
531
+ ];
532
+ await bundledClient.sendBundled('test', specialCharsItems);
533
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
534
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
535
+ expect(recoveredItems).toEqual(specialCharsItems);
536
+ });
537
+ it('null and undefined values are handled correctly', async () => {
538
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
539
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
540
+ });
541
+ const itemsWithNulls = [
542
+ { id: 'null-test', name: 'test', value: undefined },
543
+ {
544
+ id: 'explicit-null',
545
+ name: 'test',
546
+ metadata: { key: null },
547
+ },
548
+ ];
549
+ await bundledClient.sendBundled('test', itemsWithNulls);
550
+ const sqsRecords = simulateSqsDelivery(capturedEnvelopes);
551
+ const { items: recoveredItems } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
552
+ expect(recoveredItems[0]?.value).toBeUndefined();
553
+ expect(recoveredItems[1]?.metadata?.key).toBeNull();
554
+ });
555
+ it('recordMap correctly tracks items back to SQS messages', async () => {
556
+ const bundledClient = new sqs_bundled_client_1.BundledSQSClient(mockSqsClient, {
557
+ compression: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
558
+ maxItemsPerBundle: 3,
559
+ });
560
+ const items = Array.from({ length: 10 }, (_, i) => makeTestEvent(`item-${i}`, 'tracking', i));
561
+ await bundledClient.sendBundled('test', items);
562
+ const sqsRecords = capturedEnvelopes.map((env, i) => ({
563
+ messageId: `bundle-${i}`,
564
+ body: JSON.stringify({ messageBody: env }),
565
+ }));
566
+ const { items: recoveredItems, recordMap, stats } = await (0, sqs_unbundle_1.unbundleRecords)(sqsRecords);
567
+ expect(recoveredItems).toHaveLength(10);
568
+ const messageIdCounts = new Map();
569
+ for (const item of recoveredItems) {
570
+ const messageId = recordMap.get(item);
571
+ expect(messageId).toBeDefined();
572
+ if (messageId) {
573
+ messageIdCounts.set(messageId, (messageIdCounts.get(messageId) ?? 0) + 1);
574
+ }
575
+ }
576
+ expect(messageIdCounts.size).toBe(capturedEnvelopes.length);
577
+ for (const [messageId, count] of messageIdCounts) {
578
+ expect(count).toBeLessThanOrEqual(3);
579
+ expect(messageId).toMatch(/^bundle-\d+$/);
580
+ }
581
+ expect(stats.bundledSqsRecords).toBe(capturedEnvelopes.length);
582
+ });
583
+ });
584
+ });
585
585
  //# sourceMappingURL=sqs-bundling-roundtrip.spec.js.map