@adtrackify/at-service-common 5.1.2 → 5.1.3
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.
- package/dist/cjs/__tests__/clients/acuity-client.spec.js +20 -21
- package/dist/cjs/__tests__/clients/acuity-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/cross-platform-compression.spec.js +86 -97
- package/dist/cjs/__tests__/clients/cross-platform-compression.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/dynamodb-client.spec.js +95 -94
- package/dist/cjs/__tests__/clients/dynamodb-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/event-collector-client.spec.js +58 -58
- package/dist/cjs/__tests__/clients/event-collector-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/liveintent-client.spec.js +37 -0
- package/dist/cjs/__tests__/clients/liveintent-client.spec.js.map +1 -0
- package/dist/cjs/__tests__/clients/open-exchange-rates-client.spec.js +17 -18
- package/dist/cjs/__tests__/clients/open-exchange-rates-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/sqs-bundled-client.spec.js +255 -273
- package/dist/cjs/__tests__/clients/sqs-bundled-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/sqs-bundling-contracts.spec.js +125 -137
- package/dist/cjs/__tests__/clients/sqs-bundling-contracts.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/sqs-client.spec.js +77 -78
- package/dist/cjs/__tests__/clients/sqs-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/clients/sqs-unbundle.spec.js +430 -431
- package/dist/cjs/__tests__/clients/sqs-unbundle.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/contact-enrichments-db-service.spec.js +29 -30
- package/dist/cjs/__tests__/db/contact-enrichments-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/destinations-db-service.spec.js +47 -45
- package/dist/cjs/__tests__/db/destinations-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/products-db-service.spec.js +40 -41
- package/dist/cjs/__tests__/db/products-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/shared-read-db-services.spec.js +26 -27
- package/dist/cjs/__tests__/db/shared-read-db-services.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/shopify-app-installs-db-service.spec.js +37 -38
- package/dist/cjs/__tests__/db/shopify-app-installs-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/subscriptions-db-service.spec.js +35 -36
- package/dist/cjs/__tests__/db/subscriptions-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/db/user-accounts-db-service.spec.js +27 -28
- package/dist/cjs/__tests__/db/user-accounts-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/helpers/account-users-helper.spec.js +64 -65
- package/dist/cjs/__tests__/helpers/account-users-helper.spec.js.map +1 -1
- package/dist/cjs/__tests__/helpers/acuity-helper.spec.js +18 -19
- package/dist/cjs/__tests__/helpers/acuity-helper.spec.js.map +1 -1
- package/dist/cjs/__tests__/helpers/api-key-auth-helper.spec.js +23 -24
- package/dist/cjs/__tests__/helpers/api-key-auth-helper.spec.js.map +1 -1
- package/dist/cjs/__tests__/helpers/cognito-auth-helper.spec.js +16 -17
- package/dist/cjs/__tests__/helpers/cognito-auth-helper.spec.js.map +1 -1
- package/dist/cjs/__tests__/helpers/order-calculation-helper.spec.js +42 -43
- package/dist/cjs/__tests__/helpers/order-calculation-helper.spec.js.map +1 -1
- package/dist/cjs/__tests__/helpers/public-api-response-helper.spec.js +23 -24
- package/dist/cjs/__tests__/helpers/public-api-response-helper.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/helpers.spec.js +114 -115
- package/dist/cjs/__tests__/identity-cache/helpers.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-cache-alias-write.spec.js +29 -30
- package/dist/cjs/__tests__/identity-cache/identity-cache-alias-write.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-cache-db-service.spec.js +19 -20
- package/dist/cjs/__tests__/identity-cache/identity-cache-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js +200 -223
- package/dist/cjs/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js +114 -123
- package/dist/cjs/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-client.spec.js +107 -110
- package/dist/cjs/__tests__/identity-cache/identity-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-cache-hit.spec.js +31 -32
- package/dist/cjs/__tests__/identity-cache/identity-gateway-cache-hit.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-cache-miss.spec.js +47 -60
- package/dist/cjs/__tests__/identity-cache/identity-gateway-cache-miss.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-constructor.spec.js +15 -16
- package/dist/cjs/__tests__/identity-cache/identity-gateway-constructor.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-edge-cases.spec.js +28 -35
- package/dist/cjs/__tests__/identity-cache/identity-gateway-edge-cases.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-enqueue-async.spec.js +27 -28
- package/dist/cjs/__tests__/identity-cache/identity-gateway-enqueue-async.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-stale-cache.spec.js +52 -74
- package/dist/cjs/__tests__/identity-cache/identity-gateway-stale-cache.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/identity-gateway-test-setup.d.ts +18 -14
- package/dist/cjs/__tests__/identity-cache/identity-gateway-test-setup.js +30 -37
- package/dist/cjs/__tests__/identity-cache/identity-gateway-test-setup.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js +424 -403
- package/dist/cjs/__tests__/identity-cache/trait-merging-and-staleness.spec.js.map +1 -1
- package/dist/cjs/__tests__/identity-cache/volatile-traits-optimization.spec.js +218 -219
- package/dist/cjs/__tests__/identity-cache/volatile-traits-optimization.spec.js.map +1 -1
- package/dist/cjs/__tests__/integration/sqs-bundling-roundtrip.spec.js +117 -118
- package/dist/cjs/__tests__/integration/sqs-bundling-roundtrip.spec.js.map +1 -1
- package/dist/cjs/__tests__/libs/compress-decompress.spec.js +7 -8
- package/dist/cjs/__tests__/libs/compress-decompress.spec.js.map +1 -1
- package/dist/cjs/__tests__/libs/contacts.spec.js +101 -102
- package/dist/cjs/__tests__/libs/contacts.spec.js.map +1 -1
- package/dist/cjs/__tests__/libs/currency.spec.js +56 -57
- package/dist/cjs/__tests__/libs/currency.spec.js.map +1 -1
- package/dist/cjs/__tests__/libs/dates.spec.js +94 -82
- package/dist/cjs/__tests__/libs/dates.spec.js.map +1 -1
- package/dist/cjs/__tests__/libs/domain.spec.js +68 -69
- package/dist/cjs/__tests__/libs/domain.spec.js.map +1 -1
- package/dist/cjs/__tests__/libs/numbers.spec.js +249 -250
- package/dist/cjs/__tests__/libs/numbers.spec.js.map +1 -1
- package/dist/cjs/__tests__/s3-client/s3-client.spec.js +16 -15
- package/dist/cjs/__tests__/s3-client/s3-client.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/acuity-api-service.spec.js +32 -35
- package/dist/cjs/__tests__/services/acuity-api-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/cost/cost-calculation-types.spec.js +14 -15
- package/dist/cjs/__tests__/services/cost/cost-calculation-types.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/cost/cost-calculator-service.spec.js +949 -1187
- package/dist/cjs/__tests__/services/cost/cost-calculator-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/cost/cost-currency-service.spec.js +39 -40
- package/dist/cjs/__tests__/services/cost/cost-currency-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/cost/cost-filter-service.spec.js +204 -201
- package/dist/cjs/__tests__/services/cost/cost-filter-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/cost/order-cost/order-cost-resolution-service.spec.js +174 -299
- package/dist/cjs/__tests__/services/cost/order-cost/order-cost-resolution-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/email-verification/contact-email-verification-service.spec.js +39 -41
- package/dist/cjs/__tests__/services/email-verification/contact-email-verification-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/email-verification/email-verification-service.spec.js +22 -27
- package/dist/cjs/__tests__/services/email-verification/email-verification-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/events/collect-queue-tracking-service.spec.js +64 -67
- package/dist/cjs/__tests__/services/events/collect-queue-tracking-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/events/tracking-event-sqs-service.spec.js +51 -54
- package/dist/cjs/__tests__/services/events/tracking-event-sqs-service.spec.js.map +1 -1
- package/dist/cjs/__tests__/services/liveintent-api-service.spec.js +67 -0
- package/dist/cjs/__tests__/services/liveintent-api-service.spec.js.map +1 -0
- package/dist/cjs/__tests__/shopify/shopify-graphql-transformer.spec.js +9 -10
- package/dist/cjs/__tests__/shopify/shopify-graphql-transformer.spec.js.map +1 -1
- package/dist/cjs/__tests__/unit/libs/api-router/public-api-router.spec.js +58 -69
- package/dist/cjs/__tests__/unit/libs/api-router/public-api-router.spec.js.map +1 -1
- package/dist/cjs/__tests__/unit/libs/api-router/route-matcher.spec.js +31 -32
- package/dist/cjs/__tests__/unit/libs/api-router/route-matcher.spec.js.map +1 -1
- package/dist/cjs/__tests__/utils/custom-measure-formula-utils.spec.js +64 -65
- package/dist/cjs/__tests__/utils/custom-measure-formula-utils.spec.js.map +1 -1
- package/dist/cjs/clients/generic/cognito-client.js +14 -14
- package/dist/cjs/clients/generic/cognito-client.js.map +1 -1
- package/dist/cjs/clients/generic/dynamodb-client.js +9 -9
- package/dist/cjs/clients/generic/dynamodb-client.js.map +1 -1
- package/dist/cjs/clients/generic/eventbridge-client.js +2 -2
- package/dist/cjs/clients/generic/eventbridge-client.js.map +1 -1
- package/dist/cjs/clients/generic/http-client.js +5 -5
- package/dist/cjs/clients/generic/http-client.js.map +1 -1
- package/dist/cjs/clients/generic/lambda-invoke-client.js.map +1 -1
- package/dist/cjs/clients/generic/location-client.js +2 -2
- package/dist/cjs/clients/generic/location-client.js.map +1 -1
- package/dist/cjs/clients/generic/redis-client.js +2 -13
- package/dist/cjs/clients/generic/redis-client.js.map +1 -1
- package/dist/cjs/clients/generic/s3-client.d.ts +1 -0
- package/dist/cjs/clients/generic/s3-client.js +19 -19
- package/dist/cjs/clients/generic/s3-client.js.map +1 -1
- package/dist/cjs/clients/generic/singlestore-db-client.d.ts +2 -2
- package/dist/cjs/clients/generic/singlestore-db-client.js +8 -18
- package/dist/cjs/clients/generic/singlestore-db-client.js.map +1 -1
- package/dist/cjs/clients/generic/sqs-bundled-client.js +2 -2
- package/dist/cjs/clients/generic/sqs-bundled-client.js.map +1 -1
- package/dist/cjs/clients/generic/sqs-bundled-client.types.js +1 -1
- package/dist/cjs/clients/generic/sqs-bundled-client.types.js.map +1 -1
- package/dist/cjs/clients/generic/sqs-client.d.ts +1 -1
- package/dist/cjs/clients/generic/sqs-client.js +2 -2
- package/dist/cjs/clients/generic/sqs-client.js.map +1 -1
- package/dist/cjs/clients/generic/sqs-unbundle.js +7 -6
- package/dist/cjs/clients/generic/sqs-unbundle.js.map +1 -1
- package/dist/cjs/clients/internal-api/accounts-client.js +14 -14
- package/dist/cjs/clients/internal-api/accounts-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/cache-lambda-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/db-management-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/destinations-client.js +8 -8
- package/dist/cjs/clients/internal-api/destinations-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/event-collector-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/identity-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/shopify-app-install-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/subscriptions-client.js.map +1 -1
- package/dist/cjs/clients/internal-api/users-auth-client.js +11 -11
- package/dist/cjs/clients/internal-api/users-auth-client.js.map +1 -1
- package/dist/cjs/clients/third-party/acuity-client.js.map +1 -1
- package/dist/cjs/clients/third-party/emailable-client.js.map +1 -1
- package/dist/cjs/clients/third-party/index.d.ts +1 -0
- package/dist/cjs/clients/third-party/index.js +1 -0
- package/dist/cjs/clients/third-party/index.js.map +1 -1
- package/dist/cjs/clients/third-party/liveintent-client.d.ts +11 -0
- package/dist/cjs/clients/third-party/liveintent-client.js +25 -0
- package/dist/cjs/clients/third-party/liveintent-client.js.map +1 -0
- package/dist/cjs/clients/third-party/loops-client.js.map +1 -1
- package/dist/cjs/clients/third-party/open-exchange-rates-client.js.map +1 -1
- package/dist/cjs/clients/third-party/shopify/shopify-graphql-client.js.map +1 -1
- package/dist/cjs/clients/third-party/shopify-client.js +15 -15
- package/dist/cjs/clients/third-party/shopify-client.js.map +1 -1
- package/dist/cjs/constants/sqs.js +5 -5
- package/dist/cjs/constants/sqs.js.map +1 -1
- package/dist/cjs/helpers/account-users-helper.js.map +1 -1
- package/dist/cjs/helpers/acuity-helper.js.map +1 -1
- package/dist/cjs/helpers/api-key-auth-helper.d.ts +1 -2
- package/dist/cjs/helpers/api-key-auth-helper.js.map +1 -1
- package/dist/cjs/helpers/api-key-authorizer-helper.js.map +1 -1
- package/dist/cjs/helpers/cognito-auth-helper.d.ts +1 -2
- package/dist/cjs/helpers/cognito-auth-helper.js.map +1 -1
- package/dist/cjs/helpers/input-validation-helper.d.ts +1 -1
- package/dist/cjs/helpers/input-validation-helper.js.map +1 -1
- package/dist/cjs/helpers/logging-helper.d.ts +5 -5
- package/dist/cjs/helpers/logging-helper.js +7 -17
- package/dist/cjs/helpers/logging-helper.js.map +1 -1
- package/dist/cjs/helpers/order-calculation-helper.js.map +1 -1
- package/dist/cjs/helpers/public-api-response-helper.js.map +1 -1
- package/dist/cjs/helpers/response-helper.js.map +1 -1
- package/dist/cjs/helpers/shopify-helper.js.map +1 -1
- package/dist/cjs/helpers/sqs-utils.js +4 -8
- package/dist/cjs/helpers/sqs-utils.js.map +1 -1
- package/dist/cjs/libs/api-router/public-api-router.d.ts +2 -2
- package/dist/cjs/libs/api-router/public-api-router.js.map +1 -1
- package/dist/cjs/libs/api-router/route-matcher.js.map +1 -1
- package/dist/cjs/libs/click-id-parser.js +1 -1
- package/dist/cjs/libs/click-id-parser.js.map +1 -1
- package/dist/cjs/libs/compression.d.ts +1 -1
- package/dist/cjs/libs/compression.js.map +1 -1
- package/dist/cjs/libs/contacts.js.map +1 -1
- package/dist/cjs/libs/cookie.js +1 -1
- package/dist/cjs/libs/cookie.js.map +1 -1
- package/dist/cjs/libs/crypto.js.map +1 -1
- package/dist/cjs/libs/csv.js.map +1 -1
- package/dist/cjs/libs/currency.js.map +1 -1
- package/dist/cjs/libs/dates.d.ts +1 -0
- package/dist/cjs/libs/dates.js +18 -1
- package/dist/cjs/libs/dates.js.map +1 -1
- package/dist/cjs/libs/domain.js.map +1 -1
- package/dist/cjs/libs/emails.js.map +1 -1
- package/dist/cjs/libs/http-error.js.map +1 -1
- package/dist/cjs/libs/http-status-codes.js +1 -1
- package/dist/cjs/libs/http-status-codes.js.map +1 -1
- package/dist/cjs/libs/numbers.js.map +1 -1
- package/dist/cjs/libs/referrer-parser/referrer-parser-util.d.ts +1 -0
- package/dist/cjs/libs/referrer-parser/referrer-parser-util.js +2 -2
- package/dist/cjs/libs/referrer-parser/referrer-parser-util.js.map +1 -1
- package/dist/cjs/libs/strings.js.map +1 -1
- package/dist/cjs/libs/traits.js.map +1 -1
- package/dist/cjs/libs/url.js.map +1 -1
- package/dist/cjs/services/acuity-api-service.js.map +1 -1
- package/dist/cjs/services/cache/product-cache-service.js.map +1 -1
- package/dist/cjs/services/cost/cost-calculation-types.js +2 -1
- package/dist/cjs/services/cost/cost-calculation-types.js.map +1 -1
- package/dist/cjs/services/cost/cost-calculator-service.js +10 -43
- package/dist/cjs/services/cost/cost-calculator-service.js.map +1 -1
- package/dist/cjs/services/cost/cost-currency-service.js.map +1 -1
- package/dist/cjs/services/cost/cost-filter-service.js +7 -16
- package/dist/cjs/services/cost/cost-filter-service.js.map +1 -1
- package/dist/cjs/services/cost/order-cost/order-cost-resolution-service.js +9 -24
- package/dist/cjs/services/cost/order-cost/order-cost-resolution-service.js.map +1 -1
- package/dist/cjs/services/db/accounts-db-service.js.map +1 -1
- package/dist/cjs/services/db/api-keys-db-service.js.map +1 -1
- package/dist/cjs/services/db/contact-enrichments-db-service.js.map +1 -1
- package/dist/cjs/services/db/custom-measures-db-service.js.map +1 -1
- package/dist/cjs/services/db/destinations-db-service.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-db-service.d.ts +1 -1
- package/dist/cjs/services/db/identity-cache-db-service.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +1 -5
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +7 -21
- package/dist/cjs/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/key-builders.js +7 -7
- package/dist/cjs/services/db/identity-cache-dynamodb-service/key-builders.js.map +1 -1
- package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js +3 -3
- package/dist/cjs/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
- package/dist/cjs/services/db/index.d.ts +0 -1
- package/dist/cjs/services/db/index.js +0 -1
- package/dist/cjs/services/db/index.js.map +1 -1
- package/dist/cjs/services/db/log-events-db-service.js.map +1 -1
- package/dist/cjs/services/db/pixels-db-service.js.map +1 -1
- package/dist/cjs/services/db/products-db-service.js +16 -45
- package/dist/cjs/services/db/products-db-service.js.map +1 -1
- package/dist/cjs/services/db/purchasable-contacts-db-service.js.map +1 -1
- package/dist/cjs/services/db/purchased-contacts/purchased-contacts-db-service.js.map +1 -1
- package/dist/cjs/services/db/shopify-app-installs-db-service.js.map +1 -1
- package/dist/cjs/services/db/shopify-products-cache-db-service.js.map +1 -1
- package/dist/cjs/services/db/subscriptions-db-service.js.map +1 -1
- package/dist/cjs/services/db/tracking-events-db-service.js.map +1 -1
- package/dist/cjs/services/db/user-accounts-db-service.js.map +1 -1
- package/dist/cjs/services/email-verification/contact-email-verification-service.js.map +1 -1
- package/dist/cjs/services/email-verification/email-verification-service.js.map +1 -1
- package/dist/cjs/services/eventbridge-integration-service.js.map +1 -1
- package/dist/cjs/services/events/build-collect-queue-tracking-event.js +2 -2
- package/dist/cjs/services/events/build-collect-queue-tracking-event.js.map +1 -1
- package/dist/cjs/services/events/collect-queue-tracking-service.js.map +1 -1
- package/dist/cjs/services/events/log-event-service.js.map +1 -1
- package/dist/cjs/services/events/metric-event-service.js.map +1 -1
- package/dist/cjs/services/events/tracking-event-sqs-service.js.map +1 -1
- package/dist/cjs/services/generic-cache-service.js.map +1 -1
- package/dist/cjs/services/index.d.ts +1 -1
- package/dist/cjs/services/index.js +1 -1
- package/dist/cjs/services/index.js.map +1 -1
- package/dist/cjs/services/ipdata-lookup-service.d.ts +1 -1
- package/dist/cjs/services/ipdata-lookup-service.js.map +1 -1
- package/dist/cjs/services/liveintent-api-service.d.ts +15 -0
- package/dist/cjs/services/liveintent-api-service.js +59 -0
- package/dist/cjs/services/liveintent-api-service.js.map +1 -0
- package/dist/cjs/services/shopify/products/shopify-products-serviceV2.js.map +1 -1
- package/dist/cjs/services/shopify/shopify-graphql-transformer.js +1 -1
- package/dist/cjs/services/shopify/shopify-graphql-transformer.js.map +1 -1
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.js +8 -17
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/internal-events/event-detail-types.js +4 -4
- package/dist/cjs/types/internal-events/event-detail-types.js.map +1 -1
- package/dist/cjs/types/liveintent-types.d.ts +8 -0
- package/dist/cjs/types/liveintent-types.js +3 -0
- package/dist/cjs/types/liveintent-types.js.map +1 -0
- package/dist/cjs/types/public-api-types.js +1 -1
- package/dist/cjs/types/public-api-types.js.map +1 -1
- package/dist/cjs/types/shopify-graphql-types/admin.types.js +491 -491
- package/dist/cjs/types/shopify-graphql-types/admin.types.js.map +1 -1
- package/dist/cjs/types/shopify-rest-types.d.ts +1 -1
- package/dist/cjs/utils/compression.d.ts +2 -0
- package/dist/cjs/utils/compression.js +11 -11
- package/dist/cjs/utils/compression.js.map +1 -1
- package/dist/cjs/utils/custom-measure-formula-utils.js.map +1 -1
- package/dist/cjs/utils/retry-envelope.js +4 -3
- package/dist/cjs/utils/retry-envelope.js.map +1 -1
- package/dist/cjs/utils/size.js +3 -2
- package/dist/cjs/utils/size.js.map +1 -1
- package/dist/esm/__tests__/clients/acuity-client.spec.js +5 -6
- package/dist/esm/__tests__/clients/acuity-client.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/cross-platform-compression.spec.js +0 -1
- package/dist/esm/__tests__/clients/cross-platform-compression.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/dynamodb-client.spec.js +42 -41
- package/dist/esm/__tests__/clients/dynamodb-client.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/event-collector-client.spec.js +18 -18
- package/dist/esm/__tests__/clients/event-collector-client.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/liveintent-client.spec.js +35 -0
- package/dist/esm/__tests__/clients/liveintent-client.spec.js.map +1 -0
- package/dist/esm/__tests__/clients/open-exchange-rates-client.spec.js +3 -4
- package/dist/esm/__tests__/clients/open-exchange-rates-client.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/sqs-bundled-client.spec.js +47 -55
- package/dist/esm/__tests__/clients/sqs-bundled-client.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/sqs-bundling-contracts.spec.js +1 -3
- package/dist/esm/__tests__/clients/sqs-bundling-contracts.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/sqs-client.spec.js +21 -22
- package/dist/esm/__tests__/clients/sqs-client.spec.js.map +1 -1
- package/dist/esm/__tests__/clients/sqs-unbundle.spec.js +8 -9
- package/dist/esm/__tests__/clients/sqs-unbundle.spec.js.map +1 -1
- package/dist/esm/__tests__/db/contact-enrichments-db-service.spec.js +5 -6
- package/dist/esm/__tests__/db/contact-enrichments-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/db/destinations-db-service.spec.js +11 -9
- package/dist/esm/__tests__/db/destinations-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/db/products-db-service.spec.js +8 -9
- package/dist/esm/__tests__/db/products-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/db/shared-read-db-services.spec.js +6 -7
- package/dist/esm/__tests__/db/shared-read-db-services.spec.js.map +1 -1
- package/dist/esm/__tests__/db/shopify-app-installs-db-service.spec.js +12 -13
- package/dist/esm/__tests__/db/shopify-app-installs-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/db/subscriptions-db-service.spec.js +11 -12
- package/dist/esm/__tests__/db/subscriptions-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/db/user-accounts-db-service.spec.js +6 -7
- package/dist/esm/__tests__/db/user-accounts-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/helpers/account-users-helper.spec.js +3 -4
- package/dist/esm/__tests__/helpers/account-users-helper.spec.js.map +1 -1
- package/dist/esm/__tests__/helpers/acuity-helper.spec.js +0 -1
- package/dist/esm/__tests__/helpers/acuity-helper.spec.js.map +1 -1
- package/dist/esm/__tests__/helpers/api-key-auth-helper.spec.js +3 -4
- package/dist/esm/__tests__/helpers/api-key-auth-helper.spec.js.map +1 -1
- package/dist/esm/__tests__/helpers/cognito-auth-helper.spec.js +1 -2
- package/dist/esm/__tests__/helpers/cognito-auth-helper.spec.js.map +1 -1
- package/dist/esm/__tests__/helpers/order-calculation-helper.spec.js +4 -5
- package/dist/esm/__tests__/helpers/order-calculation-helper.spec.js.map +1 -1
- package/dist/esm/__tests__/helpers/public-api-response-helper.spec.js +1 -2
- package/dist/esm/__tests__/helpers/public-api-response-helper.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/helpers.spec.js +1 -2
- package/dist/esm/__tests__/identity-cache/helpers.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-cache-alias-write.spec.js +15 -16
- package/dist/esm/__tests__/identity-cache/identity-cache-alias-write.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-cache-db-service.spec.js +1 -2
- package/dist/esm/__tests__/identity-cache/identity-cache-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js +29 -52
- package/dist/esm/__tests__/identity-cache/identity-cache-dynamodb-db-service.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js +31 -40
- package/dist/esm/__tests__/identity-cache/identity-cache-tier-routing.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-client.spec.js +21 -24
- package/dist/esm/__tests__/identity-cache/identity-client.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-cache-hit.spec.js +0 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-cache-hit.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-cache-miss.spec.js +4 -17
- package/dist/esm/__tests__/identity-cache/identity-gateway-cache-miss.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-constructor.spec.js +0 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-constructor.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-edge-cases.spec.js +2 -9
- package/dist/esm/__tests__/identity-cache/identity-gateway-edge-cases.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-enqueue-async.spec.js +0 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-enqueue-async.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-stale-cache.spec.js +7 -29
- package/dist/esm/__tests__/identity-cache/identity-gateway-stale-cache.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/identity-gateway-test-setup.d.ts +18 -14
- package/dist/esm/__tests__/identity-cache/identity-gateway-test-setup.js +30 -37
- package/dist/esm/__tests__/identity-cache/identity-gateway-test-setup.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js +37 -16
- package/dist/esm/__tests__/identity-cache/trait-merging-and-staleness.spec.js.map +1 -1
- package/dist/esm/__tests__/identity-cache/volatile-traits-optimization.spec.js +5 -6
- package/dist/esm/__tests__/identity-cache/volatile-traits-optimization.spec.js.map +1 -1
- package/dist/esm/__tests__/integration/sqs-bundling-roundtrip.spec.js +9 -10
- package/dist/esm/__tests__/integration/sqs-bundling-roundtrip.spec.js.map +1 -1
- package/dist/esm/__tests__/libs/compress-decompress.spec.js +1 -2
- package/dist/esm/__tests__/libs/compress-decompress.spec.js.map +1 -1
- package/dist/esm/__tests__/libs/contacts.spec.js +0 -1
- package/dist/esm/__tests__/libs/contacts.spec.js.map +1 -1
- package/dist/esm/__tests__/libs/currency.spec.js +3 -4
- package/dist/esm/__tests__/libs/currency.spec.js.map +1 -1
- package/dist/esm/__tests__/libs/dates.spec.js +23 -11
- package/dist/esm/__tests__/libs/dates.spec.js.map +1 -1
- package/dist/esm/__tests__/libs/domain.spec.js +0 -1
- package/dist/esm/__tests__/libs/domain.spec.js.map +1 -1
- package/dist/esm/__tests__/libs/numbers.spec.js +0 -1
- package/dist/esm/__tests__/libs/numbers.spec.js.map +1 -1
- package/dist/esm/__tests__/s3-client/s3-client.spec.js +7 -6
- package/dist/esm/__tests__/s3-client/s3-client.spec.js.map +1 -1
- package/dist/esm/__tests__/services/acuity-api-service.spec.js +10 -13
- package/dist/esm/__tests__/services/acuity-api-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/cost/cost-calculation-types.spec.js +0 -1
- package/dist/esm/__tests__/services/cost/cost-calculation-types.spec.js.map +1 -1
- package/dist/esm/__tests__/services/cost/cost-calculator-service.spec.js +280 -518
- package/dist/esm/__tests__/services/cost/cost-calculator-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/cost/cost-currency-service.spec.js +3 -4
- package/dist/esm/__tests__/services/cost/cost-currency-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/cost/cost-filter-service.spec.js +22 -19
- package/dist/esm/__tests__/services/cost/cost-filter-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/cost/order-cost/order-cost-resolution-service.spec.js +41 -133
- package/dist/esm/__tests__/services/cost/order-cost/order-cost-resolution-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/email-verification/contact-email-verification-service.spec.js +6 -8
- package/dist/esm/__tests__/services/email-verification/contact-email-verification-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/email-verification/email-verification-service.spec.js +5 -10
- package/dist/esm/__tests__/services/email-verification/email-verification-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/events/collect-queue-tracking-service.spec.js +14 -17
- package/dist/esm/__tests__/services/events/collect-queue-tracking-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/events/tracking-event-sqs-service.spec.js +16 -19
- package/dist/esm/__tests__/services/events/tracking-event-sqs-service.spec.js.map +1 -1
- package/dist/esm/__tests__/services/liveintent-api-service.spec.js +65 -0
- package/dist/esm/__tests__/services/liveintent-api-service.spec.js.map +1 -0
- package/dist/esm/__tests__/shopify/shopify-graphql-transformer.spec.js +1 -2
- package/dist/esm/__tests__/shopify/shopify-graphql-transformer.spec.js.map +1 -1
- package/dist/esm/__tests__/unit/libs/api-router/public-api-router.spec.js +14 -15
- package/dist/esm/__tests__/unit/libs/api-router/public-api-router.spec.js.map +1 -1
- package/dist/esm/__tests__/unit/libs/api-router/route-matcher.spec.js +1 -2
- package/dist/esm/__tests__/unit/libs/api-router/route-matcher.spec.js.map +1 -1
- package/dist/esm/__tests__/utils/custom-measure-formula-utils.spec.js +0 -1
- package/dist/esm/__tests__/utils/custom-measure-formula-utils.spec.js.map +1 -1
- package/dist/esm/clients/generic/cognito-client.js +2 -2
- package/dist/esm/clients/generic/cognito-client.js.map +1 -1
- package/dist/esm/clients/generic/dynamodb-client.js +9 -9
- package/dist/esm/clients/generic/dynamodb-client.js.map +1 -1
- package/dist/esm/clients/generic/eventbridge-client.js +1 -1
- package/dist/esm/clients/generic/eventbridge-client.js.map +1 -1
- package/dist/esm/clients/generic/http-client.js +5 -5
- package/dist/esm/clients/generic/http-client.js.map +1 -1
- package/dist/esm/clients/generic/lambda-invoke-client.js.map +1 -1
- package/dist/esm/clients/generic/location-client.js +1 -1
- package/dist/esm/clients/generic/location-client.js.map +1 -1
- package/dist/esm/clients/generic/redis-client.js +2 -13
- package/dist/esm/clients/generic/redis-client.js.map +1 -1
- package/dist/esm/clients/generic/s3-client.d.ts +1 -0
- package/dist/esm/clients/generic/s3-client.js +1 -1
- package/dist/esm/clients/generic/s3-client.js.map +1 -1
- package/dist/esm/clients/generic/singlestore-db-client.d.ts +2 -2
- package/dist/esm/clients/generic/singlestore-db-client.js +1 -1
- package/dist/esm/clients/generic/singlestore-db-client.js.map +1 -1
- package/dist/esm/clients/generic/sqs-bundled-client.js +2 -2
- package/dist/esm/clients/generic/sqs-bundled-client.js.map +1 -1
- package/dist/esm/clients/generic/sqs-client.d.ts +1 -1
- package/dist/esm/clients/generic/sqs-client.js +2 -2
- package/dist/esm/clients/generic/sqs-client.js.map +1 -1
- package/dist/esm/clients/generic/sqs-unbundle.js +2 -2
- package/dist/esm/clients/generic/sqs-unbundle.js.map +1 -1
- package/dist/esm/clients/internal-api/accounts-client.js +1 -1
- package/dist/esm/clients/internal-api/accounts-client.js.map +1 -1
- package/dist/esm/clients/internal-api/cache-lambda-client.js.map +1 -1
- package/dist/esm/clients/internal-api/destinations-client.js +1 -1
- package/dist/esm/clients/internal-api/destinations-client.js.map +1 -1
- package/dist/esm/clients/internal-api/event-collector-client.js.map +1 -1
- package/dist/esm/clients/internal-api/identity-client.js.map +1 -1
- package/dist/esm/clients/internal-api/users-auth-client.js +1 -1
- package/dist/esm/clients/internal-api/users-auth-client.js.map +1 -1
- package/dist/esm/clients/third-party/emailable-client.js.map +1 -1
- package/dist/esm/clients/third-party/index.d.ts +1 -0
- package/dist/esm/clients/third-party/index.js +1 -0
- package/dist/esm/clients/third-party/index.js.map +1 -1
- package/dist/esm/clients/third-party/liveintent-client.d.ts +11 -0
- package/dist/esm/clients/third-party/liveintent-client.js +21 -0
- package/dist/esm/clients/third-party/liveintent-client.js.map +1 -0
- package/dist/esm/clients/third-party/loops-client.js.map +1 -1
- package/dist/esm/clients/third-party/open-exchange-rates-client.js.map +1 -1
- package/dist/esm/clients/third-party/shopify/shopify-graphql-client.js +1 -1
- package/dist/esm/clients/third-party/shopify/shopify-graphql-client.js.map +1 -1
- package/dist/esm/clients/third-party/shopify-client.js +1 -1
- package/dist/esm/clients/third-party/shopify-client.js.map +1 -1
- package/dist/esm/constants/sqs.js +3 -3
- package/dist/esm/constants/sqs.js.map +1 -1
- package/dist/esm/helpers/account-users-helper.js.map +1 -1
- package/dist/esm/helpers/acuity-helper.js.map +1 -1
- package/dist/esm/helpers/api-key-auth-helper.d.ts +1 -2
- package/dist/esm/helpers/api-key-auth-helper.js.map +1 -1
- package/dist/esm/helpers/api-key-authorizer-helper.js.map +1 -1
- package/dist/esm/helpers/cognito-auth-helper.d.ts +1 -2
- package/dist/esm/helpers/cognito-auth-helper.js.map +1 -1
- package/dist/esm/helpers/input-validation-helper.d.ts +1 -1
- package/dist/esm/helpers/input-validation-helper.js.map +1 -1
- package/dist/esm/helpers/logging-helper.d.ts +5 -5
- package/dist/esm/helpers/logging-helper.js.map +1 -1
- package/dist/esm/helpers/order-calculation-helper.js.map +1 -1
- package/dist/esm/helpers/public-api-response-helper.js.map +1 -1
- package/dist/esm/helpers/response-helper.js.map +1 -1
- package/dist/esm/helpers/shopify-helper.js.map +1 -1
- package/dist/esm/helpers/sqs-utils.js +1 -6
- package/dist/esm/helpers/sqs-utils.js.map +1 -1
- package/dist/esm/libs/api-router/public-api-router.d.ts +2 -2
- package/dist/esm/libs/api-router/public-api-router.js.map +1 -1
- package/dist/esm/libs/api-router/route-matcher.js.map +1 -1
- package/dist/esm/libs/click-id-parser.js.map +1 -1
- package/dist/esm/libs/compression.d.ts +1 -1
- package/dist/esm/libs/compression.js.map +1 -1
- package/dist/esm/libs/contacts.js.map +1 -1
- package/dist/esm/libs/cookie.js.map +1 -1
- package/dist/esm/libs/csv.js.map +1 -1
- package/dist/esm/libs/currency.js.map +1 -1
- package/dist/esm/libs/dates.d.ts +1 -0
- package/dist/esm/libs/dates.js +16 -0
- package/dist/esm/libs/dates.js.map +1 -1
- package/dist/esm/libs/domain.js.map +1 -1
- package/dist/esm/libs/emails.js.map +1 -1
- package/dist/esm/libs/http-error.js.map +1 -1
- package/dist/esm/libs/numbers.js.map +1 -1
- package/dist/esm/libs/referrer-parser/referrer-parser-util.d.ts +1 -0
- package/dist/esm/libs/referrer-parser/referrer-parser-util.js +2 -2
- package/dist/esm/libs/referrer-parser/referrer-parser-util.js.map +1 -1
- package/dist/esm/libs/strings.js.map +1 -1
- package/dist/esm/libs/traits.js.map +1 -1
- package/dist/esm/services/acuity-api-service.js.map +1 -1
- package/dist/esm/services/cache/product-cache-service.js.map +1 -1
- package/dist/esm/services/cost/cost-calculation-types.js.map +1 -1
- package/dist/esm/services/cost/cost-calculator-service.js +10 -43
- package/dist/esm/services/cost/cost-calculator-service.js.map +1 -1
- package/dist/esm/services/cost/cost-currency-service.js.map +1 -1
- package/dist/esm/services/cost/cost-filter-service.js +7 -16
- package/dist/esm/services/cost/cost-filter-service.js.map +1 -1
- package/dist/esm/services/cost/order-cost/order-cost-resolution-service.js +9 -24
- package/dist/esm/services/cost/order-cost/order-cost-resolution-service.js.map +1 -1
- package/dist/esm/services/db/accounts-db-service.js.map +1 -1
- package/dist/esm/services/db/api-keys-db-service.js.map +1 -1
- package/dist/esm/services/db/contact-enrichments-db-service.js.map +1 -1
- package/dist/esm/services/db/custom-measures-db-service.js.map +1 -1
- package/dist/esm/services/db/identity-cache-db-service.d.ts +1 -1
- package/dist/esm/services/db/identity-cache-db-service.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js +2 -6
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-cache-dynamodb-db-service.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js +8 -22
- package/dist/esm/services/db/identity-cache-dynamodb-service/identity-gateway-service.js.map +1 -1
- package/dist/esm/services/db/identity-cache-dynamodb-service/types.js.map +1 -1
- package/dist/esm/services/db/index.d.ts +0 -1
- package/dist/esm/services/db/index.js +0 -1
- package/dist/esm/services/db/index.js.map +1 -1
- package/dist/esm/services/db/log-events-db-service.js.map +1 -1
- package/dist/esm/services/db/products-db-service.js +16 -45
- package/dist/esm/services/db/products-db-service.js.map +1 -1
- package/dist/esm/services/db/purchasable-contacts-db-service.js.map +1 -1
- package/dist/esm/services/db/purchased-contacts/purchased-contacts-db-service.js.map +1 -1
- package/dist/esm/services/db/shopify-app-installs-db-service.js.map +1 -1
- package/dist/esm/services/db/shopify-products-cache-db-service.js.map +1 -1
- package/dist/esm/services/db/subscriptions-db-service.js.map +1 -1
- package/dist/esm/services/db/tracking-events-db-service.js.map +1 -1
- package/dist/esm/services/email-verification/contact-email-verification-service.js.map +1 -1
- package/dist/esm/services/email-verification/email-verification-service.js.map +1 -1
- package/dist/esm/services/events/build-collect-queue-tracking-event.js.map +1 -1
- package/dist/esm/services/events/collect-queue-tracking-service.js +1 -1
- package/dist/esm/services/events/collect-queue-tracking-service.js.map +1 -1
- package/dist/esm/services/events/log-event-service.js.map +1 -1
- package/dist/esm/services/events/metric-event-service.js.map +1 -1
- package/dist/esm/services/events/tracking-event-sqs-service.js.map +1 -1
- package/dist/esm/services/generic-cache-service.js.map +1 -1
- package/dist/esm/services/index.d.ts +1 -1
- package/dist/esm/services/index.js +1 -1
- package/dist/esm/services/index.js.map +1 -1
- package/dist/esm/services/ipdata-lookup-service.d.ts +1 -1
- package/dist/esm/services/ipdata-lookup-service.js.map +1 -1
- package/dist/esm/services/liveintent-api-service.d.ts +15 -0
- package/dist/esm/services/liveintent-api-service.js +55 -0
- package/dist/esm/services/liveintent-api-service.js.map +1 -0
- package/dist/esm/services/shopify/products/shopify-products-serviceV2.js.map +1 -1
- package/dist/esm/services/shopify/shopify-graphql-transformer.js +1 -1
- package/dist/esm/services/shopify/shopify-graphql-transformer.js.map +1 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/types/index.js.map +1 -1
- package/dist/esm/types/liveintent-types.d.ts +8 -0
- package/dist/esm/types/liveintent-types.js +2 -0
- package/dist/esm/types/liveintent-types.js.map +1 -0
- package/dist/esm/types/shopify-rest-types.d.ts +1 -1
- package/dist/esm/utils/compression.d.ts +2 -0
- package/dist/esm/utils/compression.js +3 -3
- package/dist/esm/utils/compression.js.map +1 -1
- package/dist/esm/utils/custom-measure-formula-utils.js.map +1 -1
- package/dist/esm/utils/retry-envelope.js.map +1 -1
- package/dist/esm/utils/size.js.map +1 -1
- package/package.json +136 -139
- package/dist/cjs/__tests__/clients/client-timeout-inventory.spec.js +0 -21
- package/dist/cjs/__tests__/clients/client-timeout-inventory.spec.js.map +0 -1
- package/dist/cjs/__tests__/clients/redis-client.spec.js +0 -79
- package/dist/cjs/__tests__/clients/redis-client.spec.js.map +0 -1
- package/dist/cjs/__tests__/services/currency-exchange-rate-lookup-service.spec.js +0 -40
- package/dist/cjs/__tests__/services/currency-exchange-rate-lookup-service.spec.js.map +0 -1
- package/dist/cjs/clients/third-party/exchange-rate-api-client.d.ts +0 -17
- package/dist/cjs/clients/third-party/exchange-rate-api-client.js +0 -20
- package/dist/cjs/clients/third-party/exchange-rate-api-client.js.map +0 -1
- package/dist/cjs/services/currency-exchange-rate-lookup-service.d.ts +0 -12
- package/dist/cjs/services/currency-exchange-rate-lookup-service.js +0 -98
- package/dist/cjs/services/currency-exchange-rate-lookup-service.js.map +0 -1
- package/dist/cjs/services/db/currency-exchange-rates-db-service.d.ts +0 -21
- package/dist/cjs/services/db/currency-exchange-rates-db-service.js +0 -40
- package/dist/cjs/services/db/currency-exchange-rates-db-service.js.map +0 -1
- package/dist/esm/__tests__/clients/client-timeout-inventory.spec.js +0 -19
- package/dist/esm/__tests__/clients/client-timeout-inventory.spec.js.map +0 -1
- package/dist/esm/__tests__/clients/redis-client.spec.d.ts +0 -1
- package/dist/esm/__tests__/clients/redis-client.spec.js +0 -77
- package/dist/esm/__tests__/clients/redis-client.spec.js.map +0 -1
- package/dist/esm/__tests__/services/currency-exchange-rate-lookup-service.spec.d.ts +0 -1
- package/dist/esm/__tests__/services/currency-exchange-rate-lookup-service.spec.js +0 -38
- package/dist/esm/__tests__/services/currency-exchange-rate-lookup-service.spec.js.map +0 -1
- package/dist/esm/clients/third-party/exchange-rate-api-client.d.ts +0 -17
- package/dist/esm/clients/third-party/exchange-rate-api-client.js +0 -16
- package/dist/esm/clients/third-party/exchange-rate-api-client.js.map +0 -1
- package/dist/esm/services/currency-exchange-rate-lookup-service.d.ts +0 -12
- package/dist/esm/services/currency-exchange-rate-lookup-service.js +0 -94
- package/dist/esm/services/currency-exchange-rate-lookup-service.js.map +0 -1
- package/dist/esm/services/db/currency-exchange-rates-db-service.d.ts +0 -21
- package/dist/esm/services/db/currency-exchange-rates-db-service.js +0 -36
- package/dist/esm/services/db/currency-exchange-rates-db-service.js.map +0 -1
- /package/dist/cjs/__tests__/clients/{client-timeout-inventory.spec.d.ts → liveintent-client.spec.d.ts} +0 -0
- /package/dist/cjs/__tests__/{clients/redis-client.spec.d.ts → services/liveintent-api-service.spec.d.ts} +0 -0
- /package/dist/{cjs/__tests__/services/currency-exchange-rate-lookup-service.spec.d.ts → esm/__tests__/clients/liveintent-client.spec.d.ts} +0 -0
- /package/dist/esm/__tests__/{clients/client-timeout-inventory.spec.d.ts → services/liveintent-api-service.spec.d.ts} +0 -0
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const vitest_1 = require("vitest");
|
|
4
3
|
const sqs_unbundle_1 = require("../../clients/generic/sqs-unbundle");
|
|
5
4
|
const sqs_bundled_client_types_1 = require("../../clients/generic/sqs-bundled-client.types");
|
|
6
5
|
const compression_1 = require("../../utils/compression");
|
|
7
6
|
const node_zlib_1 = require("node:zlib");
|
|
8
7
|
const node_util_1 = require("node:util");
|
|
9
8
|
const gzipAsync = (0, node_util_1.promisify)(node_zlib_1.gzip);
|
|
10
|
-
|
|
9
|
+
jest.mock('../../helpers/logging-helper', () => ({
|
|
11
10
|
Logger: {
|
|
12
|
-
debug:
|
|
13
|
-
info:
|
|
14
|
-
warn:
|
|
15
|
-
error:
|
|
11
|
+
debug: jest.fn(),
|
|
12
|
+
info: jest.fn(),
|
|
13
|
+
warn: jest.fn(),
|
|
14
|
+
error: jest.fn(),
|
|
16
15
|
},
|
|
17
16
|
}));
|
|
18
17
|
function makeTestEvent(id, name = 'test_event', value) {
|
|
@@ -57,224 +56,224 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
57
56
|
p: base64,
|
|
58
57
|
};
|
|
59
58
|
}
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
describe('isBundledEnvelope', () => {
|
|
60
|
+
it('returns true for valid bundled envelope with NONE compression', () => {
|
|
62
61
|
const envelope = makeBundledEnvelope([makeTestEvent('1')]);
|
|
63
|
-
|
|
62
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(true);
|
|
64
63
|
});
|
|
65
|
-
|
|
64
|
+
it('returns true for valid bundled envelope with ZSTD compression', async () => {
|
|
66
65
|
const envelope = await makeCompressedEnvelope([makeTestEvent('1')]);
|
|
67
|
-
|
|
66
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(true);
|
|
68
67
|
});
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
it('returns false for null', () => {
|
|
69
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(null)).toBe(false);
|
|
71
70
|
});
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
it('returns false for undefined', () => {
|
|
72
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(undefined)).toBe(false);
|
|
74
73
|
});
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
it('returns false for plain object (legacy message)', () => {
|
|
75
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(makeTestEvent('1'))).toBe(false);
|
|
77
76
|
});
|
|
78
|
-
|
|
77
|
+
it('returns false for wrong version', () => {
|
|
79
78
|
const envelope = { v: 2, c: 'none', n: 1, p: [] };
|
|
80
|
-
|
|
79
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(false);
|
|
81
80
|
});
|
|
82
|
-
|
|
81
|
+
it('returns true for valid bundled envelope with GZIP compression', async () => {
|
|
83
82
|
const envelope = await makeGzipCompressedEnvelope([makeTestEvent('1')]);
|
|
84
|
-
|
|
83
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(true);
|
|
85
84
|
});
|
|
86
|
-
|
|
85
|
+
it('returns false for invalid compression algorithm', () => {
|
|
87
86
|
const envelope = { v: 1, c: 'lz4', n: 1, p: [] };
|
|
88
|
-
|
|
87
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(false);
|
|
89
88
|
});
|
|
90
|
-
|
|
89
|
+
it('returns false for missing count', () => {
|
|
91
90
|
const envelope = { v: 1, c: 'none', p: [] };
|
|
92
|
-
|
|
91
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(false);
|
|
93
92
|
});
|
|
94
|
-
|
|
93
|
+
it('returns false for missing payload', () => {
|
|
95
94
|
const envelope = { v: 1, c: 'none', n: 1 };
|
|
96
|
-
|
|
95
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(false);
|
|
97
96
|
});
|
|
98
97
|
});
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
describe('unbundleMessage', () => {
|
|
99
|
+
it('unbundles NONE compression envelope', async () => {
|
|
101
100
|
const items = [makeTestEvent('1'), makeTestEvent('2')];
|
|
102
101
|
const envelope = makeBundledEnvelope(items);
|
|
103
102
|
const result = await (0, sqs_unbundle_1.unbundleMessage)(envelope);
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
expect(result).toHaveLength(2);
|
|
104
|
+
expect(result[0].eventId).toBe('1');
|
|
105
|
+
expect(result[1].eventId).toBe('2');
|
|
107
106
|
});
|
|
108
|
-
|
|
107
|
+
it('unbundles ZSTD compressed envelope', async () => {
|
|
109
108
|
const items = [makeTestEvent('1'), makeTestEvent('2'), makeTestEvent('3')];
|
|
110
109
|
const envelope = await makeCompressedEnvelope(items);
|
|
111
110
|
const result = await (0, sqs_unbundle_1.unbundleMessage)(envelope);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
111
|
+
expect(result).toHaveLength(3);
|
|
112
|
+
expect(result[0].eventId).toBe('1');
|
|
113
|
+
expect(result[1].eventId).toBe('2');
|
|
114
|
+
expect(result[2].eventId).toBe('3');
|
|
116
115
|
});
|
|
117
|
-
|
|
116
|
+
it('unbundles large batches with ZSTD compression', async () => {
|
|
118
117
|
const items = Array.from({ length: 500 }, (_, i) => makeTestEvent(`event-${i}`, `event_${i}`, i * 10));
|
|
119
118
|
const envelope = await makeCompressedEnvelope(items);
|
|
120
119
|
const result = await (0, sqs_unbundle_1.unbundleMessage)(envelope);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
120
|
+
expect(result).toHaveLength(500);
|
|
121
|
+
expect(result[0].eventId).toBe('event-0');
|
|
122
|
+
expect(result[499].eventId).toBe('event-499');
|
|
124
123
|
});
|
|
125
|
-
|
|
124
|
+
it('throws on unsupported bundle version', async () => {
|
|
126
125
|
const envelope = { v: 99, c: 'none', n: 1, p: [] };
|
|
127
|
-
await
|
|
126
|
+
await expect((0, sqs_unbundle_1.unbundleMessage)(envelope)).rejects.toThrow('Unsupported bundle version: 99');
|
|
128
127
|
});
|
|
129
|
-
|
|
128
|
+
it('throws on invalid payload type for NONE compression', async () => {
|
|
130
129
|
const envelope = { v: 1, c: 'none', n: 1, p: 'not-an-array' };
|
|
131
|
-
await
|
|
130
|
+
await expect((0, sqs_unbundle_1.unbundleMessage)(envelope)).rejects.toThrow('Invalid bundle: NONE compression but payload is not an array');
|
|
132
131
|
});
|
|
133
|
-
|
|
132
|
+
it('throws on invalid payload type for ZSTD compression', async () => {
|
|
134
133
|
const envelope = { v: 1, c: 'zstd', n: 1, p: [] };
|
|
135
|
-
await
|
|
134
|
+
await expect((0, sqs_unbundle_1.unbundleMessage)(envelope)).rejects.toThrow('Invalid bundle: zstd compression but payload is not a string');
|
|
136
135
|
});
|
|
137
|
-
|
|
136
|
+
it('unbundles GZIP compressed envelope', async () => {
|
|
138
137
|
const items = [makeTestEvent('1'), makeTestEvent('2'), makeTestEvent('3')];
|
|
139
138
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
140
139
|
const result = await (0, sqs_unbundle_1.unbundleMessage)(envelope);
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
expect(result).toHaveLength(3);
|
|
141
|
+
expect(result[0].eventId).toBe('1');
|
|
142
|
+
expect(result[1].eventId).toBe('2');
|
|
143
|
+
expect(result[2].eventId).toBe('3');
|
|
145
144
|
});
|
|
146
|
-
|
|
145
|
+
it('unbundles large batches with GZIP compression', async () => {
|
|
147
146
|
const items = Array.from({ length: 500 }, (_, i) => makeTestEvent(`event-${i}`, `event_${i}`, i * 10));
|
|
148
147
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
149
148
|
const result = await (0, sqs_unbundle_1.unbundleMessage)(envelope);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
149
|
+
expect(result).toHaveLength(500);
|
|
150
|
+
expect(result[0].eventId).toBe('event-0');
|
|
151
|
+
expect(result[499].eventId).toBe('event-499');
|
|
153
152
|
});
|
|
154
|
-
|
|
153
|
+
it('throws on invalid payload type for GZIP compression', async () => {
|
|
155
154
|
const envelope = { v: 1, c: 'gzip', n: 1, p: [] };
|
|
156
|
-
await
|
|
155
|
+
await expect((0, sqs_unbundle_1.unbundleMessage)(envelope)).rejects.toThrow('Invalid bundle: gzip compression but payload is not a string');
|
|
157
156
|
});
|
|
158
157
|
});
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
describe('unbundleRecords', () => {
|
|
159
|
+
describe('legacy (non-bundled) messages', () => {
|
|
160
|
+
it('parses raw JSON message', async () => {
|
|
162
161
|
const event = makeTestEvent('raw-1', 'purchase');
|
|
163
162
|
const record = makeSqsRecord(event);
|
|
164
163
|
const { items, stats, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
expect(items).toHaveLength(1);
|
|
165
|
+
expect(items[0].eventId).toBe('raw-1');
|
|
166
|
+
expect(items[0].name).toBe('purchase');
|
|
167
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
168
|
+
expect(stats.bundledSqsRecords).toBe(0);
|
|
169
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
171
170
|
});
|
|
172
|
-
|
|
171
|
+
it('parses wrapped messageBody format', async () => {
|
|
173
172
|
const event = makeTestEvent('wrapped-1');
|
|
174
173
|
const record = makeSqsRecord({ messageBody: event });
|
|
175
174
|
const { items, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
175
|
+
expect(items).toHaveLength(1);
|
|
176
|
+
expect(items[0].eventId).toBe('wrapped-1');
|
|
177
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
179
178
|
});
|
|
180
|
-
|
|
179
|
+
it('handles multiple legacy records', async () => {
|
|
181
180
|
const records = [
|
|
182
181
|
makeSqsRecord(makeTestEvent('1'), 'msg-1'),
|
|
183
182
|
makeSqsRecord(makeTestEvent('2'), 'msg-2'),
|
|
184
183
|
makeSqsRecord(makeTestEvent('3'), 'msg-3'),
|
|
185
184
|
];
|
|
186
185
|
const { items, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
186
|
+
expect(items).toHaveLength(3);
|
|
187
|
+
expect(stats.legacySqsRecords).toBe(3);
|
|
188
|
+
expect(stats.totalItems).toBe(3);
|
|
189
|
+
expect(recordMap.get(items[0])).toBe('msg-1');
|
|
190
|
+
expect(recordMap.get(items[1])).toBe('msg-2');
|
|
191
|
+
expect(recordMap.get(items[2])).toBe('msg-3');
|
|
193
192
|
});
|
|
194
193
|
});
|
|
195
|
-
|
|
196
|
-
|
|
194
|
+
describe('bundled messages (NONE compression)', () => {
|
|
195
|
+
it('unbundles wrapped messageBody envelope', async () => {
|
|
197
196
|
const items = [makeTestEvent('b1'), makeTestEvent('b2')];
|
|
198
197
|
const envelope = makeBundledEnvelope(items);
|
|
199
198
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
200
199
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
200
|
+
expect(result).toHaveLength(2);
|
|
201
|
+
expect(result[0].eventId).toBe('b1');
|
|
202
|
+
expect(result[1].eventId).toBe('b2');
|
|
203
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
204
|
+
expect(stats.legacySqsRecords).toBe(0);
|
|
206
205
|
});
|
|
207
|
-
|
|
206
|
+
it('unbundles raw envelope (not wrapped)', async () => {
|
|
208
207
|
const items = [makeTestEvent('r1'), makeTestEvent('r2')];
|
|
209
208
|
const envelope = makeBundledEnvelope(items);
|
|
210
209
|
const record = makeSqsRecord(envelope);
|
|
211
210
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
expect(result).toHaveLength(2);
|
|
212
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
214
213
|
});
|
|
215
|
-
|
|
214
|
+
it('maps all items from bundle to same messageId', async () => {
|
|
216
215
|
const items = [makeTestEvent('x1'), makeTestEvent('x2'), makeTestEvent('x3')];
|
|
217
216
|
const envelope = makeBundledEnvelope(items);
|
|
218
217
|
const record = makeSqsRecord({ messageBody: envelope }, 'bundle-msg-1');
|
|
219
218
|
const { items: result, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
expect(result).toHaveLength(3);
|
|
220
|
+
expect(recordMap.get(result[0])).toBe('bundle-msg-1');
|
|
221
|
+
expect(recordMap.get(result[1])).toBe('bundle-msg-1');
|
|
222
|
+
expect(recordMap.get(result[2])).toBe('bundle-msg-1');
|
|
224
223
|
});
|
|
225
224
|
});
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
describe('bundled messages (ZSTD compression)', () => {
|
|
226
|
+
it('unbundles ZSTD compressed envelope', async () => {
|
|
228
227
|
const items = [makeTestEvent('z1'), makeTestEvent('z2')];
|
|
229
228
|
const envelope = await makeCompressedEnvelope(items);
|
|
230
229
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
231
230
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
231
|
+
expect(result).toHaveLength(2);
|
|
232
|
+
expect(result[0].eventId).toBe('z1');
|
|
233
|
+
expect(result[1].eventId).toBe('z2');
|
|
234
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
236
235
|
});
|
|
237
|
-
|
|
236
|
+
it('handles large compressed bundles (500 items)', async () => {
|
|
238
237
|
const items = Array.from({ length: 500 }, (_, i) => makeTestEvent(`item-${i}`));
|
|
239
238
|
const envelope = await makeCompressedEnvelope(items);
|
|
240
239
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
241
240
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
241
|
+
expect(result).toHaveLength(500);
|
|
242
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
243
|
+
expect(stats.totalItems).toBe(500);
|
|
245
244
|
});
|
|
246
245
|
});
|
|
247
|
-
|
|
248
|
-
|
|
246
|
+
describe('bundled messages (GZIP compression - CF Worker)', () => {
|
|
247
|
+
it('unbundles GZIP compressed envelope', async () => {
|
|
249
248
|
const items = [makeTestEvent('g1'), makeTestEvent('g2')];
|
|
250
249
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
251
250
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
252
251
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
expect(result).toHaveLength(2);
|
|
253
|
+
expect(result[0].eventId).toBe('g1');
|
|
254
|
+
expect(result[1].eventId).toBe('g2');
|
|
255
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
257
256
|
});
|
|
258
|
-
|
|
257
|
+
it('handles large GZIP compressed bundles (500 items)', async () => {
|
|
259
258
|
const items = Array.from({ length: 500 }, (_, i) => makeTestEvent(`item-${i}`));
|
|
260
259
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
261
260
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
262
261
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
262
|
+
expect(result).toHaveLength(500);
|
|
263
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
264
|
+
expect(stats.totalItems).toBe(500);
|
|
266
265
|
});
|
|
267
|
-
|
|
266
|
+
it('maps all items from GZIP bundle to same messageId', async () => {
|
|
268
267
|
const items = [makeTestEvent('x1'), makeTestEvent('x2'), makeTestEvent('x3')];
|
|
269
268
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
270
269
|
const record = makeSqsRecord({ messageBody: envelope }, 'gzip-bundle-msg-1');
|
|
271
270
|
const { items: result, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
271
|
+
expect(result).toHaveLength(3);
|
|
272
|
+
expect(recordMap.get(result[0])).toBe('gzip-bundle-msg-1');
|
|
273
|
+
expect(recordMap.get(result[1])).toBe('gzip-bundle-msg-1');
|
|
274
|
+
expect(recordMap.get(result[2])).toBe('gzip-bundle-msg-1');
|
|
276
275
|
});
|
|
277
|
-
|
|
276
|
+
it('unbundles GZIP envelope wrapped in full InternalSQSMessage format (CF Worker format)', async () => {
|
|
278
277
|
const items = [makeTestEvent('cf1'), makeTestEvent('cf2'), makeTestEvent('cf3')];
|
|
279
278
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
280
279
|
const internalSqsMessage = {
|
|
@@ -285,18 +284,18 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
285
284
|
};
|
|
286
285
|
const record = makeSqsRecord(internalSqsMessage, 'sqs-msg-id');
|
|
287
286
|
const { items: result, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
287
|
+
expect(result).toHaveLength(3);
|
|
288
|
+
expect(result[0].eventId).toBe('cf1');
|
|
289
|
+
expect(result[1].eventId).toBe('cf2');
|
|
290
|
+
expect(result[2].eventId).toBe('cf3');
|
|
291
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
292
|
+
expect(stats.legacySqsRecords).toBe(0);
|
|
293
|
+
expect(stats.totalItems).toBe(3);
|
|
294
|
+
expect(recordMap.get(result[0])).toBe('sqs-msg-id');
|
|
295
|
+
expect(recordMap.get(result[1])).toBe('sqs-msg-id');
|
|
296
|
+
expect(recordMap.get(result[2])).toBe('sqs-msg-id');
|
|
298
297
|
});
|
|
299
|
-
|
|
298
|
+
it('unbundles GZIP envelope with extra wrapper fields (messageTime, messageType)', async () => {
|
|
300
299
|
const items = [makeTestEvent('w1')];
|
|
301
300
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
302
301
|
const wrappedMessage = {
|
|
@@ -307,11 +306,11 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
307
306
|
};
|
|
308
307
|
const record = makeSqsRecord(wrappedMessage);
|
|
309
308
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
309
|
+
expect(result).toHaveLength(1);
|
|
310
|
+
expect(result[0].eventId).toBe('w1');
|
|
311
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
313
312
|
});
|
|
314
|
-
|
|
313
|
+
it('handles decompression failure gracefully (does not return wrapper)', async () => {
|
|
315
314
|
const corruptedEnvelope = {
|
|
316
315
|
v: 1,
|
|
317
316
|
c: 'gzip',
|
|
@@ -327,16 +326,16 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
327
326
|
};
|
|
328
327
|
const record = makeSqsRecord(internalSqsMessage, 'sqs-record-id');
|
|
329
328
|
const { items, stats, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
329
|
+
expect(failedMessageIds).toHaveLength(1);
|
|
330
|
+
expect(stats.failedRecords).toBe(1);
|
|
331
|
+
expect(items).toHaveLength(0);
|
|
333
332
|
items.forEach((item) => {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
333
|
+
expect(item).not.toHaveProperty('messageTime');
|
|
334
|
+
expect(item).not.toHaveProperty('messageType');
|
|
335
|
+
expect(item).not.toHaveProperty('messageBody');
|
|
337
336
|
});
|
|
338
337
|
});
|
|
339
|
-
|
|
338
|
+
it('verifies decompression failure does NOT leak wrapper into items', async () => {
|
|
340
339
|
const badEnvelope = {
|
|
341
340
|
v: 1,
|
|
342
341
|
c: 'gzip',
|
|
@@ -352,12 +351,12 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
352
351
|
};
|
|
353
352
|
const record = makeSqsRecord(wrapper, 'sqs-msg-id');
|
|
354
353
|
const { items, stats, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
354
|
+
expect(failedMessageIds).toContain('sqs-msg-id');
|
|
355
|
+
expect(stats.failedRecords).toBe(1);
|
|
356
|
+
expect(items).toHaveLength(0);
|
|
357
|
+
expect(stats.totalItems).toBe(0);
|
|
359
358
|
});
|
|
360
|
-
|
|
359
|
+
it('simulates old version without GZIP - returns envelope as item (BUG)', async () => {
|
|
361
360
|
const items = [{ pixelId: 'px123', trackingEvent: { name: 'page_view' } }];
|
|
362
361
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
363
362
|
const wrapper = {
|
|
@@ -366,19 +365,19 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
366
365
|
messageBody: envelope,
|
|
367
366
|
messageId: 'cf-msg-id',
|
|
368
367
|
};
|
|
369
|
-
|
|
368
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(envelope)).toBe(true);
|
|
370
369
|
const record = makeSqsRecord(wrapper, 'sqs-msg-id');
|
|
371
370
|
const { items: result, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
371
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
372
|
+
expect(result).toHaveLength(1);
|
|
373
|
+
expect(result[0].pixelId).toBe('px123');
|
|
374
|
+
expect(result[0]).not.toHaveProperty('v');
|
|
375
|
+
expect(result[0]).not.toHaveProperty('c');
|
|
376
|
+
expect(result[0]).not.toHaveProperty('n');
|
|
377
|
+
expect(result[0]).not.toHaveProperty('p');
|
|
378
|
+
expect(result[0]).not.toHaveProperty('s');
|
|
380
379
|
});
|
|
381
|
-
|
|
380
|
+
it('unknown compression algorithm causes legacy fallback (returns messageBody)', async () => {
|
|
382
381
|
const unknownEnvelope = {
|
|
383
382
|
v: 1,
|
|
384
383
|
c: 'lz4',
|
|
@@ -392,20 +391,20 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
392
391
|
messageBody: unknownEnvelope,
|
|
393
392
|
messageId: 'wrapper-msg-id',
|
|
394
393
|
};
|
|
395
|
-
|
|
394
|
+
expect((0, sqs_unbundle_1.isBundledEnvelope)(unknownEnvelope)).toBe(false);
|
|
396
395
|
const record = makeSqsRecord(wrapper, 'sqs-msg-id');
|
|
397
396
|
const { items, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
397
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
398
|
+
expect(stats.bundledSqsRecords).toBe(0);
|
|
399
|
+
expect(items).toHaveLength(1);
|
|
400
|
+
expect(items[0]).toHaveProperty('v', 1);
|
|
401
|
+
expect(items[0]).toHaveProperty('c', 'lz4');
|
|
402
|
+
expect(items[0]).toHaveProperty('n', 1);
|
|
403
|
+
expect(items[0]).toHaveProperty('p');
|
|
405
404
|
});
|
|
406
405
|
});
|
|
407
|
-
|
|
408
|
-
|
|
406
|
+
describe('mixed message formats', () => {
|
|
407
|
+
it('handles mix of legacy and bundled messages', async () => {
|
|
409
408
|
const legacyEvent = makeTestEvent('legacy-1');
|
|
410
409
|
const bundledItems = [makeTestEvent('bundled-1'), makeTestEvent('bundled-2')];
|
|
411
410
|
const bundleEnvelope = makeBundledEnvelope(bundledItems);
|
|
@@ -414,15 +413,15 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
414
413
|
makeSqsRecord({ messageBody: bundleEnvelope }, 'msg-bundle'),
|
|
415
414
|
];
|
|
416
415
|
const { items, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
416
|
+
expect(items).toHaveLength(3);
|
|
417
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
418
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
419
|
+
expect(stats.totalItems).toBe(3);
|
|
420
|
+
expect(recordMap.get(items[0])).toBe('msg-legacy');
|
|
421
|
+
expect(recordMap.get(items[1])).toBe('msg-bundle');
|
|
422
|
+
expect(recordMap.get(items[2])).toBe('msg-bundle');
|
|
424
423
|
});
|
|
425
|
-
|
|
424
|
+
it('handles mix of NONE and ZSTD compressed bundles', async () => {
|
|
426
425
|
const noneItems = [makeTestEvent('none-1')];
|
|
427
426
|
const zstdItems = [makeTestEvent('zstd-1'), makeTestEvent('zstd-2')];
|
|
428
427
|
const noneEnvelope = makeBundledEnvelope(noneItems);
|
|
@@ -432,11 +431,11 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
432
431
|
makeSqsRecord({ messageBody: zstdEnvelope }, 'msg-zstd'),
|
|
433
432
|
];
|
|
434
433
|
const { items, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
434
|
+
expect(items).toHaveLength(3);
|
|
435
|
+
expect(stats.bundledSqsRecords).toBe(2);
|
|
436
|
+
expect(stats.totalItems).toBe(3);
|
|
438
437
|
});
|
|
439
|
-
|
|
438
|
+
it('handles mix of ZSTD, GZIP, and legacy messages', async () => {
|
|
440
439
|
const legacyEvent = makeTestEvent('legacy-1');
|
|
441
440
|
const zstdItems = [makeTestEvent('zstd-1'), makeTestEvent('zstd-2')];
|
|
442
441
|
const gzipItems = [makeTestEvent('gzip-1'), makeTestEvent('gzip-2'), makeTestEvent('gzip-3')];
|
|
@@ -448,29 +447,29 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
448
447
|
makeSqsRecord({ messageBody: gzipEnvelope }, 'msg-gzip'),
|
|
449
448
|
];
|
|
450
449
|
const { items, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
450
|
+
expect(items).toHaveLength(6);
|
|
451
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
452
|
+
expect(stats.bundledSqsRecords).toBe(2);
|
|
453
|
+
expect(stats.totalItems).toBe(6);
|
|
454
|
+
expect(recordMap.get(items[0])).toBe('msg-legacy');
|
|
455
|
+
expect(recordMap.get(items[1])).toBe('msg-zstd');
|
|
456
|
+
expect(recordMap.get(items[2])).toBe('msg-zstd');
|
|
457
|
+
expect(recordMap.get(items[3])).toBe('msg-gzip');
|
|
458
|
+
expect(recordMap.get(items[4])).toBe('msg-gzip');
|
|
459
|
+
expect(recordMap.get(items[5])).toBe('msg-gzip');
|
|
461
460
|
});
|
|
462
461
|
});
|
|
463
|
-
|
|
464
|
-
|
|
462
|
+
describe('error handling', () => {
|
|
463
|
+
it('returns failed messageId for invalid JSON', async () => {
|
|
465
464
|
const records = [makeSqsRecord('not-valid-json{{{', 'msg-bad'), makeSqsRecord(makeTestEvent('good'), 'msg-good')];
|
|
466
465
|
const { items, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
466
|
+
expect(items).toHaveLength(1);
|
|
467
|
+
expect(items[0].eventId).toBe('good');
|
|
468
|
+
expect(failedMessageIds).toEqual(['msg-bad']);
|
|
469
|
+
expect(stats.failedRecords).toBe(1);
|
|
470
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
472
471
|
});
|
|
473
|
-
|
|
472
|
+
it('returns failed messageId for corrupt ZSTD compressed data', async () => {
|
|
474
473
|
const corruptEnvelope = {
|
|
475
474
|
v: 1,
|
|
476
475
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
|
|
@@ -482,12 +481,12 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
482
481
|
makeSqsRecord(makeTestEvent('valid'), 'msg-valid'),
|
|
483
482
|
];
|
|
484
483
|
const { items, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
484
|
+
expect(items).toHaveLength(1);
|
|
485
|
+
expect(items[0].eventId).toBe('valid');
|
|
486
|
+
expect(failedMessageIds).toContain('msg-corrupt');
|
|
487
|
+
expect(stats.failedRecords).toBe(1);
|
|
489
488
|
});
|
|
490
|
-
|
|
489
|
+
it('returns failed messageId for corrupt GZIP compressed data', async () => {
|
|
491
490
|
const corruptEnvelope = {
|
|
492
491
|
v: 1,
|
|
493
492
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.GZIP,
|
|
@@ -499,27 +498,27 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
499
498
|
makeSqsRecord(makeTestEvent('valid'), 'msg-valid'),
|
|
500
499
|
];
|
|
501
500
|
const { items, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
501
|
+
expect(items).toHaveLength(1);
|
|
502
|
+
expect(items[0].eventId).toBe('valid');
|
|
503
|
+
expect(failedMessageIds).toContain('msg-corrupt-gzip');
|
|
504
|
+
expect(stats.failedRecords).toBe(1);
|
|
506
505
|
});
|
|
507
|
-
|
|
506
|
+
it('returns empty result for all failed records', async () => {
|
|
508
507
|
const records = [makeSqsRecord('invalid-1', 'msg-1'), makeSqsRecord('invalid-2', 'msg-2')];
|
|
509
508
|
const { items, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
509
|
+
expect(items).toHaveLength(0);
|
|
510
|
+
expect(failedMessageIds).toEqual(['msg-1', 'msg-2']);
|
|
511
|
+
expect(stats.failedRecords).toBe(2);
|
|
512
|
+
expect(stats.totalItems).toBe(0);
|
|
514
513
|
});
|
|
515
|
-
|
|
514
|
+
it('handles empty records array', async () => {
|
|
516
515
|
const { items, failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)([]);
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
516
|
+
expect(items).toHaveLength(0);
|
|
517
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
518
|
+
expect(stats.totalRecords).toBe(0);
|
|
519
|
+
expect(stats.totalItems).toBe(0);
|
|
521
520
|
});
|
|
522
|
-
|
|
521
|
+
it('rejects ZSTD payload exceeding max decompressed size', async () => {
|
|
523
522
|
const largeItems = Array.from({ length: 1000 }, (_, i) => ({
|
|
524
523
|
id: `item-${i}`,
|
|
525
524
|
data: 'x'.repeat(1000),
|
|
@@ -529,10 +528,10 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
529
528
|
const { failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
530
529
|
maxDecompressedSizeBytes: 100 * 1024,
|
|
531
530
|
});
|
|
532
|
-
|
|
533
|
-
|
|
531
|
+
expect(failedMessageIds).toContain('msg-too-large');
|
|
532
|
+
expect(stats.failedRecords).toBe(1);
|
|
534
533
|
});
|
|
535
|
-
|
|
534
|
+
it('rejects GZIP payload exceeding max decompressed size (post-decompress check)', async () => {
|
|
536
535
|
const largeItems = Array.from({ length: 1000 }, (_, i) => ({
|
|
537
536
|
id: `item-${i}`,
|
|
538
537
|
data: 'x'.repeat(1000),
|
|
@@ -542,10 +541,10 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
542
541
|
const { failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
543
542
|
maxDecompressedSizeBytes: 100 * 1024,
|
|
544
543
|
});
|
|
545
|
-
|
|
546
|
-
|
|
544
|
+
expect(failedMessageIds).toContain('msg-too-large-gzip');
|
|
545
|
+
expect(stats.failedRecords).toBe(1);
|
|
547
546
|
});
|
|
548
|
-
|
|
547
|
+
it('fails on invalid base64 in compressed payload', async () => {
|
|
549
548
|
const badEnvelope = {
|
|
550
549
|
v: 1,
|
|
551
550
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
|
|
@@ -555,11 +554,11 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
555
554
|
};
|
|
556
555
|
const record = makeSqsRecord({ messageBody: badEnvelope }, 'msg-bad-base64');
|
|
557
556
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
558
|
-
|
|
557
|
+
expect(failedMessageIds).toContain('msg-bad-base64');
|
|
559
558
|
});
|
|
560
559
|
});
|
|
561
|
-
|
|
562
|
-
|
|
560
|
+
describe('bundle format edge cases', () => {
|
|
561
|
+
it('successfully unbundles even when n does not match actual item count', async () => {
|
|
563
562
|
const envelope = {
|
|
564
563
|
v: 1,
|
|
565
564
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.NONE,
|
|
@@ -569,54 +568,54 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
569
568
|
};
|
|
570
569
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
571
570
|
const { items } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
572
|
-
|
|
571
|
+
expect(items).toHaveLength(2);
|
|
573
572
|
});
|
|
574
|
-
|
|
573
|
+
it('treats envelope with unsupported version as legacy message', async () => {
|
|
575
574
|
const badEnvelope = { v: 99, c: 'none', n: 1, s: 10, p: [] };
|
|
576
575
|
const record = makeSqsRecord({ messageBody: badEnvelope }, 'msg-bad-version');
|
|
577
576
|
const { items, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
577
|
+
expect(items).toHaveLength(1);
|
|
578
|
+
expect(items[0].v).toBe(99);
|
|
579
|
+
expect(stats.legacySqsRecords).toBe(1);
|
|
580
|
+
expect(stats.bundledSqsRecords).toBe(0);
|
|
582
581
|
});
|
|
583
582
|
});
|
|
584
|
-
|
|
585
|
-
|
|
583
|
+
describe('timeout protection', () => {
|
|
584
|
+
it('respects timeoutMs option for ZSTD', async () => {
|
|
586
585
|
const items = [makeTestEvent('1')];
|
|
587
586
|
const envelope = await makeCompressedEnvelope(items);
|
|
588
587
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
589
588
|
const { items: result, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
590
589
|
timeoutMs: 5000,
|
|
591
590
|
});
|
|
592
|
-
|
|
593
|
-
|
|
591
|
+
expect(result).toHaveLength(1);
|
|
592
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
594
593
|
});
|
|
595
|
-
|
|
594
|
+
it('respects timeoutMs option for GZIP', async () => {
|
|
596
595
|
const items = [makeTestEvent('1')];
|
|
597
596
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
598
597
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
599
598
|
const { items: result, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
600
599
|
timeoutMs: 5000,
|
|
601
600
|
});
|
|
602
|
-
|
|
603
|
-
|
|
601
|
+
expect(result).toHaveLength(1);
|
|
602
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
604
603
|
});
|
|
605
|
-
|
|
604
|
+
it('passes timeoutMs through to decompression', async () => {
|
|
606
605
|
const items = [makeTestEvent('1')];
|
|
607
606
|
const envelope = await makeCompressedEnvelope(items);
|
|
608
607
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
609
|
-
await
|
|
608
|
+
await expect((0, sqs_unbundle_1.unbundleRecords)([record], { timeoutMs: 30000 })).resolves.toBeDefined();
|
|
610
609
|
});
|
|
611
|
-
|
|
610
|
+
it('CompressionTimeoutError is properly exported', () => {
|
|
612
611
|
const error = new compression_1.CompressionTimeoutError(compression_1.CompressionOperation.DECOMPRESS, 5000);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
612
|
+
expect(error).toBeInstanceOf(Error);
|
|
613
|
+
expect(error.name).toBe('CompressionTimeoutError');
|
|
614
|
+
expect(error.operation).toBe('decompress');
|
|
615
|
+
expect(error.timeoutMs).toBe(5000);
|
|
616
|
+
expect(error.message).toContain('timed out after 5000ms');
|
|
618
617
|
});
|
|
619
|
-
|
|
618
|
+
it('includes timeout info in failure logging for ZSTD', async () => {
|
|
620
619
|
const corruptEnvelope = {
|
|
621
620
|
v: 1,
|
|
622
621
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.ZSTD,
|
|
@@ -628,9 +627,9 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
628
627
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
629
628
|
timeoutMs: 5000,
|
|
630
629
|
});
|
|
631
|
-
|
|
630
|
+
expect(failedMessageIds).toContain('msg-timeout-test');
|
|
632
631
|
});
|
|
633
|
-
|
|
632
|
+
it('includes timeout info in failure logging for GZIP', async () => {
|
|
634
633
|
const corruptEnvelope = {
|
|
635
634
|
v: 1,
|
|
636
635
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.GZIP,
|
|
@@ -642,27 +641,27 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
642
641
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
643
642
|
timeoutMs: 5000,
|
|
644
643
|
});
|
|
645
|
-
|
|
644
|
+
expect(failedMessageIds).toContain('msg-gzip-timeout-test');
|
|
646
645
|
});
|
|
647
646
|
});
|
|
648
|
-
|
|
649
|
-
|
|
647
|
+
describe('end-to-end: producer bundle → consumer unbundle', () => {
|
|
648
|
+
it('simulates full bundle → unbundle flow with compression', async () => {
|
|
650
649
|
const producerItems = Array.from({ length: 100 }, (_, i) => makeTestEvent(`event-${i}`, 'page_view', i * 1.5));
|
|
651
650
|
const envelope = await makeCompressedEnvelope(producerItems, 3);
|
|
652
651
|
const sqsMessageBody = { messageBody: envelope };
|
|
653
652
|
const consumerRecord = makeSqsRecord(sqsMessageBody, 'sqs-message-id-123');
|
|
654
653
|
const { items, recordMap, stats } = await (0, sqs_unbundle_1.unbundleRecords)([consumerRecord]);
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
654
|
+
expect(items).toHaveLength(100);
|
|
655
|
+
expect(items[0]).toEqual({ eventId: 'event-0', name: 'page_view', value: 0 });
|
|
656
|
+
expect(items[99]).toEqual({ eventId: 'event-99', name: 'page_view', value: 148.5 });
|
|
657
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
658
|
+
expect(stats.legacySqsRecords).toBe(0);
|
|
659
|
+
expect(stats.totalItems).toBe(100);
|
|
661
660
|
for (const item of items) {
|
|
662
|
-
|
|
661
|
+
expect(recordMap.get(item)).toBe('sqs-message-id-123');
|
|
663
662
|
}
|
|
664
663
|
});
|
|
665
|
-
|
|
664
|
+
it('simulates mixed batch with legacy and bundled messages', async () => {
|
|
666
665
|
const legacyRecord1 = makeSqsRecord({ messageBody: makeTestEvent('legacy-1', 'purchase', 99.99) }, 'legacy-msg-1');
|
|
667
666
|
const legacyRecord2 = makeSqsRecord(makeTestEvent('legacy-2', 'add_to_cart', 29.99), 'legacy-msg-2');
|
|
668
667
|
const bundledItems = [
|
|
@@ -674,19 +673,19 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
674
673
|
const bundledRecord = makeSqsRecord({ messageBody: envelope }, 'bundled-msg-1');
|
|
675
674
|
const records = [legacyRecord1, bundledRecord, legacyRecord2];
|
|
676
675
|
const { items, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
676
|
+
expect(items).toHaveLength(5);
|
|
677
|
+
expect(stats.legacySqsRecords).toBe(2);
|
|
678
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
679
|
+
expect(stats.totalItems).toBe(5);
|
|
680
|
+
expect(recordMap.get(items[0])).toBe('legacy-msg-1');
|
|
681
|
+
expect(recordMap.get(items[1])).toBe('bundled-msg-1');
|
|
682
|
+
expect(recordMap.get(items[2])).toBe('bundled-msg-1');
|
|
683
|
+
expect(recordMap.get(items[3])).toBe('bundled-msg-1');
|
|
684
|
+
expect(recordMap.get(items[4])).toBe('legacy-msg-2');
|
|
686
685
|
});
|
|
687
686
|
});
|
|
688
|
-
|
|
689
|
-
|
|
687
|
+
describe('consumer edge cases - real sequences', () => {
|
|
688
|
+
it('handles 500 items in single compressed bundle with exact verification', async () => {
|
|
690
689
|
const originalItems = Array.from({ length: 500 }, (_, i) => ({
|
|
691
690
|
id: `item-${i}`,
|
|
692
691
|
name: `Event ${i}`,
|
|
@@ -696,21 +695,21 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
696
695
|
const envelope = await makeCompressedEnvelope(originalItems);
|
|
697
696
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-500-items');
|
|
698
697
|
const { items, recordMap, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
698
|
+
expect(items).toHaveLength(500);
|
|
699
|
+
expect(items[0]).toEqual(originalItems[0]);
|
|
700
|
+
expect(items[249]).toEqual(originalItems[249]);
|
|
701
|
+
expect(items[499]).toEqual(originalItems[499]);
|
|
702
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
703
|
+
expect(stats.totalItems).toBe(500);
|
|
705
704
|
for (let i = 0; i < 500; i++) {
|
|
706
|
-
|
|
707
|
-
|
|
705
|
+
expect(items[i].id).toBe(`item-${i}`);
|
|
706
|
+
expect(items[i].data.nested.value).toBe(i * 1.5);
|
|
708
707
|
}
|
|
709
708
|
for (const item of items) {
|
|
710
|
-
|
|
709
|
+
expect(recordMap.get(item)).toBe('msg-500-items');
|
|
711
710
|
}
|
|
712
711
|
});
|
|
713
|
-
|
|
712
|
+
it('handles multiple bundles in single batch with different item counts', async () => {
|
|
714
713
|
const counts = [10, 50, 100, 200, 300];
|
|
715
714
|
const records = [];
|
|
716
715
|
const expectedTotal = counts.reduce((sum, c) => sum + c, 0);
|
|
@@ -725,24 +724,24 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
725
724
|
records.push(makeSqsRecord({ messageBody: envelope }, `msg-bundle-${bundleIdx}`));
|
|
726
725
|
}
|
|
727
726
|
const { items, recordMap, stats } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
727
|
+
expect(items).toHaveLength(expectedTotal);
|
|
728
|
+
expect(stats.totalItems).toBe(expectedTotal);
|
|
729
|
+
expect(stats.bundledSqsRecords).toBe(5);
|
|
730
|
+
expect(stats.legacySqsRecords).toBe(0);
|
|
731
|
+
expect(stats.failedRecords).toBe(0);
|
|
733
732
|
const itemsByBundle = new Map();
|
|
734
733
|
for (const item of items) {
|
|
735
734
|
const expectedMsgId = `msg-bundle-${item.bundleId}`;
|
|
736
|
-
|
|
735
|
+
expect(recordMap.get(item)).toBe(expectedMsgId);
|
|
737
736
|
itemsByBundle.set(item.bundleId, (itemsByBundle.get(item.bundleId) ?? 0) + 1);
|
|
738
737
|
}
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
738
|
+
expect(itemsByBundle.get(0)).toBe(10);
|
|
739
|
+
expect(itemsByBundle.get(1)).toBe(50);
|
|
740
|
+
expect(itemsByBundle.get(2)).toBe(100);
|
|
741
|
+
expect(itemsByBundle.get(3)).toBe(200);
|
|
742
|
+
expect(itemsByBundle.get(4)).toBe(300);
|
|
744
743
|
});
|
|
745
|
-
|
|
744
|
+
it('handles realistic 80% bundled / 20% legacy migration ratio', async () => {
|
|
746
745
|
const records = [];
|
|
747
746
|
const totalMessages = 100;
|
|
748
747
|
const bundledCount = 80;
|
|
@@ -767,24 +766,24 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
767
766
|
}
|
|
768
767
|
const shuffled = [...records].sort(() => Math.random() - 0.5);
|
|
769
768
|
const { items, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)(shuffled);
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
769
|
+
expect(stats.totalRecords).toBe(totalMessages);
|
|
770
|
+
expect(stats.bundledSqsRecords).toBe(bundledCount);
|
|
771
|
+
expect(stats.legacySqsRecords).toBe(legacyCount);
|
|
772
|
+
expect(stats.failedRecords).toBe(0);
|
|
773
|
+
expect(items).toHaveLength(bundledCount * itemsPerBundle + legacyCount);
|
|
774
|
+
expect(stats.totalItems).toBe(2020);
|
|
776
775
|
const bundledItems = items.filter((i) => i.type === 'bundled');
|
|
777
776
|
const legacyItems = items.filter((i) => i.type === 'legacy');
|
|
778
|
-
|
|
779
|
-
|
|
777
|
+
expect(bundledItems).toHaveLength(bundledCount * itemsPerBundle);
|
|
778
|
+
expect(legacyItems).toHaveLength(legacyCount);
|
|
780
779
|
for (const item of bundledItems) {
|
|
781
|
-
|
|
780
|
+
expect(recordMap.get(item)).toBe(`msg-bundled-${item.bundleIdx}`);
|
|
782
781
|
}
|
|
783
782
|
for (const item of legacyItems) {
|
|
784
|
-
|
|
783
|
+
expect(recordMap.get(item)).toBe(`msg-legacy-${item.legacyIdx}`);
|
|
785
784
|
}
|
|
786
785
|
});
|
|
787
|
-
|
|
786
|
+
it('preserves Unicode characters through ZSTD compression', async () => {
|
|
788
787
|
const unicodeItems = [
|
|
789
788
|
{
|
|
790
789
|
id: 'emoji',
|
|
@@ -840,17 +839,17 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
840
839
|
const envelope = await makeCompressedEnvelope(unicodeItems);
|
|
841
840
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-unicode');
|
|
842
841
|
const { items } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
843
|
-
|
|
842
|
+
expect(items).toHaveLength(unicodeItems.length);
|
|
844
843
|
for (let i = 0; i < unicodeItems.length; i++) {
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
844
|
+
expect(items[i].id).toBe(unicodeItems[i].id);
|
|
845
|
+
expect(items[i].content).toBe(unicodeItems[i].content);
|
|
846
|
+
expect(items[i].description).toBe(unicodeItems[i].description);
|
|
848
847
|
const originalBytes = Buffer.from(unicodeItems[i].content, 'utf8');
|
|
849
848
|
const recoveredBytes = Buffer.from(items[i].content, 'utf8');
|
|
850
|
-
|
|
849
|
+
expect(recoveredBytes.equals(originalBytes)).toBe(true);
|
|
851
850
|
}
|
|
852
851
|
});
|
|
853
|
-
|
|
852
|
+
it('preserves deeply nested structures (10 levels)', async () => {
|
|
854
853
|
function createDeepStructure(depth, maxDepth = 10) {
|
|
855
854
|
const node = {
|
|
856
855
|
level: depth,
|
|
@@ -873,16 +872,16 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
873
872
|
const envelope = await makeCompressedEnvelope(deepItems);
|
|
874
873
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-deep');
|
|
875
874
|
const { items } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
876
|
-
|
|
875
|
+
expect(items).toHaveLength(10);
|
|
877
876
|
for (let i = 0; i < 10; i++) {
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
877
|
+
expect(JSON.stringify(items[i])).toBe(JSON.stringify(deepItems[i]));
|
|
878
|
+
expect(items[i].nested.level).toBe(0);
|
|
879
|
+
expect(items[i].nested.child?.level).toBe(1);
|
|
880
|
+
expect(items[i].nested.child?.child?.child?.level).toBe(3);
|
|
881
|
+
expect(items[i].arrays[0][0][0][0][0][0]).toBe('deeply');
|
|
883
882
|
}
|
|
884
883
|
});
|
|
885
|
-
|
|
884
|
+
it('handles binary-like string data (base64 encoded)', async () => {
|
|
886
885
|
const binaryItems = [
|
|
887
886
|
{
|
|
888
887
|
id: 'small-binary',
|
|
@@ -913,16 +912,16 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
913
912
|
const envelope = await makeCompressedEnvelope(binaryItems);
|
|
914
913
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-binary');
|
|
915
914
|
const { items } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
916
|
-
|
|
915
|
+
expect(items).toHaveLength(binaryItems.length);
|
|
917
916
|
for (let i = 0; i < binaryItems.length; i++) {
|
|
918
|
-
|
|
919
|
-
|
|
917
|
+
expect(items[i].id).toBe(binaryItems[i].id);
|
|
918
|
+
expect(items[i].base64Data).toBe(binaryItems[i].base64Data);
|
|
920
919
|
const originalDecoded = Buffer.from(binaryItems[i].base64Data, 'base64');
|
|
921
920
|
const recoveredDecoded = Buffer.from(items[i].base64Data, 'base64');
|
|
922
|
-
|
|
921
|
+
expect(recoveredDecoded.equals(originalDecoded)).toBe(true);
|
|
923
922
|
}
|
|
924
923
|
});
|
|
925
|
-
|
|
924
|
+
it('handles concurrent unbundling stress test (100 records in parallel)', async () => {
|
|
926
925
|
const recordCount = 100;
|
|
927
926
|
const records = [];
|
|
928
927
|
for (let i = 0; i < recordCount; i++) {
|
|
@@ -940,24 +939,24 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
940
939
|
const startTime = Date.now();
|
|
941
940
|
const { items, recordMap, stats, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
942
941
|
const duration = Date.now() - startTime;
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
942
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
943
|
+
expect(stats.failedRecords).toBe(0);
|
|
944
|
+
expect(stats.bundledSqsRecords).toBe(recordCount);
|
|
946
945
|
const seenUniqueIds = new Set();
|
|
947
946
|
for (const item of items) {
|
|
948
|
-
|
|
947
|
+
expect(seenUniqueIds.has(item.uniqueId)).toBe(false);
|
|
949
948
|
seenUniqueIds.add(item.uniqueId);
|
|
950
949
|
const expectedMsgId = `stress-msg-${item.recordIdx}`;
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
950
|
+
expect(recordMap.get(item)).toBe(expectedMsgId);
|
|
951
|
+
expect(item.itemIdx).toBeGreaterThanOrEqual(0);
|
|
952
|
+
expect(item.itemIdx).toBeLessThan(30);
|
|
954
953
|
}
|
|
955
954
|
const expectedTotal = Array.from({ length: recordCount }, (_, i) => 10 + (i % 20)).reduce((a, b) => a + b, 0);
|
|
956
|
-
|
|
957
|
-
|
|
955
|
+
expect(items).toHaveLength(expectedTotal);
|
|
956
|
+
expect(stats.totalItems).toBe(expectedTotal);
|
|
958
957
|
console.log(`Unbundled ${recordCount} records (${stats.totalItems} items) in ${duration}ms`);
|
|
959
958
|
});
|
|
960
|
-
|
|
959
|
+
it('handles items with all JSON primitive types', async () => {
|
|
961
960
|
const primitiveItems = [
|
|
962
961
|
{
|
|
963
962
|
id: 'primitives',
|
|
@@ -991,10 +990,10 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
991
990
|
const envelope = await makeCompressedEnvelope(primitiveItems);
|
|
992
991
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-primitives');
|
|
993
992
|
const { items } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
994
|
-
|
|
995
|
-
|
|
993
|
+
expect(items).toHaveLength(3);
|
|
994
|
+
expect(JSON.stringify(items)).toBe(JSON.stringify(primitiveItems));
|
|
996
995
|
});
|
|
997
|
-
|
|
996
|
+
it('maintains item order across multiple bundles', async () => {
|
|
998
997
|
const records = [];
|
|
999
998
|
let globalIdx = 0;
|
|
1000
999
|
for (let bundleIdx = 0; bundleIdx < 10; bundleIdx++) {
|
|
@@ -1016,29 +1015,29 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1016
1015
|
}
|
|
1017
1016
|
for (const [, orders] of bundleGroups) {
|
|
1018
1017
|
for (let i = 1; i < orders.length; i++) {
|
|
1019
|
-
|
|
1018
|
+
expect(orders[i]).toBeGreaterThan(orders[i - 1]);
|
|
1020
1019
|
}
|
|
1021
1020
|
}
|
|
1022
1021
|
});
|
|
1023
|
-
|
|
1022
|
+
it('handles edge case: single item bundles', async () => {
|
|
1024
1023
|
const records = await Promise.all(Array.from({ length: 50 }, async (_, i) => {
|
|
1025
1024
|
const items = [{ id: `single-${i}`, value: i }];
|
|
1026
1025
|
const envelope = await makeCompressedEnvelope(items);
|
|
1027
1026
|
return makeSqsRecord({ messageBody: envelope }, `single-msg-${i}`);
|
|
1028
1027
|
}));
|
|
1029
1028
|
const { items, stats, recordMap } = await (0, sqs_unbundle_1.unbundleRecords)(records);
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1029
|
+
expect(items).toHaveLength(50);
|
|
1030
|
+
expect(stats.bundledSqsRecords).toBe(50);
|
|
1031
|
+
expect(stats.totalItems).toBe(50);
|
|
1033
1032
|
for (let i = 0; i < 50; i++) {
|
|
1034
1033
|
const item = items.find((x) => x.value === i);
|
|
1035
|
-
|
|
1034
|
+
expect(item).toBeDefined();
|
|
1036
1035
|
if (!item)
|
|
1037
1036
|
throw new Error(`Expected item with value ${i} to be found`);
|
|
1038
|
-
|
|
1037
|
+
expect(recordMap.get(item)).toMatch(/single-msg-\d+/);
|
|
1039
1038
|
}
|
|
1040
1039
|
});
|
|
1041
|
-
|
|
1040
|
+
it('handles edge case: empty arrays in bundles', async () => {
|
|
1042
1041
|
const emptyEnvelope = {
|
|
1043
1042
|
v: 1,
|
|
1044
1043
|
c: sqs_bundled_client_types_1.CompressionAlgorithm.NONE,
|
|
@@ -1047,14 +1046,14 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1047
1046
|
};
|
|
1048
1047
|
const record = makeSqsRecord({ messageBody: emptyEnvelope }, 'msg-empty');
|
|
1049
1048
|
const { items, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1049
|
+
expect(items).toHaveLength(0);
|
|
1050
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
1051
|
+
expect(stats.totalItems).toBe(0);
|
|
1053
1052
|
});
|
|
1054
1053
|
});
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1054
|
+
describe('GZIP comprehensive tests', () => {
|
|
1055
|
+
describe('GZIP pre-decompression bomb protection', () => {
|
|
1056
|
+
it('rejects GZIP with fake ISIZE claiming huge size BEFORE decompression starts', async () => {
|
|
1058
1057
|
const gzipHeader = Buffer.from([0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03]);
|
|
1059
1058
|
const emptyDeflate = Buffer.from([0x03, 0x00]);
|
|
1060
1059
|
const crc32 = Buffer.from([0x00, 0x00, 0x00, 0x00]);
|
|
@@ -1073,20 +1072,20 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1073
1072
|
const { failedMessageIds, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
1074
1073
|
maxDecompressedSizeBytes: 10 * 1024 * 1024,
|
|
1075
1074
|
});
|
|
1076
|
-
|
|
1077
|
-
|
|
1075
|
+
expect(failedMessageIds).toContain('msg-gzip-bomb');
|
|
1076
|
+
expect(stats.failedRecords).toBe(1);
|
|
1078
1077
|
});
|
|
1079
|
-
|
|
1078
|
+
it('allows GZIP with ISIZE within limit', async () => {
|
|
1080
1079
|
const items = [makeTestEvent('valid-1')];
|
|
1081
1080
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
1082
1081
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-gzip-valid');
|
|
1083
1082
|
const { items: result, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
1084
1083
|
maxDecompressedSizeBytes: 10 * 1024 * 1024,
|
|
1085
1084
|
});
|
|
1086
|
-
|
|
1087
|
-
|
|
1085
|
+
expect(result).toHaveLength(1);
|
|
1086
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
1088
1087
|
});
|
|
1089
|
-
|
|
1088
|
+
it('pre-check catches bomb even when ISIZE is exactly at limit + 1', async () => {
|
|
1090
1089
|
const limit = 1000;
|
|
1091
1090
|
const gzipHeader = Buffer.from([0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03]);
|
|
1092
1091
|
const emptyDeflate = Buffer.from([0x03, 0x00]);
|
|
@@ -1106,21 +1105,21 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1106
1105
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
1107
1106
|
maxDecompressedSizeBytes: limit,
|
|
1108
1107
|
});
|
|
1109
|
-
|
|
1108
|
+
expect(failedMessageIds).toContain('msg-boundary-bomb');
|
|
1110
1109
|
});
|
|
1111
1110
|
});
|
|
1112
|
-
|
|
1113
|
-
|
|
1111
|
+
describe('empty GZIP bundle', () => {
|
|
1112
|
+
it('unbundles empty GZIP compressed array', async () => {
|
|
1114
1113
|
const envelope = await makeGzipCompressedEnvelope([]);
|
|
1115
1114
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-empty-gzip');
|
|
1116
1115
|
const { items, stats } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1116
|
+
expect(items).toHaveLength(0);
|
|
1117
|
+
expect(stats.bundledSqsRecords).toBe(1);
|
|
1118
|
+
expect(stats.totalItems).toBe(0);
|
|
1120
1119
|
});
|
|
1121
1120
|
});
|
|
1122
|
-
|
|
1123
|
-
|
|
1121
|
+
describe('Unicode characters in GZIP payload', () => {
|
|
1122
|
+
it('preserves emoji through GZIP compression', async () => {
|
|
1124
1123
|
const items = [
|
|
1125
1124
|
{ eventId: 'emoji-1', content: '🎉🚀💻🌍✨' },
|
|
1126
1125
|
{ eventId: 'emoji-2', content: '👋🏽👨👩👧👦🏳️🌈' },
|
|
@@ -1128,11 +1127,11 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1128
1127
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
1129
1128
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
1130
1129
|
const { items: result } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1130
|
+
expect(result).toHaveLength(2);
|
|
1131
|
+
expect(result[0].content).toBe('🎉🚀💻🌍✨');
|
|
1132
|
+
expect(result[1].content).toBe('👋🏽👨👩👧👦🏳️🌈');
|
|
1134
1133
|
});
|
|
1135
|
-
|
|
1134
|
+
it('preserves CJK characters through GZIP compression', async () => {
|
|
1136
1135
|
const items = [
|
|
1137
1136
|
{ eventId: 'cjk-1', content: '中文测试:欢迎使用' },
|
|
1138
1137
|
{ eventId: 'cjk-2', content: 'こんにちは世界 ひらがな カタカナ' },
|
|
@@ -1141,12 +1140,12 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1141
1140
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
1142
1141
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
1143
1142
|
const { items: result } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1143
|
+
expect(result).toHaveLength(3);
|
|
1144
|
+
expect(result[0].content).toBe('中文测试:欢迎使用');
|
|
1145
|
+
expect(result[1].content).toBe('こんにちは世界 ひらがな カタカナ');
|
|
1146
|
+
expect(result[2].content).toBe('안녕하세요 세계');
|
|
1148
1147
|
});
|
|
1149
|
-
|
|
1148
|
+
it('preserves special characters and mixed scripts through GZIP compression', async () => {
|
|
1150
1149
|
const items = [
|
|
1151
1150
|
{ eventId: 'special-1', content: '∑∫∂∇ε → ∞ × ∈ ⊆ ∀∃' },
|
|
1152
1151
|
{ eventId: 'special-2', content: 'العربية: مرحبا بكم' },
|
|
@@ -1156,17 +1155,17 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1156
1155
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
1157
1156
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
1158
1157
|
const { items: result } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1159
|
-
|
|
1158
|
+
expect(result).toHaveLength(4);
|
|
1160
1159
|
for (let i = 0; i < items.length; i++) {
|
|
1161
|
-
|
|
1160
|
+
expect(result[i].content).toBe(items[i].content);
|
|
1162
1161
|
const originalBytes = Buffer.from(items[i].content, 'utf8');
|
|
1163
1162
|
const recoveredBytes = Buffer.from(result[i].content, 'utf8');
|
|
1164
|
-
|
|
1163
|
+
expect(recoveredBytes.equals(originalBytes)).toBe(true);
|
|
1165
1164
|
}
|
|
1166
1165
|
});
|
|
1167
1166
|
});
|
|
1168
|
-
|
|
1169
|
-
|
|
1167
|
+
describe('GZIP with invalid magic bytes', () => {
|
|
1168
|
+
it('fails gracefully for buffer with wrong magic bytes', async () => {
|
|
1170
1169
|
const wrongMagic = Buffer.from([0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03]);
|
|
1171
1170
|
const filler = Buffer.alloc(10);
|
|
1172
1171
|
const invalidGzip = Buffer.concat([wrongMagic, filler]);
|
|
@@ -1180,9 +1179,9 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1180
1179
|
};
|
|
1181
1180
|
const record = makeSqsRecord({ messageBody: badEnvelope }, 'msg-wrong-magic');
|
|
1182
1181
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1183
|
-
|
|
1182
|
+
expect(failedMessageIds).toContain('msg-wrong-magic');
|
|
1184
1183
|
});
|
|
1185
|
-
|
|
1184
|
+
it('fails gracefully for buffer starting with valid magic but corrupted data', async () => {
|
|
1186
1185
|
const validMagic = Buffer.from([0x1f, 0x8b]);
|
|
1187
1186
|
const garbage = Buffer.from('this is not valid gzip data after magic');
|
|
1188
1187
|
const invalidGzip = Buffer.concat([validMagic, garbage]);
|
|
@@ -1196,25 +1195,25 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1196
1195
|
};
|
|
1197
1196
|
const record = makeSqsRecord({ messageBody: badEnvelope }, 'msg-corrupt-gzip');
|
|
1198
1197
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1199
|
-
|
|
1198
|
+
expect(failedMessageIds).toContain('msg-corrupt-gzip');
|
|
1200
1199
|
});
|
|
1201
1200
|
});
|
|
1202
|
-
|
|
1203
|
-
|
|
1201
|
+
describe('GZIP minimum size edge cases', () => {
|
|
1202
|
+
it('handles buffer exactly 18 bytes (minimum valid)', async () => {
|
|
1204
1203
|
const minBuffer = Buffer.alloc(18);
|
|
1205
1204
|
minBuffer[0] = 0x1f;
|
|
1206
1205
|
minBuffer[1] = 0x8b;
|
|
1207
1206
|
const size = (0, compression_1.getGzipUncompressedSize)(minBuffer);
|
|
1208
|
-
|
|
1207
|
+
expect(size).toBe(0);
|
|
1209
1208
|
});
|
|
1210
|
-
|
|
1209
|
+
it('returns undefined for buffer exactly 17 bytes (too small)', async () => {
|
|
1211
1210
|
const tooSmall = Buffer.alloc(17);
|
|
1212
1211
|
tooSmall[0] = 0x1f;
|
|
1213
1212
|
tooSmall[1] = 0x8b;
|
|
1214
1213
|
const size = (0, compression_1.getGzipUncompressedSize)(tooSmall);
|
|
1215
|
-
|
|
1214
|
+
expect(size).toBeUndefined();
|
|
1216
1215
|
});
|
|
1217
|
-
|
|
1216
|
+
it('fails gracefully for 17-byte GZIP envelope', async () => {
|
|
1218
1217
|
const tooSmall = Buffer.alloc(17);
|
|
1219
1218
|
tooSmall[0] = 0x1f;
|
|
1220
1219
|
tooSmall[1] = 0x8b;
|
|
@@ -1228,31 +1227,31 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1228
1227
|
};
|
|
1229
1228
|
const record = makeSqsRecord({ messageBody: badEnvelope }, 'msg-too-small');
|
|
1230
1229
|
const { failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1231
|
-
|
|
1230
|
+
expect(failedMessageIds).toContain('msg-too-small');
|
|
1232
1231
|
});
|
|
1233
1232
|
});
|
|
1234
|
-
|
|
1235
|
-
|
|
1233
|
+
describe('GZIP timeout protection', () => {
|
|
1234
|
+
it('CompressionTimeoutError has correct properties', () => {
|
|
1236
1235
|
const error = new compression_1.CompressionTimeoutError(compression_1.CompressionOperation.DECOMPRESS, 100);
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1236
|
+
expect(error).toBeInstanceOf(Error);
|
|
1237
|
+
expect(error.name).toBe('CompressionTimeoutError');
|
|
1238
|
+
expect(error.operation).toBe('decompress');
|
|
1239
|
+
expect(error.timeoutMs).toBe(100);
|
|
1240
|
+
expect(error.message).toContain('timed out after 100ms');
|
|
1242
1241
|
});
|
|
1243
|
-
|
|
1242
|
+
it('GZIP decompression respects timeout option', async () => {
|
|
1244
1243
|
const items = [makeTestEvent('timeout-test')];
|
|
1245
1244
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
1246
1245
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
1247
1246
|
const { items: result, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
1248
1247
|
timeoutMs: 10000,
|
|
1249
1248
|
});
|
|
1250
|
-
|
|
1251
|
-
|
|
1249
|
+
expect(result).toHaveLength(1);
|
|
1250
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
1252
1251
|
});
|
|
1253
1252
|
});
|
|
1254
|
-
|
|
1255
|
-
|
|
1253
|
+
describe('large GZIP near SQS limit', () => {
|
|
1254
|
+
it('decompresses large GZIP bundle near 256KB compressed', async () => {
|
|
1256
1255
|
const items = Array.from({ length: 200 }, (_, i) => ({
|
|
1257
1256
|
eventId: `large-${i}`,
|
|
1258
1257
|
name: 'page_view',
|
|
@@ -1264,96 +1263,96 @@ async function makeGzipCompressedEnvelope(items) {
|
|
|
1264
1263
|
console.log(`Large GZIP test: compressed payload ~${Math.round(compressedSize / 1024)}KB`);
|
|
1265
1264
|
const record = makeSqsRecord({ messageBody: envelope }, 'msg-large-gzip');
|
|
1266
1265
|
const { items: result, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record]);
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1266
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
1267
|
+
expect(result).toHaveLength(200);
|
|
1268
|
+
expect(result[0].eventId).toBe('large-0');
|
|
1269
|
+
expect(result[199].eventId).toBe('large-199');
|
|
1271
1270
|
});
|
|
1272
|
-
|
|
1271
|
+
it('handles GZIP with maximum decompressed size exactly at limit', async () => {
|
|
1273
1272
|
const items = [{ eventId: 'boundary', data: 'x'.repeat(5000) }];
|
|
1274
1273
|
const envelope = await makeGzipCompressedEnvelope(items);
|
|
1275
1274
|
const record = makeSqsRecord({ messageBody: envelope });
|
|
1276
1275
|
const { items: result, failedMessageIds } = await (0, sqs_unbundle_1.unbundleRecords)([record], {
|
|
1277
1276
|
maxDecompressedSizeBytes: 10 * 1024,
|
|
1278
1277
|
});
|
|
1279
|
-
|
|
1280
|
-
|
|
1278
|
+
expect(failedMessageIds).toHaveLength(0);
|
|
1279
|
+
expect(result).toHaveLength(1);
|
|
1281
1280
|
});
|
|
1282
1281
|
});
|
|
1283
1282
|
});
|
|
1284
1283
|
});
|
|
1285
|
-
|
|
1286
|
-
|
|
1284
|
+
describe('getGzipUncompressedSize', () => {
|
|
1285
|
+
it('returns correct size for valid GZIP', async () => {
|
|
1287
1286
|
const originalData = 'Hello, World! This is a test.';
|
|
1288
1287
|
const compressed = await gzipAsync(Buffer.from(originalData, 'utf8'));
|
|
1289
1288
|
const size = (0, compression_1.getGzipUncompressedSize)(compressed);
|
|
1290
|
-
|
|
1289
|
+
expect(size).toBe(Buffer.byteLength(originalData, 'utf8'));
|
|
1291
1290
|
});
|
|
1292
|
-
|
|
1291
|
+
it('returns correct size for larger payload', async () => {
|
|
1293
1292
|
const originalData = 'x'.repeat(10000);
|
|
1294
1293
|
const compressed = await gzipAsync(Buffer.from(originalData, 'utf8'));
|
|
1295
1294
|
const size = (0, compression_1.getGzipUncompressedSize)(compressed);
|
|
1296
|
-
|
|
1295
|
+
expect(size).toBe(10000);
|
|
1297
1296
|
});
|
|
1298
|
-
|
|
1297
|
+
it('returns undefined for buffer too small', () => {
|
|
1299
1298
|
const tooSmall = Buffer.alloc(17);
|
|
1300
1299
|
tooSmall[0] = 0x1f;
|
|
1301
1300
|
tooSmall[1] = 0x8b;
|
|
1302
|
-
|
|
1301
|
+
expect((0, compression_1.getGzipUncompressedSize)(tooSmall)).toBeUndefined();
|
|
1303
1302
|
});
|
|
1304
|
-
|
|
1303
|
+
it('returns undefined for wrong magic bytes', () => {
|
|
1305
1304
|
const wrongMagic = Buffer.alloc(20);
|
|
1306
1305
|
wrongMagic[0] = 0x00;
|
|
1307
1306
|
wrongMagic[1] = 0x00;
|
|
1308
|
-
|
|
1307
|
+
expect((0, compression_1.getGzipUncompressedSize)(wrongMagic)).toBeUndefined();
|
|
1309
1308
|
});
|
|
1310
|
-
|
|
1311
|
-
|
|
1309
|
+
it('returns undefined for empty buffer', () => {
|
|
1310
|
+
expect((0, compression_1.getGzipUncompressedSize)(Buffer.alloc(0))).toBeUndefined();
|
|
1312
1311
|
});
|
|
1313
|
-
|
|
1314
|
-
|
|
1312
|
+
it('returns undefined for single byte buffer', () => {
|
|
1313
|
+
expect((0, compression_1.getGzipUncompressedSize)(Buffer.from([0x1f]))).toBeUndefined();
|
|
1315
1314
|
});
|
|
1316
|
-
|
|
1317
|
-
|
|
1315
|
+
it('returns undefined for buffer with only magic bytes', () => {
|
|
1316
|
+
expect((0, compression_1.getGzipUncompressedSize)(Buffer.from([0x1f, 0x8b]))).toBeUndefined();
|
|
1318
1317
|
});
|
|
1319
|
-
|
|
1318
|
+
it('returns 0 for GZIP with ISIZE = 0', () => {
|
|
1320
1319
|
const buffer = Buffer.alloc(18);
|
|
1321
1320
|
buffer[0] = 0x1f;
|
|
1322
1321
|
buffer[1] = 0x8b;
|
|
1323
1322
|
const size = (0, compression_1.getGzipUncompressedSize)(buffer);
|
|
1324
|
-
|
|
1323
|
+
expect(size).toBe(0);
|
|
1325
1324
|
});
|
|
1326
|
-
|
|
1325
|
+
it('reads ISIZE correctly as little-endian', async () => {
|
|
1327
1326
|
const buffer = Buffer.alloc(18);
|
|
1328
1327
|
buffer[0] = 0x1f;
|
|
1329
1328
|
buffer[1] = 0x8b;
|
|
1330
1329
|
buffer.writeUInt32LE(0x12345678, 14);
|
|
1331
1330
|
const size = (0, compression_1.getGzipUncompressedSize)(buffer);
|
|
1332
|
-
|
|
1331
|
+
expect(size).toBe(0x12345678);
|
|
1333
1332
|
});
|
|
1334
|
-
|
|
1333
|
+
it('handles maximum 32-bit ISIZE value', () => {
|
|
1335
1334
|
const buffer = Buffer.alloc(18);
|
|
1336
1335
|
buffer[0] = 0x1f;
|
|
1337
1336
|
buffer[1] = 0x8b;
|
|
1338
1337
|
buffer.writeUInt32LE(0xffffffff, 14);
|
|
1339
1338
|
const size = (0, compression_1.getGzipUncompressedSize)(buffer);
|
|
1340
|
-
|
|
1339
|
+
expect(size).toBe(0xffffffff);
|
|
1341
1340
|
});
|
|
1342
|
-
|
|
1341
|
+
it('correctly extracts size from real GZIP data', async () => {
|
|
1343
1342
|
const testSizes = [1, 10, 100, 1000, 50000];
|
|
1344
1343
|
for (const testSize of testSizes) {
|
|
1345
1344
|
const originalData = 'a'.repeat(testSize);
|
|
1346
1345
|
const compressed = await gzipAsync(Buffer.from(originalData, 'utf8'));
|
|
1347
1346
|
const size = (0, compression_1.getGzipUncompressedSize)(compressed);
|
|
1348
|
-
|
|
1347
|
+
expect(size).toBe(testSize);
|
|
1349
1348
|
}
|
|
1350
1349
|
});
|
|
1351
|
-
|
|
1350
|
+
it('handles JSON array compression correctly', async () => {
|
|
1352
1351
|
const items = [{ id: 1 }, { id: 2 }, { id: 3 }];
|
|
1353
1352
|
const json = JSON.stringify(items);
|
|
1354
1353
|
const compressed = await gzipAsync(Buffer.from(json, 'utf8'));
|
|
1355
1354
|
const size = (0, compression_1.getGzipUncompressedSize)(compressed);
|
|
1356
|
-
|
|
1355
|
+
expect(size).toBe(Buffer.byteLength(json, 'utf8'));
|
|
1357
1356
|
});
|
|
1358
1357
|
});
|
|
1359
1358
|
//# sourceMappingURL=sqs-unbundle.spec.js.map
|