diff --git a/package-lock.json b/package-lock.json index 85f846f737..67b69b8688 100644 --- a/package-lock.json +++ b/package-lock.json @@ -472,57 +472,439 @@ } }, "node_modules/@aws-sdk/client-lambda": { - "version": "3.413.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.413.0.tgz", - "integrity": "sha512-hFkaHul+bpWjUOeBIh4uvMwkv1Tfeo3XXXSag5Kbkl3RNJxqfjCYjHl0MamczmknvNLskv0EZffvNlTyTa91sg==", - "dev": true, + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.418.0.tgz", + "integrity": "sha512-9EB4QNsd95/4va1JTekPqtM3K+cDSULCiGgM1KJ9NOqAaA3vVOM2/9NVzVjG2ohFw36skTmyu62+LmKLbpB4ng==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.413.0", - "@aws-sdk/credential-provider-node": "3.413.0", - "@aws-sdk/middleware-host-header": "3.413.0", - "@aws-sdk/middleware-logger": "3.413.0", - "@aws-sdk/middleware-recursion-detection": "3.413.0", - "@aws-sdk/middleware-signing": "3.413.0", - "@aws-sdk/middleware-user-agent": "3.413.0", - "@aws-sdk/types": "3.413.0", - "@aws-sdk/util-endpoints": "3.413.0", - "@aws-sdk/util-user-agent-browser": "3.413.0", - "@aws-sdk/util-user-agent-node": "3.413.0", - "@smithy/config-resolver": "^2.0.8", - "@smithy/eventstream-serde-browser": "^2.0.7", - "@smithy/eventstream-serde-config-resolver": "^2.0.7", - "@smithy/eventstream-serde-node": "^2.0.7", - "@smithy/fetch-http-handler": "^2.1.3", - "@smithy/hash-node": "^2.0.7", - "@smithy/invalid-dependency": "^2.0.7", - "@smithy/middleware-content-length": "^2.0.9", - "@smithy/middleware-endpoint": "^2.0.7", - "@smithy/middleware-retry": "^2.0.10", - "@smithy/middleware-serde": "^2.0.7", - "@smithy/middleware-stack": "^2.0.0", - "@smithy/node-config-provider": "^2.0.10", - "@smithy/node-http-handler": "^2.1.3", - "@smithy/protocol-http": "^3.0.3", - "@smithy/smithy-client": "^2.1.4", - "@smithy/types": "^2.3.1", - "@smithy/url-parser": "^2.0.7", + "@aws-sdk/client-sts": "3.418.0", + "@aws-sdk/credential-provider-node": "3.418.0", + "@aws-sdk/middleware-host-header": "3.418.0", + "@aws-sdk/middleware-logger": "3.418.0", + "@aws-sdk/middleware-recursion-detection": "3.418.0", + "@aws-sdk/middleware-signing": "3.418.0", + "@aws-sdk/middleware-user-agent": "3.418.0", + "@aws-sdk/region-config-resolver": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@aws-sdk/util-endpoints": "3.418.0", + "@aws-sdk/util-user-agent-browser": "3.418.0", + "@aws-sdk/util-user-agent-node": "3.418.0", + "@smithy/config-resolver": "^2.0.10", + "@smithy/eventstream-serde-browser": "^2.0.9", + "@smithy/eventstream-serde-config-resolver": "^2.0.9", + "@smithy/eventstream-serde-node": "^2.0.9", + "@smithy/fetch-http-handler": "^2.1.5", + "@smithy/hash-node": "^2.0.9", + "@smithy/invalid-dependency": "^2.0.9", + "@smithy/middleware-content-length": "^2.0.11", + "@smithy/middleware-endpoint": "^2.0.9", + "@smithy/middleware-retry": "^2.0.12", + "@smithy/middleware-serde": "^2.0.9", + "@smithy/middleware-stack": "^2.0.2", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/node-http-handler": "^2.1.5", + "@smithy/protocol-http": "^3.0.5", + "@smithy/smithy-client": "^2.1.6", + "@smithy/types": "^2.3.3", + "@smithy/url-parser": "^2.0.9", "@smithy/util-base64": "^2.0.0", "@smithy/util-body-length-browser": "^2.0.0", "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.8", - "@smithy/util-defaults-mode-node": "^2.0.10", - "@smithy/util-retry": "^2.0.0", - "@smithy/util-stream": "^2.0.10", + "@smithy/util-defaults-mode-browser": "^2.0.10", + "@smithy/util-defaults-mode-node": "^2.0.12", + "@smithy/util-retry": "^2.0.2", + "@smithy/util-stream": "^2.0.12", "@smithy/util-utf8": "^2.0.0", - "@smithy/util-waiter": "^2.0.7", + "@smithy/util-waiter": "^2.0.9", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sso": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.418.0.tgz", + "integrity": "sha512-fakz3YeSW/kCAOJ5w4ObrrQBxsYO8sU8i6WHLv6iWAsYZKAws2Mqa8g89P61+GitSH4z9waksdLouS6ep78/5A==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.418.0", + "@aws-sdk/middleware-logger": "3.418.0", + "@aws-sdk/middleware-recursion-detection": "3.418.0", + "@aws-sdk/middleware-user-agent": "3.418.0", + "@aws-sdk/region-config-resolver": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@aws-sdk/util-endpoints": "3.418.0", + "@aws-sdk/util-user-agent-browser": "3.418.0", + "@aws-sdk/util-user-agent-node": "3.418.0", + "@smithy/config-resolver": "^2.0.10", + "@smithy/fetch-http-handler": "^2.1.5", + "@smithy/hash-node": "^2.0.9", + "@smithy/invalid-dependency": "^2.0.9", + "@smithy/middleware-content-length": "^2.0.11", + "@smithy/middleware-endpoint": "^2.0.9", + "@smithy/middleware-retry": "^2.0.12", + "@smithy/middleware-serde": "^2.0.9", + "@smithy/middleware-stack": "^2.0.2", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/node-http-handler": "^2.1.5", + "@smithy/protocol-http": "^3.0.5", + "@smithy/smithy-client": "^2.1.6", + "@smithy/types": "^2.3.3", + "@smithy/url-parser": "^2.0.9", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.10", + "@smithy/util-defaults-mode-node": "^2.0.12", + "@smithy/util-retry": "^2.0.2", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/client-sts": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.418.0.tgz", + "integrity": "sha512-L0n0Hw+Pm+BhXTN1bYZ0y4JAMArYgazdHf1nUSlEHndgZicCCuQtlMLxfo3i/IbtWi0dzfZcZ9d/MdAM8p4Jyw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.418.0", + "@aws-sdk/middleware-host-header": "3.418.0", + "@aws-sdk/middleware-logger": "3.418.0", + "@aws-sdk/middleware-recursion-detection": "3.418.0", + "@aws-sdk/middleware-sdk-sts": "3.418.0", + "@aws-sdk/middleware-signing": "3.418.0", + "@aws-sdk/middleware-user-agent": "3.418.0", + "@aws-sdk/region-config-resolver": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@aws-sdk/util-endpoints": "3.418.0", + "@aws-sdk/util-user-agent-browser": "3.418.0", + "@aws-sdk/util-user-agent-node": "3.418.0", + "@smithy/config-resolver": "^2.0.10", + "@smithy/fetch-http-handler": "^2.1.5", + "@smithy/hash-node": "^2.0.9", + "@smithy/invalid-dependency": "^2.0.9", + "@smithy/middleware-content-length": "^2.0.11", + "@smithy/middleware-endpoint": "^2.0.9", + "@smithy/middleware-retry": "^2.0.12", + "@smithy/middleware-serde": "^2.0.9", + "@smithy/middleware-stack": "^2.0.2", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/node-http-handler": "^2.1.5", + "@smithy/protocol-http": "^3.0.5", + "@smithy/smithy-client": "^2.1.6", + "@smithy/types": "^2.3.3", + "@smithy/url-parser": "^2.0.9", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.10", + "@smithy/util-defaults-mode-node": "^2.0.12", + "@smithy/util-retry": "^2.0.2", + "@smithy/util-utf8": "^2.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.418.0.tgz", + "integrity": "sha512-e74sS+x63EZUBO+HaI8zor886YdtmULzwKdctsZp5/37Xho1CVUNtEC+fYa69nigBD9afoiH33I4JggaHgrekQ==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.418.0.tgz", + "integrity": "sha512-LTAeKKV85unlSqGNIeqEZ4N9gufaSoH+670n5YTUEk564zHCkUQW0PJomzLF5jKBco6Yfzv6rPBTukd+x9XWqw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.418.0", + "@aws-sdk/credential-provider-process": "3.418.0", + "@aws-sdk/credential-provider-sso": "3.418.0", + "@aws-sdk/credential-provider-web-identity": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.418.0.tgz", + "integrity": "sha512-VveTjtSC6m8YXj3fQDkMKEZuHv+CR2Z4u/NAN51Fi4xOtIWUtOBj5rfZ8HmBYoBjRF0DtRlPXuMiNnXAzTctfQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.418.0", + "@aws-sdk/credential-provider-ini": "3.418.0", + "@aws-sdk/credential-provider-process": "3.418.0", + "@aws-sdk/credential-provider-sso": "3.418.0", + "@aws-sdk/credential-provider-web-identity": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@smithy/credential-provider-imds": "^2.0.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.418.0.tgz", + "integrity": "sha512-xPbdm2WKz1oH6pTkrJoUmr3OLuqvvcPYTQX0IIlc31tmDwDWPQjXGGFD/vwZGIZIkKaFpFxVMgAzfFScxox7dw==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.418.0.tgz", + "integrity": "sha512-tUF5Hg/HfaU5t+E7IuvohYlodSIlBXa28xAJPPFxhKrUnvP6AIoW6JLazOtCIQjQgJYEUILV29XX+ojUuITcaw==", + "dependencies": { + "@aws-sdk/client-sso": "3.418.0", + "@aws-sdk/token-providers": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.418.0.tgz", + "integrity": "sha512-do7ang565n9p3dS1JdsQY01rUfRx8vkxQqz5M8OlcEHBNiCdi2PvSjNwcBdrv/FKkyIxZb0TImOfBSt40hVdxQ==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.418.0.tgz", + "integrity": "sha512-LrMTdzalkPw/1ujLCKPLwCGvPMCmT4P+vOZQRbSEVZPnlZk+Aj++aL/RaHou0jL4kJH3zl8iQepriBt4a7UvXQ==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/protocol-http": "^3.0.5", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-logger": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.418.0.tgz", + "integrity": "sha512-StKGmyPVfoO/wdNTtKemYwoJsqIl4l7oqarQY7VSf2Mp3mqaa+njLViHsQbirYpyqpgUEusOnuTlH5utxJ1NsQ==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.418.0.tgz", + "integrity": "sha512-kKFrIQglBLUFPbHSDy1+bbe3Na2Kd70JSUC3QLMbUHmqipXN8KeXRfAj7vTv97zXl0WzG0buV++WcNwOm1rFjg==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/protocol-http": "^3.0.5", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.418.0.tgz", + "integrity": "sha512-cW8ijrCTP+mgihvcq4+TbhAcE/we5lFl4ydRqvTdtcSnYQAVQADg47rnTScQiFsPFEB3NKq7BGeyTJF9MKolPA==", + "dependencies": { + "@aws-sdk/middleware-signing": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-signing": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.418.0.tgz", + "integrity": "sha512-onvs5KoYQE8OlOE740RxWBGtsUyVIgAo0CzRKOQO63ZEYqpL1Os+MS1CGzdNhvQnJgJruE1WW+Ix8fjN30zKPA==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.5", + "@smithy/signature-v4": "^2.0.0", + "@smithy/types": "^2.3.3", + "@smithy/util-middleware": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.418.0.tgz", + "integrity": "sha512-Jdcztg9Tal9SEAL0dKRrnpKrm6LFlWmAhvuwv0dQ7bNTJxIxyEFbpqdgy7mpQHsLVZgq1Aad/7gT/72c9igyZw==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@aws-sdk/util-endpoints": "3.418.0", + "@smithy/protocol-http": "^3.0.5", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/token-providers": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.418.0.tgz", + "integrity": "sha512-9P7Q0VN0hEzTngy3Sz5eya2qEOEf0Q8qf1vB3um0gE6ID6EVAdz/nc/DztfN32MFxk8FeVBrCP5vWdoOzmd72g==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.418.0", + "@aws-sdk/middleware-logger": "3.418.0", + "@aws-sdk/middleware-recursion-detection": "3.418.0", + "@aws-sdk/middleware-user-agent": "3.418.0", + "@aws-sdk/types": "3.418.0", + "@aws-sdk/util-endpoints": "3.418.0", + "@aws-sdk/util-user-agent-browser": "3.418.0", + "@aws-sdk/util-user-agent-node": "3.418.0", + "@smithy/config-resolver": "^2.0.10", + "@smithy/fetch-http-handler": "^2.1.5", + "@smithy/hash-node": "^2.0.9", + "@smithy/invalid-dependency": "^2.0.9", + "@smithy/middleware-content-length": "^2.0.11", + "@smithy/middleware-endpoint": "^2.0.9", + "@smithy/middleware-retry": "^2.0.12", + "@smithy/middleware-serde": "^2.0.9", + "@smithy/middleware-stack": "^2.0.2", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/node-http-handler": "^2.1.5", + "@smithy/property-provider": "^2.0.0", + "@smithy/protocol-http": "^3.0.5", + "@smithy/shared-ini-file-loader": "^2.0.6", + "@smithy/smithy-client": "^2.1.6", + "@smithy/types": "^2.3.3", + "@smithy/url-parser": "^2.0.9", + "@smithy/util-base64": "^2.0.0", + "@smithy/util-body-length-browser": "^2.0.0", + "@smithy/util-body-length-node": "^2.1.0", + "@smithy/util-defaults-mode-browser": "^2.0.10", + "@smithy/util-defaults-mode-node": "^2.0.12", + "@smithy/util-retry": "^2.0.2", + "@smithy/util-utf8": "^2.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/types": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.418.0.tgz", + "integrity": "sha512-y4PQSH+ulfFLY0+FYkaK4qbIaQI9IJNMO2xsxukW6/aNoApNymN1D2FSi2la8Qbp/iPjNDKsG8suNPm9NtsWXQ==", + "dependencies": { + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-endpoints": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.418.0.tgz", + "integrity": "sha512-sYSDwRTl7yE7LhHkPzemGzmIXFVHSsi3AQ1KeNEk84eBqxMHHcCc2kqklaBk2roXWe50QDgRMy1ikZUxvtzNHQ==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.418.0.tgz", + "integrity": "sha512-c4p4mc0VV/jIeNH0lsXzhJ1MpWRLuboGtNEpqE4s1Vl9ck2amv9VdUUZUmHbg+bVxlMgRQ4nmiovA4qIrqGuyg==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/types": "^2.3.3", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.418.0.tgz", + "integrity": "sha512-BXMskXFtg+dmzSCgmnWOffokxIbPr1lFqa1D9kvM3l3IFRiFGx2IyDg+8MAhq11aPDLvoa/BDuQ0Yqma5izOhg==", + "dependencies": { + "@aws-sdk/types": "3.418.0", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/types": "^2.3.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, "node_modules/@aws-sdk/client-secrets-manager": { "version": "3.413.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.413.0.tgz", @@ -997,6 +1379,21 @@ "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.418.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.418.0.tgz", + "integrity": "sha512-lJRZ/9TjZU6yLz+mAwxJkcJZ6BmyYoIJVo1p5+BN//EFdEmC8/c0c9gXMRzfISV/mqWSttdtccpAyN4/goHTYA==", + "dependencies": { + "@smithy/node-config-provider": "^2.0.12", + "@smithy/types": "^2.3.3", + "@smithy/util-config-provider": "^2.0.0", + "@smithy/util-middleware": "^2.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@aws-sdk/service-error-classification": { "version": "3.374.0", "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.374.0.tgz", @@ -1174,19 +1571,6 @@ "tslib": "^2.3.1" } }, - "node_modules/@aws-sdk/util-utf8-node": { - "version": "3.259.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-node/-/util-utf8-node-3.259.0.tgz", - "integrity": "sha512-2sbGdmrkODKeJb6kbEOKpX8cYtS9IO16XRAtINcN7sInWfspAITDofrabf0i0tFQF0hsJtbC5dyJRn87w0gYIQ==", - "dev": true, - "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -4463,11 +4847,11 @@ "dev": true }, "node_modules/@smithy/abort-controller": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.7.tgz", - "integrity": "sha512-rITz65zk8QA3GQ1OeoJ3/Q4+8j/HqubWU8TBqk57BMYTOX+P+LNMoVHPqzLHhE6qKot5muhThNCYvOKNt7ojJA==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.9.tgz", + "integrity": "sha512-8liHOEbx99xcy4VndeQNQhyA0LS+e7UqsuRnDTSIA26IKBv/7vA9w09KOd4fgNULrvX0r3WpA6cwsQTRJpSWkg==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4475,14 +4859,14 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.8.tgz", - "integrity": "sha512-e7mwQteHjo9S1GK+TfzP3o7ujE2ZK30d6wkv5brKtabrZF7MBflj9CwUP2XYuOYebdWirHOtv8ZfkMrpcbJfYw==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.10.tgz", + "integrity": "sha512-MwToDsCltHjumkCuRn883qoNeJUawc2b8sX9caSn5vLz6J5crU1IklklNxWCaMO2z2nDL91Po4b/aI1eHv5PfA==", "dependencies": { - "@smithy/node-config-provider": "^2.0.10", - "@smithy/types": "^2.3.1", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/types": "^2.3.3", "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.0", + "@smithy/util-middleware": "^2.0.2", "tslib": "^2.5.0" }, "engines": { @@ -4490,14 +4874,14 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.10.tgz", - "integrity": "sha512-may2/gYlDip2rjlU1Z5fcCEWY0Fu3tSu/HykgZrLfb2/171P6OYuz7dGNKBOCS1W57vP4W5wmUhm0WGehrixig==", - "dependencies": { - "@smithy/node-config-provider": "^2.0.10", - "@smithy/property-provider": "^2.0.8", - "@smithy/types": "^2.3.1", - "@smithy/url-parser": "^2.0.7", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.12.tgz", + "integrity": "sha512-S3lUNe+2fEFwKcmiQniXGPXt69vaHvQCw8kYQOBL4OvJsgwfpkIYDZdroHbTshYi0M6WaKL26Mw+hvgma6dZqA==", + "dependencies": { + "@smithy/node-config-provider": "^2.0.12", + "@smithy/property-provider": "^2.0.10", + "@smithy/types": "^2.3.3", + "@smithy/url-parser": "^2.0.9", "tslib": "^2.5.0" }, "engines": { @@ -4505,24 +4889,23 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.7.tgz", - "integrity": "sha512-sW3AhXZhmmhh0f11EOotmNNa0rjrKwnMYNKfbp3B/qigdw6foKcmFGX+HF3XGN7w7fFeEFuXr97Ok24gRj92Xg==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.9.tgz", + "integrity": "sha512-sy0pcbKnawt1iu+qCoSFbs/h9PAaUgvlJEO3lqkE1HFFj4p5RgL98vH+9CyDoj6YY82cG5XsorFmcLqQJHTOYw==", "dependencies": { "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "@smithy/util-hex-encoding": "^2.0.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.7.tgz", - "integrity": "sha512-5ZKW1tUe+LD1F6dSHs+nC0vRNmMMWDJWCsw44FkhivhOB4MliGfC1ZNeO45AHD749jfJT/zcGGr2ruQT9VbThA==", - "dev": true, + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.9.tgz", + "integrity": "sha512-g70enHZau2hGj1Uxedrn8AAjH9E7RnpHdwkuPKapagah53ztbwI7xaNeA5SLD4MjSjdrjathyQBCQKIzwXrR1g==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/eventstream-serde-universal": "^2.0.9", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4530,12 +4913,11 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.7.tgz", - "integrity": "sha512-0n4LPHZt6/RAHVkwzms6U2xibmizkSYLS9HzlT86WF29X56v7OTCkMF+pUFNYZamN7iRq1Z8PM48mQsBoJPaSA==", - "dev": true, + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.9.tgz", + "integrity": "sha512-+15GzIMtdSuRPyuCeGZ7gzgD94Ejv6eM1vKcqvipdzS+i36KTZ2A9aZsJk+gDw//OCD1EMx9SqpV6bUvMS4PWg==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4543,13 +4925,12 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.7.tgz", - "integrity": "sha512-ZkBvDIBlJ9eJx/+CC2AY8LxAndGO+Z2FOPPprmNNDbK9/pZzVLHWGwlpsPYnA9Pc0gfOu7isIJM1yPXiK70O3A==", - "dev": true, + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.9.tgz", + "integrity": "sha512-UEJcvN2WXXEjkewtFkj1S2HSZLbyCgzUnfoFPrTuKy4+xRfakO5dNx6ws2h1pvb8Vc7mTuBL+Webl1R5mnVsXA==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/eventstream-serde-universal": "^2.0.9", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4557,13 +4938,12 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.7.tgz", - "integrity": "sha512-CNYEzEPDIGbfvYYN7iajPY6sVZdtGvJzSbvqgH+EvismooFj8ahydGp8IKYPnd5ge5uwTATppJ2t8149tYkS7g==", - "dev": true, + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.9.tgz", + "integrity": "sha512-dAHQEYlK/1tjjieBE7jjXwpLQFgKdkvC4HSQf+/Jj4t34XbUmXWHbw92/EuLp9+vjNB/JQPvkwpMtN31jxIDeg==", "dependencies": { - "@smithy/eventstream-codec": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/eventstream-codec": "^2.0.9", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4571,23 +4951,23 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.1.3.tgz", - "integrity": "sha512-kUg+Ey4mJeR/3+Ponuhb1rsmsfZRwjCLvC+WcPgeI+ittretEzuWAPN+9anD0HJEoApVjHpndzxPtlncbCUJDQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.1.5.tgz", + "integrity": "sha512-BIeCHGfr5JCGN+EMTwZK74ELvjPXOIrI7OLM5OhZJJ6AmZyRv2S9ANJk18AtLwht0TsSm+8WoXIEp8LuxNgUyA==", "dependencies": { - "@smithy/protocol-http": "^3.0.3", - "@smithy/querystring-builder": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/protocol-http": "^3.0.5", + "@smithy/querystring-builder": "^2.0.9", + "@smithy/types": "^2.3.3", "@smithy/util-base64": "^2.0.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/hash-node": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.7.tgz", - "integrity": "sha512-aB5lvIDP1v+ZUUS8ek3XW5xnZ6jUQ86JXqG7a5jMP6AbjAc3439mIbs6+f1EQ5MtYmrQCEtRRyvv5QofvotH0w==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.9.tgz", + "integrity": "sha512-XP3yWd5wyCtiVmsY5Nuq/FUwyCEQ6YG7DsvRh7ThldNukGpCzyFdP8eivZJVjn4Fx7oYrrOnVoYZ0WEgpW1AvQ==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "@smithy/util-buffer-from": "^2.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.5.0" @@ -4597,11 +4977,11 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.7.tgz", - "integrity": "sha512-qVOZnHFPzQo4BS47/PANHX32Y69c0tJxKBkqTL795D/DKInqBwmBO/m1gS7v0ZQqmtCuoy2l87RflQfRY2xEIw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.9.tgz", + "integrity": "sha512-RuJqhYf8nViK96IIO9JbTtjDUuFItVfuuJhWw2yk7fv67yltQ7fZD6IQ2OsHHluoVmstnQJuCg5raXJR696Ubw==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" } }, @@ -4617,12 +4997,12 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.9.tgz", - "integrity": "sha512-2XVFsGqswxrIBi0w4Njwzb1zsbte26U513K+WPFm9z6SB/3WR5/VBVjTaTcamrXznTAqBjTwTL0Ysisv1dW0Rw==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.11.tgz", + "integrity": "sha512-Malj4voNTL4+a5ZL3a6+Ij7JTUMTa2R7c3ZIBzMxN5OUUgAspU7uFi1Q97f4B0afVh2joQBAWH5IQJUG25nl8g==", "dependencies": { - "@smithy/protocol-http": "^3.0.3", - "@smithy/types": "^2.3.1", + "@smithy/protocol-http": "^3.0.5", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4630,14 +5010,14 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.7.tgz", - "integrity": "sha512-4/L0wV7PzHEprJB0gazSTIwlW/2cCfwC9EHavUMhoCyl1tLer6CJwDbAMit1IMvwbHkwuKopueb8dFPHfpS2Pw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.9.tgz", + "integrity": "sha512-72/o8R6AAO4+nyTI6h4z6PYGTSA4dr1M7tZz29U8DEUHuh1YkhC77js0P6RyF9G0wDLuYqxb+Yh0crI5WG2pJg==", "dependencies": { - "@smithy/middleware-serde": "^2.0.7", - "@smithy/types": "^2.3.1", - "@smithy/url-parser": "^2.0.7", - "@smithy/util-middleware": "^2.0.0", + "@smithy/middleware-serde": "^2.0.9", + "@smithy/types": "^2.3.3", + "@smithy/url-parser": "^2.0.9", + "@smithy/util-middleware": "^2.0.2", "tslib": "^2.5.0" }, "engines": { @@ -4645,16 +5025,16 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.10.tgz", - "integrity": "sha512-VwAQOR5Rh/y9BzUgb5DzUk7qYBiMZu3pEQa5EwwAf/F7lpMuNildGrAxtDmsXk90490FJwa6LyFknXP3kO5BnA==", - "dependencies": { - "@smithy/node-config-provider": "^2.0.10", - "@smithy/protocol-http": "^3.0.3", - "@smithy/service-error-classification": "^2.0.0", - "@smithy/types": "^2.3.1", - "@smithy/util-middleware": "^2.0.0", - "@smithy/util-retry": "^2.0.0", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.12.tgz", + "integrity": "sha512-YQ/ufXX4/d9/+Jf1QQ4J+CVeupC7BW52qldBTvRV33PDX9vxndlAwkFwzBcmnUFC3Hjf1//HW6I77EItcjNSCA==", + "dependencies": { + "@smithy/node-config-provider": "^2.0.12", + "@smithy/protocol-http": "^3.0.5", + "@smithy/service-error-classification": "^2.0.2", + "@smithy/types": "^2.3.3", + "@smithy/util-middleware": "^2.0.2", + "@smithy/util-retry": "^2.0.2", "tslib": "^2.5.0", "uuid": "^8.3.2" }, @@ -4663,11 +5043,11 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.7.tgz", - "integrity": "sha512-tOldis4PUNafdGErLZ+33p9Pf3MmTlLa176X321Z6ZaCf1XNEow9m3T5vXrcHErVAvjPG0mp3l54J94HnPc+rQ==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.9.tgz", + "integrity": "sha512-GVbauxrr6WmtCaesakktg3t5LR/yDbajpC7KkWc8rtCpddMI4ShAVO5Q6DqwX8MDFi4CLaY8H7eTGcxhl3jbLg==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4675,10 +5055,11 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.0.tgz", - "integrity": "sha512-31XC1xNF65nlbc16yuh3wwTudmqs6qy4EseQUGF8A/p2m/5wdd/cnXJqpniy/XvXVwkHPz/GwV36HqzHtIKATQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.3.tgz", + "integrity": "sha512-AlhPmbwpkC4lQBVaVHXczmjFvsAhDHhrakqLt038qFLotnJcvDLhmMzAtu23alBeOSkKxkTQq0LsAt2N0WpAbw==", "dependencies": { + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4686,13 +5067,13 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.10.tgz", - "integrity": "sha512-e5MiLH5Eu+BbYsmhZIkvUKCzite6JCBPL75PNjlRK2TWvSpfp19hNf2SiJIQbPalcFj5zlyBvtcEkF1sfYIdhg==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.0.12.tgz", + "integrity": "sha512-df9y9ywv+JmS40Y60ZqJ4jfZiTCmyHQffwzIqjBjLJLJl0imf9F6DWBd+jiEWHvlohR+sFhyY+KL/qzKgnAq1A==", "dependencies": { - "@smithy/property-provider": "^2.0.8", - "@smithy/shared-ini-file-loader": "^2.0.9", - "@smithy/types": "^2.3.1", + "@smithy/property-provider": "^2.0.10", + "@smithy/shared-ini-file-loader": "^2.0.11", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4700,14 +5081,14 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.3.tgz", - "integrity": "sha512-TGkgpx68SqvbspVHaG3iwqP2mKYOT4whiq7Kv2X9v+InngL4MkpH3LQ0Dk7kbloahZr+hAOyb6s8D7T8TXRrzA==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.5.tgz", + "integrity": "sha512-52uF+BrZaFiBh+NT/bADiVDCQO91T+OwDRsuaAeWZC1mlCXFjAPPQdxeQohtuYOe9m7mPP/xIMNiqbe8jvndHA==", "dependencies": { - "@smithy/abort-controller": "^2.0.7", - "@smithy/protocol-http": "^3.0.3", - "@smithy/querystring-builder": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/abort-controller": "^2.0.9", + "@smithy/protocol-http": "^3.0.5", + "@smithy/querystring-builder": "^2.0.9", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4715,11 +5096,11 @@ } }, "node_modules/@smithy/property-provider": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.8.tgz", - "integrity": "sha512-oaaP/i7bGG8XbxG9Kx4PZh83iJ2jo/vt8RmJdi9hmc8APBaW1HGDperVXDCyPQdVYXmiqrtxc/rPImyBma1G3A==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.10.tgz", + "integrity": "sha512-YMBVfh0ZMmJtbsUn+WfSwR32iRljZPdRN0Tn2GAcdJ+ejX8WrBXD7Z0jIkQDrQZr8fEuuv5x8WxMIj+qVbsPQw==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4727,11 +5108,11 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.3.tgz", - "integrity": "sha512-UGfmQNdijlFV+UzgdRyfe05S5vLDdcdkvNcxhGvQ+Er7TjUkZSxjukQB9VXtT8oTHztgOMX74DDlPBsVzZR5Pg==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.5.tgz", + "integrity": "sha512-3t3fxj+ip4EPHRC2fQ0JimMxR/qCQ1LSQJjZZVZFgROnFLYWPDgUZqpoi7chr+EzatxJVXF/Rtoi5yLHOWCoZQ==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4739,11 +5120,11 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.7.tgz", - "integrity": "sha512-RPHnqt4iH1Kwp1Zbf4gJI88hZiynEZjE5hEWJNBmKqCe1Q6v7HBLtaovTaiuYaMEmPyb2KxOi3lISAdT6uuPqw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.9.tgz", + "integrity": "sha512-Yt6CPF4j3j1cuwod/DRflbuXxBFjJm7gAjy6W1RE21Rz5/kfGFqiZBXWmmXwGtnnhiLThYwoHK4S6/TQtnx0Fg==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "@smithy/util-uri-escape": "^2.0.0", "tslib": "^2.5.0" }, @@ -4752,11 +5133,11 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.7.tgz", - "integrity": "sha512-Cwi/Hgs73nbLKfgH7dXAxzvDxyTrK+BLrlAd0KXU7xcBR94V132nvxoq39BMWckYAPmnMwxCwq8uusNH4Dnagw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.9.tgz", + "integrity": "sha512-U6z4N743s4vrcxPW8p8+reLV0PjMCYEyb1/wtMVvv3VnbJ74gshdI8SR1sBnEh95cF8TxonmX5IxY25tS9qGfg==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4764,19 +5145,22 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.0.tgz", - "integrity": "sha512-2z5Nafy1O0cTf69wKyNjGW/sNVMiqDnb4jgwfMG8ye8KnFJ5qmJpDccwIbJNhXIfbsxTg9SEec2oe1cexhMJvw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.2.tgz", + "integrity": "sha512-GTUd2j63gKy7A+ggvSdn2hc4sejG7LWfE+ZMF17vzWoNyqERWbRP7HTPS0d0Lwg1p6OQCAzvNigSrEIWVFt6iA==", + "dependencies": { + "@smithy/types": "^2.3.3" + }, "engines": { "node": ">=14.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.9.tgz", - "integrity": "sha512-vBLgJI+Qpz1TZ0W2kUBOmG2Q+geVEhiXE99UX02+UFag2WzOQ6frvV6rpadwJu0uwF02GG620NbiKGboqZ19YA==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.11.tgz", + "integrity": "sha512-Sf0u5C5px6eykXi6jImDTp+edvG3REtPjXnFWU/J+b7S2wkXwUqFXqBL5DdM4zC1F+M8u57ZT7NRqDwMOw7/Tw==", "dependencies": { - "@smithy/types": "^2.3.1", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4802,13 +5186,13 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.4.tgz", - "integrity": "sha512-KRQvYYjEGqvmwnKSAZ8EL0hZvPxGQMYbAKS/AMGq2fuRmwAlinSVJ/fkIs65bZp2oYjcskd1ZgKcP+2UDjNPTQ==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.7.tgz", + "integrity": "sha512-r6T/oiBQ8vCbGqObH4/h0YqD0jFB1hAS9KFRmuTfaNJueu/L2hjmjqFjv3PV5lkbNHTgUYraSv4cFQ1naxiELQ==", "dependencies": { - "@smithy/middleware-stack": "^2.0.0", - "@smithy/types": "^2.3.1", - "@smithy/util-stream": "^2.0.10", + "@smithy/middleware-stack": "^2.0.3", + "@smithy/types": "^2.3.3", + "@smithy/util-stream": "^2.0.12", "tslib": "^2.5.0" }, "engines": { @@ -4816,9 +5200,9 @@ } }, "node_modules/@smithy/types": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.3.1.tgz", - "integrity": "sha512-cS48e4Yawb6pGakj7DBJUIPFIkqnUWyXTe2ndPRNagD73b6kEJqTc8bhTyfUve0A+sijK256UKE0J1juAfCeDA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.3.3.tgz", + "integrity": "sha512-zTdIPR9PvFVNRdIKMQu4M5oyTaycIbUqLheQqaOi9rTWPkgjGO2wDBxMA1rBHQB81aqAEv+DbSS4jfKyQMnXRA==", "dependencies": { "tslib": "^2.5.0" }, @@ -4827,12 +5211,12 @@ } }, "node_modules/@smithy/url-parser": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.7.tgz", - "integrity": "sha512-SwMl1Lq3yFR2hzhwWYKg04uJHpfcXWMBPycm4Z8GkLI6Dw7rJNDApEbMtujlYw6pVP2WKbrpaGHjQ9MdP92kMQ==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.9.tgz", + "integrity": "sha512-NBnJ0NiY8z6E82Xd5VYUFQfKwK/wA/+QkKmpYUYP+cpH3aCzE6g2gvixd9vQKYjsIdRfNPCf+SFAozt8ljozOw==", "dependencies": { - "@smithy/querystring-parser": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/querystring-parser": "^2.0.9", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" } }, @@ -4891,12 +5275,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.8.tgz", - "integrity": "sha512-8znx01mkmfKxhiSB2bOF5eMutuCLMd8m2Kh0ulRp8vgzhwRLDJoU6aHSEUoNptbuTAtiFf4u0gpkYC2XfbWwuA==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.11.tgz", + "integrity": "sha512-0syV1Mz/mCQ7CG/MHKQfH+w86xq59jpD0EOXv5oe0WBXLmq2lWPpVHl2Y6+jQ+/9fYzyZ5NF+NC/WEIuiv690A==", "dependencies": { - "@smithy/property-provider": "^2.0.8", - "@smithy/types": "^2.3.1", + "@smithy/property-provider": "^2.0.10", + "@smithy/smithy-client": "^2.1.7", + "@smithy/types": "^2.3.3", "bowser": "^2.11.0", "tslib": "^2.5.0" }, @@ -4905,15 +5290,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.10.tgz", - "integrity": "sha512-QUcUckL4ZqDFVwLnh7zStRUnXtTC6hcJZ4FmMqnxlPcL33Rko0sMQwrMDnMdzF3rS3wvqugAaq3zzop1HCluvw==", - "dependencies": { - "@smithy/config-resolver": "^2.0.8", - "@smithy/credential-provider-imds": "^2.0.10", - "@smithy/node-config-provider": "^2.0.10", - "@smithy/property-provider": "^2.0.8", - "@smithy/types": "^2.3.1", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.13.tgz", + "integrity": "sha512-6BtCHYdw5Z8r6KpW8tRCc3yURgvcQwfIEeHhR70BeSOfx8T/TXPPjb8A+K45+KASspa3fzrsSxeIwB0sAeMoHA==", + "dependencies": { + "@smithy/config-resolver": "^2.0.10", + "@smithy/credential-provider-imds": "^2.0.12", + "@smithy/node-config-provider": "^2.0.12", + "@smithy/property-provider": "^2.0.10", + "@smithy/smithy-client": "^2.1.7", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4932,10 +5318,11 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.0.tgz", - "integrity": "sha512-eCWX4ECuDHn1wuyyDdGdUWnT4OGyIzV0LN1xRttBFMPI9Ff/4heSHVxneyiMtOB//zpXWCha1/SWHJOZstG7kA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.2.tgz", + "integrity": "sha512-UGPZM+Ja/vke5pc/S8G0LNiHpVirtjppsXO+GK9m9wbzRGzPJTfnZA/gERUUN/AfxEy/8SL7U1kd7u4t2X8K1w==", "dependencies": { + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4943,11 +5330,12 @@ } }, "node_modules/@smithy/util-retry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.0.tgz", - "integrity": "sha512-/dvJ8afrElasuiiIttRJeoS2sy8YXpksQwiM/TcepqdRVp7u4ejd9C4IQURHNjlfPUT7Y6lCDSa2zQJbdHhVTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.2.tgz", + "integrity": "sha512-ovWiayUB38moZcLhSFFfUgB2IMb7R1JfojU20qSahjxAgfOZvDWme3eOYUMtAVnouZ9kYJiFgHLy27qRH4NeeA==", "dependencies": { - "@smithy/service-error-classification": "^2.0.0", + "@smithy/service-error-classification": "^2.0.2", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -4955,13 +5343,13 @@ } }, "node_modules/@smithy/util-stream": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.10.tgz", - "integrity": "sha512-2EgK5cBiv9OaDmhSXmsZY8ZByBl1dg/Tbc51iBJ5GkLGVYhaA6/1l6vHHV41m4Im3D0XfZV1tmeLlQgmRnYsTQ==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.12.tgz", + "integrity": "sha512-FOCpRLaj6gvSyUC5mJAACT+sPMPmp9sD1o+hVbUH/QxwZfulypA3ZIFdAg/59/IY0d/1Q4CTztsiHEB5LgjN4g==", "dependencies": { - "@smithy/fetch-http-handler": "^2.1.3", - "@smithy/node-http-handler": "^2.1.3", - "@smithy/types": "^2.3.1", + "@smithy/fetch-http-handler": "^2.1.5", + "@smithy/node-http-handler": "^2.1.5", + "@smithy/types": "^2.3.3", "@smithy/util-base64": "^2.0.0", "@smithy/util-buffer-from": "^2.0.0", "@smithy/util-hex-encoding": "^2.0.0", @@ -4996,12 +5384,12 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.7.tgz", - "integrity": "sha512-lIY4GOmrSwMiGHhm++1ea0MdKx5y4V39ue4eNg4yxmip1hiuCLxkfXGZVLh0JPxBxAzbQw+E/5TPfY4w/RBkNw==", + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.9.tgz", + "integrity": "sha512-Hy9Cs0FtIacC1aVFk98bm/7CYqim9fnHAPRnV/SB2mj02ExYs/9Dn5SrNQmtTBTLCn65KqYnNVBNS8GuGpZOOw==", "dependencies": { - "@smithy/abort-controller": "^2.0.7", - "@smithy/types": "^2.3.1", + "@smithy/abort-controller": "^2.0.9", + "@smithy/types": "^2.3.3", "tslib": "^2.5.0" }, "engines": { @@ -17742,15 +18130,7 @@ "packages/commons": { "name": "@aws-lambda-powertools/commons", "version": "1.13.1", - "license": "MIT-0", - "devDependencies": { - "@aws-sdk/client-appconfigdata": "^3.413.0", - "@aws-sdk/client-dynamodb": "^3.413.0", - "@aws-sdk/client-lambda": "^3.413.0", - "@aws-sdk/client-secrets-manager": "^3.413.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/util-utf8-node": "^3.259.0" - } + "license": "MIT-0" }, "packages/idempotency": { "name": "@aws-lambda-powertools/idempotency", @@ -17881,6 +18261,8 @@ "license": "MIT-0", "dependencies": { "@aws-cdk/cli-lib-alpha": "^2.96.1-alpha.0", + "@aws-sdk/client-lambda": "^3.418.0", + "@smithy/util-utf8": "^2.0.0", "aws-cdk-lib": "^2.96.1", "esbuild": "^0.19.3" } diff --git a/packages/commons/package.json b/packages/commons/package.json index 119d11f620..db07041d8b 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -44,13 +44,5 @@ "powertools", "serverless", "nodejs" - ], - "devDependencies": { - "@aws-sdk/client-appconfigdata": "^3.413.0", - "@aws-sdk/client-dynamodb": "^3.413.0", - "@aws-sdk/client-lambda": "^3.413.0", - "@aws-sdk/client-secrets-manager": "^3.413.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/util-utf8-node": "^3.259.0" - } + ] } diff --git a/packages/commons/src/awsSdk/index.ts b/packages/commons/src/awsSdk/index.ts new file mode 100644 index 0000000000..6a771c2265 --- /dev/null +++ b/packages/commons/src/awsSdk/index.ts @@ -0,0 +1,2 @@ +export { addUserAgentMiddleware } from './userAgentMiddleware'; +export { isSdkClient } from './utils'; diff --git a/packages/commons/src/awsSdk/userAgentMiddleware.ts b/packages/commons/src/awsSdk/userAgentMiddleware.ts new file mode 100644 index 0000000000..5ed76d1f1e --- /dev/null +++ b/packages/commons/src/awsSdk/userAgentMiddleware.ts @@ -0,0 +1,57 @@ +import { PT_VERSION } from '../version'; +import { isSdkClient } from './utils'; +import type { MiddlewareArgsLike } from '../types/awsSdk'; + +/** + * @internal + */ +const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; +const middlewareOptions = { + relation: 'after', + toMiddleware: 'getUserAgentMiddleware', + name: 'addPowertoolsToUserAgent', + tags: ['POWERTOOLS', 'USER_AGENT'], +}; + +/** + * @internal + * returns a middleware function for the MiddlewareStack, that can be used for the SDK clients + * @param feature + */ +const customUserAgentMiddleware = (feature: string) => { + return (next: (arg0: T) => Promise) => + async (args: T) => { + const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; + args.request.headers[ + 'user-agent' + ] = `${args.request.headers['user-agent']} ${powertoolsUserAgent}`; + + return await next(args); + }; +}; + +const addUserAgentMiddleware = (client: unknown, feature: string): void => { + try { + if (isSdkClient(client)) { + if ( + client.middlewareStack + .identify() + .includes('addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT') + ) { + return; + } + client.middlewareStack.addRelativeTo( + customUserAgentMiddleware(feature), + middlewareOptions + ); + } else { + throw new Error( + `The client provided does not match the expected interface` + ); + } + } catch (e) { + console.warn('Failed to add user agent middleware', e); + } +}; + +export { customUserAgentMiddleware, addUserAgentMiddleware }; diff --git a/packages/commons/src/awsSdk/utils.ts b/packages/commons/src/awsSdk/utils.ts new file mode 100644 index 0000000000..611525abe1 --- /dev/null +++ b/packages/commons/src/awsSdk/utils.ts @@ -0,0 +1,25 @@ +import { SdkClient } from '../types/awsSdk'; + +/** + * @internal + * Type guard to check if the client provided is a valid AWS SDK v3 client + */ +const isSdkClient = (client: unknown): client is SdkClient => + typeof client === 'object' && + client !== null && + 'send' in client && + typeof client.send === 'function' && + 'config' in client && + client.config !== undefined && + typeof client.config === 'object' && + client.config !== null && + 'middlewareStack' in client && + client.middlewareStack !== undefined && + typeof client.middlewareStack === 'object' && + client.middlewareStack !== null && + 'identify' in client.middlewareStack && + typeof client.middlewareStack.identify === 'function' && + 'addRelativeTo' in client.middlewareStack && + typeof client.middlewareStack.addRelativeTo === 'function'; + +export { isSdkClient }; diff --git a/packages/commons/src/index.ts b/packages/commons/src/index.ts index 2192dc8bb8..0549592bf2 100644 --- a/packages/commons/src/index.ts +++ b/packages/commons/src/index.ts @@ -5,4 +5,4 @@ export * as ContextExamples from './samples/resources/contexts'; export * as Events from './samples/resources/events'; export * from './types/middy'; export * from './types/utils'; -export * from './userAgentMiddleware'; +export * from './awsSdk'; diff --git a/packages/commons/src/types/awsSdk.ts b/packages/commons/src/types/awsSdk.ts new file mode 100644 index 0000000000..a62ba6c891 --- /dev/null +++ b/packages/commons/src/types/awsSdk.ts @@ -0,0 +1,22 @@ +/** + * @internal + * Minimal interface for an AWS SDK v3 client + */ +interface SdkClient { + send: (args: unknown) => Promise; + config: { + serviceId: string; + }; + middlewareStack: { + identify: () => string[]; + addRelativeTo: (middleware: unknown, options: unknown) => void; + }; +} + +/** + * @internal + * Minimal type for the arguments passed to a middleware function + */ +type MiddlewareArgsLike = { request: { headers: { [key: string]: string } } }; + +export { SdkClient, MiddlewareArgsLike }; diff --git a/packages/commons/src/userAgentMiddleware.ts b/packages/commons/src/userAgentMiddleware.ts deleted file mode 100644 index 24b278f7b4..0000000000 --- a/packages/commons/src/userAgentMiddleware.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { PT_VERSION } from './version'; - -/** - * @internal - */ -const EXEC_ENV = process.env.AWS_EXECUTION_ENV || 'NA'; -const middlewareOptions = { - relation: 'after', - toMiddleware: 'getUserAgentMiddleware', - name: 'addPowertoolsToUserAgent', - tags: ['POWERTOOLS', 'USER_AGENT'], -}; - -/** - * @internal - * returns a middleware function for the MiddlewareStack, that can be used for the SDK clients - * @param feature - */ -const customUserAgentMiddleware = (feature: string) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return (next, _context) => async (args) => { - const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; - args.request.headers[ - 'user-agent' - ] = `${args.request.headers['user-agent']} ${powertoolsUserAgent}`; - - return await next(args); - }; -}; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -const addUserAgentMiddleware = (client, feature: string): void => { - try { - if ( - client.middlewareStack - .identify() - .includes('addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT') - ) { - return; - } - client.middlewareStack.addRelativeTo( - customUserAgentMiddleware(feature), - middlewareOptions - ); - } catch (e) { - console.warn('Failed to add user agent middleware', e); - } -}; - -export { addUserAgentMiddleware }; diff --git a/packages/commons/tests/unit/awsSdk.test.ts b/packages/commons/tests/unit/awsSdk.test.ts new file mode 100644 index 0000000000..fd02efd9ab --- /dev/null +++ b/packages/commons/tests/unit/awsSdk.test.ts @@ -0,0 +1,148 @@ +import { addUserAgentMiddleware, isSdkClient } from '../../src/awsSdk'; +import { PT_VERSION as version } from '../../src/version'; +import { customUserAgentMiddleware } from '../../src/awsSdk/userAgentMiddleware'; + +describe('Helpers: awsSdk', () => { + describe('Function: userAgentMiddleware', () => { + beforeAll(() => { + jest.spyOn(console, 'warn').mockImplementation(() => ({})); + }); + + it('handles gracefully failures in adding a middleware and only log a warning', () => { + // Prepare + const client = { + middlewareStack: { + addRelativeTo: () => { + throw new Error('test'); + }, + }, + }; + const warningSpy = jest + .spyOn(console, 'warn') + .mockImplementation(() => ({})); + + // Act & Assess + expect(() => addUserAgentMiddleware(client, 'my-feature')).not.toThrow(); + expect(warningSpy).toHaveBeenCalledTimes(1); + }); + + it('should return and do nothing if the client already has a Powertools UA middleware', async () => { + // Prepare + const client = { + middlewareStack: { + identify: () => 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT', + addRelativeTo: jest.fn(), + }, + send: jest.fn(), + config: { + defaultSigningName: 'bar', + }, + }; + const feature = 'my-feature'; + + // Act + addUserAgentMiddleware(client, feature); + + // Assess + expect(client.middlewareStack.addRelativeTo).toHaveBeenCalledTimes(0); + }); + + it('should call the function to add the middleware with the correct arguments', async () => { + // Prepare + const client = { + middlewareStack: { + identify: () => '', + addRelativeTo: jest.fn(), + }, + send: jest.fn(), + config: { + defaultSigningName: 'bar', + }, + }; + const feature = 'my-feature'; + + // Act + addUserAgentMiddleware(client, feature); + + // Assess + expect(client.middlewareStack.addRelativeTo).toHaveBeenNthCalledWith( + 1, + expect.any(Function), + { + relation: 'after', + toMiddleware: 'getUserAgentMiddleware', + name: 'addPowertoolsToUserAgent', + tags: ['POWERTOOLS', 'USER_AGENT'], + } + ); + }); + }); + + describe('Function: customUserAgentMiddleware', () => { + it('returns a middleware function', () => { + // Prepare + const feature = 'my-feature'; + + // Act + const middleware = customUserAgentMiddleware(feature); + + // Assess + expect(middleware).toBeInstanceOf(Function); + }); + + it('adds the Powertools UA to the request headers', async () => { + // Prepare + const feature = 'my-feature'; + const middleware = customUserAgentMiddleware(feature); + const next = jest.fn(); + const args = { + request: { + headers: { + 'user-agent': 'foo', + }, + }, + }; + + // Act + await middleware(next)(args); + + // Assess + expect(args.request.headers['user-agent']).toEqual( + `foo PT/my-feature/${version} PTEnv/NA` + ); + }); + }); + + describe('Function: isSdkClient', () => { + it('returns true if the client is a valid AWS SDK v3 client', () => { + // Prepare + const client = { + send: jest.fn(), + config: { + defaultSigningName: 'bar', + }, + middlewareStack: { + identify: () => '', + addRelativeTo: jest.fn(), + }, + }; + + // Act + const result = isSdkClient(client); + + // Assess + expect(result).toEqual(true); + }); + + it('returns false if the client is not a valid AWS SDK v3 client', () => { + // Prepare + const client = {}; + + // Act + const result = isSdkClient(client); + + // Assess + expect(result).toEqual(false); + }); + }); +}); diff --git a/packages/commons/tests/unit/userAgentMiddleware.test.ts b/packages/commons/tests/unit/userAgentMiddleware.test.ts deleted file mode 100644 index cb9bdd7812..0000000000 --- a/packages/commons/tests/unit/userAgentMiddleware.test.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { addUserAgentMiddleware } from '../../src/userAgentMiddleware'; -import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; -import { DynamoDBClient, ScanCommand } from '@aws-sdk/client-dynamodb'; -import { GetParameterCommand, SSMClient } from '@aws-sdk/client-ssm'; -import { PT_VERSION } from '../../src/version'; -import { AppConfigDataClient } from '@aws-sdk/client-appconfigdata'; -import { - GetSecretValueCommand, - SecretsManagerClient, -} from '@aws-sdk/client-secrets-manager'; -import { RelativeMiddlewareOptions } from '@aws-sdk/types/dist-types/middleware'; - -type SupportedSdkClients = - | LambdaClient - | DynamoDBClient - | SSMClient - | SecretsManagerClient - | AppConfigDataClient; - -type SupportedSdkCommands = - | InvokeCommand - | ScanCommand - | GetParameterCommand - | GetSecretValueCommand; - -const options = { - region: 'us-east-1', - endpoint: 'http://localhost:9001', - credentials: { - accessKeyId: 'test', - secretAccessKey: 'test', - sessionToken: 'test', - }, -}; - -const assertMiddleware = (feature: string) => { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return (next) => (args) => { - const userAgent = args?.request?.headers['user-agent']; - expect(userAgent).toContain(`PT/${feature}/${PT_VERSION} PTEnv/NA`); - // make sure it's at the end of the user agent - expect( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - userAgent - ?.split(' ') - .slice(userAgent?.split(' ').length - 2) // take the last to entries of the user-agent header - .join(' ') - ).toEqual(`PT/${feature}/${PT_VERSION} PTEnv/NA`); - - return next(args); - }; -}; - -const assertMiddlewareOptions: RelativeMiddlewareOptions = { - relation: 'after', - toMiddleware: 'addPowertoolsToUserAgent', - name: 'testUserAgentHeader', - tags: ['TEST'], -}; - -const runCommand = async ( - client: SupportedSdkClients, - command: SupportedSdkCommands -): Promise => { - try { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - return await client.send(command); - } catch (e) { - // throw only jest errors and swallow the SDK client errors like credentials or connection issues - if ( - e instanceof Error && - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - e.matcherResult !== undefined && - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - e.matcherResult.pass === false - ) { - throw e; - } - } -}; - -describe('Given a client of instance: ', () => { - it.each([ - { - name: 'LambdaClient', - client: new LambdaClient(options), - command: new InvokeCommand({ FunctionName: 'test', Payload: '' }), - }, - { - name: 'DynamoDBClient', - client: new DynamoDBClient(options), - command: new ScanCommand({ TableName: 'test' }), - }, - { - name: 'SSMClient', - client: new SSMClient(options), - command: new GetParameterCommand({ Name: 'test' }), - }, - { - name: 'AppConfigDataClient', - client: new AppConfigDataClient(options), - command: new GetParameterCommand({ Name: 'test' }), - }, - { - name: 'SecretsManagerClient', - client: new SecretsManagerClient(options), - command: new GetSecretValueCommand({ SecretId: 'test' }), - }, - ])( - `using $name, add powertools user agent to request header at the end`, - async ({ client, command }) => { - addUserAgentMiddleware(client, 'my-feature'); - - expect(client.middlewareStack.identify()).toContain( - 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT' - ); - - client.middlewareStack.addRelativeTo( - assertMiddleware('my-feature'), - assertMiddlewareOptions - ); - - await runCommand(client, command); - } - ); - - it('should not throw error, when client fails to add middleware', () => { - // create mock client that throws error when adding middleware - const client = { - middlewareStack: { - addRelativeTo: () => { - throw new Error('test'); - }, - }, - }; - - expect(() => addUserAgentMiddleware(client, 'my-feature')).not.toThrow(); - }); - - it('should no-op if we add the middleware twice', async () => { - const client = new LambdaClient(options); - const command = new InvokeCommand({ FunctionName: 'test', Payload: '' }); - addUserAgentMiddleware(client, 'my-feature'); - addUserAgentMiddleware(client, 'your-feature'); - - client.middlewareStack.addRelativeTo( - assertMiddleware('my-feature'), - assertMiddlewareOptions - ); - await runCommand(client, command); - - expect(client.middlewareStack.identify()).toContain( - 'addPowertoolsToUserAgent: POWERTOOLS,USER_AGENT' - ); - }); -}); diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index c544958e10..b4bd68e07f 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -17,7 +17,10 @@ import { import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import { IdempotencyRecord } from './IdempotencyRecord'; import { BasePersistenceLayer } from './BasePersistenceLayer'; -import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; +import { + addUserAgentMiddleware, + isSdkClient, +} from '@aws-lambda-powertools/commons'; /** * DynamoDB persistence layer for idempotency records. @@ -78,17 +81,16 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { this.staticPkValue = config.staticPkValue ?? `idempotency#${this.idempotencyKeyPrefix}`; + this.client = new DynamoDBClient(config?.clientConfig ?? {}); if (config?.awsSdkV3Client) { - if (config?.awsSdkV3Client instanceof DynamoDBClient) { + if (isSdkClient(config.awsSdkV3Client)) { this.client = config.awsSdkV3Client; } else { - throw Error('Not valid DynamoDBClient provided.'); + console.warn( + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); } - } else { - this.clientConfig = config?.clientConfig ?? {}; - this.client = new DynamoDBClient(this.clientConfig); } - addUserAgentMiddleware(this.client, 'idempotency'); } diff --git a/packages/idempotency/src/types/DynamoDBPersistence.ts b/packages/idempotency/src/types/DynamoDBPersistence.ts index a3a753b9da..3a30a73639 100644 --- a/packages/idempotency/src/types/DynamoDBPersistence.ts +++ b/packages/idempotency/src/types/DynamoDBPersistence.ts @@ -40,6 +40,9 @@ interface DynamoDBPersistenceOptionsBase { interface DynamoDBPersistenceOptionsWithClientConfig extends DynamoDBPersistenceOptionsBase { awsSdkV3Client?: never; + /** + * Optional configuration to pass during client initialization, e.g. AWS region. It accepts the same configuration object as the AWS SDK v3 client (`DynamoDBClient`). + */ clientConfig?: DynamoDBClientConfig; } @@ -53,6 +56,9 @@ interface DynamoDBPersistenceOptionsWithClientConfig */ interface DynamoDBPersistenceOptionsWithClientInstance extends DynamoDBPersistenceOptionsBase { + /** + * Optional AWS SDK v3 client instance (`DynamoDBClient`) to use for DynamoDB operations. If not provided, we will create a new instance of `DynamoDBClient`. + */ awsSdkV3Client?: DynamoDBClient; clientConfig?: never; } diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index d165af4b48..aa817e7b77 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -21,11 +21,17 @@ import { } from '@aws-sdk/client-dynamodb'; import { marshall } from '@aws-sdk/util-dynamodb'; import { mockClient } from 'aws-sdk-client-mock'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; import 'aws-sdk-client-mock-jest'; const getFutureTimestamp = (seconds: number): number => new Date().getTime() + seconds * 1000; +jest.mock('@aws-lambda-powertools/commons', () => ({ + ...jest.requireActual('@aws-lambda-powertools/commons'), + addUserAgentMiddleware: jest.fn(), +})); + describe('Class: DynamoDBPersistenceLayer', () => { const ENVIRONMENT_VARIABLES = process.env; const client = mockClient(DynamoDBClient); @@ -161,37 +167,47 @@ describe('Class: DynamoDBPersistenceLayer', () => { client: awsSdkV3Client, }) ); + expect(addUserAgentMiddleware).toHaveBeenCalledWith( + awsSdkV3Client, + 'idempotency' + ); }); - test('when passed an invalid AWS SDK client, it throws an error', () => { - // Act & Assess - expect(() => { - new TestDynamoDBPersistenceLayer({ - tableName: dummyTableName, - awsSdkV3Client: {} as DynamoDBClient, - }); - }).toThrow(); - }); - - test('when passed a client config it stores it for later use', () => { + it('falls back on a new SDK client and logs a warning when an unknown object is provided instead of a client', async () => { // Prepare - const clientConfig = { - region: 'someRegion', + const awsSdkV3Client = {}; + const options: DynamoDBPersistenceOptions = { + tableName: dummyTableName, + awsSdkV3Client: awsSdkV3Client as DynamoDBClient, }; + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); // Act - const persistenceLayer = new TestDynamoDBPersistenceLayer({ - tableName: dummyTableName, - clientConfig, - }); + const persistenceLayer = new TestDynamoDBPersistenceLayer(options); // Assess expect(persistenceLayer).toEqual( expect.objectContaining({ tableName: dummyTableName, - clientConfig, + client: expect.objectContaining({ + config: expect.objectContaining({ + serviceId: 'DynamoDB', + }), + }), }) ); + expect(consoleWarnSpy).toHaveBeenNthCalledWith( + 1, + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); + expect(addUserAgentMiddleware).toHaveBeenCalledWith( + expect.objectContaining({ + config: expect.objectContaining({ + serviceId: 'DynamoDB', + }), + }), + 'idempotency' + ); }); }); diff --git a/packages/parameters/src/appconfig/AppConfigProvider.ts b/packages/parameters/src/appconfig/AppConfigProvider.ts index 46b80cdaaf..ec7502697f 100644 --- a/packages/parameters/src/appconfig/AppConfigProvider.ts +++ b/packages/parameters/src/appconfig/AppConfigProvider.ts @@ -10,7 +10,10 @@ import type { AppConfigGetOptions, AppConfigGetOutput, } from '../types/AppConfigProvider'; -import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; +import { + addUserAgentMiddleware, + isSdkClient, +} from '@aws-lambda-powertools/commons'; /** * ## Intro @@ -18,15 +21,9 @@ import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; * * ## Getting started * - * This utility supports AWS SDK v3 for JavaScript only. This allows the utility to be modular, and you to install only + * This utility supports AWS SDK v3 for JavaScript only (`@aws-sdk/client-appconfigdata`). This allows the utility to be modular, and you to install only * the SDK packages you need and keep your bundle size small. * - * To use the provider, you must install the Parameters utility and the AWS SDK v3 for JavaScript for AppConfig: - * - * ```sh - * npm install @aws-lambda-powertools/parameters @aws-sdk/client-appconfigdata - * ``` - * * ## Basic usage * * @example @@ -201,16 +198,16 @@ class AppConfigProvider extends BaseProvider { */ public constructor(options: AppConfigProviderOptions) { super(); + this.client = new AppConfigDataClient(options.clientConfig || {}); if (options?.awsSdkV3Client) { - if (options?.awsSdkV3Client instanceof AppConfigDataClient) { + if (isSdkClient(options.awsSdkV3Client)) { this.client = options.awsSdkV3Client; } else { - throw Error('Not a valid AppConfigDataClient provided'); + console.warn( + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); } - } else { - this.client = new AppConfigDataClient(options.clientConfig || {}); } - addUserAgentMiddleware(this.client, 'parameters'); this.application = diff --git a/packages/parameters/src/dynamodb/DynamoDBProvider.ts b/packages/parameters/src/dynamodb/DynamoDBProvider.ts index e95afb3142..2a9dbe98a3 100644 --- a/packages/parameters/src/dynamodb/DynamoDBProvider.ts +++ b/packages/parameters/src/dynamodb/DynamoDBProvider.ts @@ -18,7 +18,10 @@ import type { } from '@aws-sdk/client-dynamodb'; import type { PaginationConfiguration } from '@aws-sdk/types'; import type { JSONValue } from '@aws-lambda-powertools/commons'; -import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; +import { + addUserAgentMiddleware, + isSdkClient, +} from '@aws-lambda-powertools/commons'; /** * ## Intro @@ -26,15 +29,9 @@ import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; * * ## Getting started * - * This utility supports AWS SDK v3 for JavaScript only. This allows the utility to be modular, and you to install only + * This utility supports AWS SDK v3 for JavaScript only (`@aws-sdk/client-dynamodb` and `@aws-sdk/util-dynamodb`). This allows the utility to be modular, and you to install only * the SDK packages you need and keep your bundle size small. * - * To use the provider, you must install the Parameters utility and the AWS SDK v3 for JavaScript for AppConfig: - * - * ```sh - * npm install @aws-lambda-powertools/parameters @aws-sdk/client-dynamodb @aws-sdk/util-dynamodb - * ``` - * * ## Basic usage * * Retrieve a value from DynamoDB: @@ -256,17 +253,16 @@ class DynamoDBProvider extends BaseProvider { public constructor(config: DynamoDBProviderOptions) { super(); + this.client = new DynamoDBClient(config?.clientConfig || {}); if (config?.awsSdkV3Client) { - if (config?.awsSdkV3Client instanceof DynamoDBClient) { + if (isSdkClient(config.awsSdkV3Client)) { this.client = config.awsSdkV3Client; } else { - throw Error('Not a valid DynamoDBClient provided'); + console.warn( + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); } - } else { - const clientConfig = config?.clientConfig || {}; - this.client = new DynamoDBClient(clientConfig); } - addUserAgentMiddleware(this.client, 'parameters'); this.tableName = config.tableName; diff --git a/packages/parameters/src/secrets/SecretsProvider.ts b/packages/parameters/src/secrets/SecretsProvider.ts index 6f82e1615e..594ab13fa4 100644 --- a/packages/parameters/src/secrets/SecretsProvider.ts +++ b/packages/parameters/src/secrets/SecretsProvider.ts @@ -9,7 +9,10 @@ import type { SecretsGetOptions, SecretsGetOutput, } from '../types/SecretsProvider'; -import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; +import { + addUserAgentMiddleware, + isSdkClient, +} from '@aws-lambda-powertools/commons'; /** * ## Intro @@ -17,15 +20,9 @@ import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; * * ## Getting started * - * This utility supports AWS SDK v3 for JavaScript only. This allows the utility to be modular, and you to install only + * This utility supports AWS SDK v3 for JavaScript only (`@aws-sdk/client-secrets-manager`). This allows the utility to be modular, and you to install only * the SDK packages you need and keep your bundle size small. * - * To use the provider, you must install the Parameters utility and the AWS SDK v3 for JavaScript for Secrets Manager: - * - * ```sh - * npm install @aws-lambda-powertools/parameters @aws-sdk/client-secrets-manager - * ``` - * * ## Basic usage * * @example @@ -162,17 +159,16 @@ class SecretsProvider extends BaseProvider { public constructor(config?: SecretsProviderOptions) { super(); + this.client = new SecretsManagerClient(config?.clientConfig || {}); if (config?.awsSdkV3Client) { - if (config?.awsSdkV3Client instanceof SecretsManagerClient) { + if (isSdkClient(config.awsSdkV3Client)) { this.client = config.awsSdkV3Client; } else { - throw Error('Not a valid SecretsManagerClient provided'); + console.warn( + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); } - } else { - const clientConfig = config?.clientConfig || {}; - this.client = new SecretsManagerClient(clientConfig); } - addUserAgentMiddleware(this.client, 'parameters'); } diff --git a/packages/parameters/src/ssm/SSMProvider.ts b/packages/parameters/src/ssm/SSMProvider.ts index 1a2f1c5ed5..bd713f7bf2 100644 --- a/packages/parameters/src/ssm/SSMProvider.ts +++ b/packages/parameters/src/ssm/SSMProvider.ts @@ -27,7 +27,10 @@ import type { SSMGetParametersByNameFromCacheOutputType, } from '../types/SSMProvider'; import type { PaginationConfiguration } from '@aws-sdk/types'; -import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; +import { + addUserAgentMiddleware, + isSdkClient, +} from '@aws-lambda-powertools/commons'; /** * ## Intro @@ -35,15 +38,9 @@ import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; * * ## Getting started * - * This utility supports AWS SDK v3 for JavaScript only. This allows the utility to be modular, and you to install only + * This utility supports AWS SDK v3 for JavaScript only (`@aws-sdk/client-ssm`). This allows the utility to be modular, and you to install only * the SDK packages you need and keep your bundle size small. * - * To use the provider, you must install the Parameters utility and the AWS SDK v3 for JavaScript for AppConfig: - * - * ```sh - * npm install @aws-lambda-powertools/parameters @aws-sdk/client-ssm - * ``` - * * ## Basic usage * * Retrieve a parameter from SSM: @@ -281,17 +278,16 @@ class SSMProvider extends BaseProvider { public constructor(config?: SSMProviderOptions) { super(); + this.client = new SSMClient(config?.clientConfig || {}); if (config?.awsSdkV3Client) { - if (config?.awsSdkV3Client instanceof SSMClient) { + if (isSdkClient(config.awsSdkV3Client)) { this.client = config.awsSdkV3Client; } else { - throw Error('Not a valid SSMClient provided'); + console.warn( + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); } - } else { - const clientConfig = config?.clientConfig || {}; - this.client = new SSMClient(clientConfig); } - addUserAgentMiddleware(this.client, 'parameters'); } diff --git a/packages/parameters/src/types/AppConfigProvider.ts b/packages/parameters/src/types/AppConfigProvider.ts index b16b5156a5..95a362af2d 100644 --- a/packages/parameters/src/types/AppConfigProvider.ts +++ b/packages/parameters/src/types/AppConfigProvider.ts @@ -28,6 +28,9 @@ interface AppConfigProviderOptionsBaseInterface { */ interface AppConfigProviderOptionsWithClientConfig extends AppConfigProviderOptionsBaseInterface { + /** + * Optional configuration to pass during client initialization, e.g. AWS region. It accepts the same configuration object as the AWS SDK v3 client (`AppConfigDataClient`). + */ clientConfig?: AppConfigDataClientConfig; awsSdkV3Client?: never; } @@ -42,6 +45,9 @@ interface AppConfigProviderOptionsWithClientConfig */ interface AppConfigProviderOptionsWithClientInstance extends AppConfigProviderOptionsBaseInterface { + /** + * Optional AWS SDK v3 client instance (`AppConfigDataClient`) to use for AppConfig operations. If not provided, we will create a new instance of `AppConfigDataClient`. + */ awsSdkV3Client?: AppConfigDataClient; clientConfig?: never; } diff --git a/packages/parameters/src/types/DynamoDBProvider.ts b/packages/parameters/src/types/DynamoDBProvider.ts index 2ddcd4e819..420f31343a 100644 --- a/packages/parameters/src/types/DynamoDBProvider.ts +++ b/packages/parameters/src/types/DynamoDBProvider.ts @@ -36,6 +36,9 @@ interface DynamoDBProviderOptionsBase { */ interface DynamoDBProviderOptionsWithClientConfig extends DynamoDBProviderOptionsBase { + /** + * Optional configuration to pass during client initialization, e.g. AWS region. It accepts the same configuration object as the AWS SDK v3 client (`DynamoDBClient`). + */ clientConfig?: DynamoDBClientConfig; awsSdkV3Client?: never; } @@ -50,6 +53,9 @@ interface DynamoDBProviderOptionsWithClientConfig */ interface DynamoDBProviderOptionsWithClientInstance extends DynamoDBProviderOptionsBase { + /** + * Optional AWS SDK v3 client instance (`DynamoDBClient`) to use for DynamoDB operations. If not provided, we will create a new instance of `DynamoDBClient`. + */ awsSdkV3Client?: DynamoDBClient; clientConfig?: never; } diff --git a/packages/parameters/src/types/SSMProvider.ts b/packages/parameters/src/types/SSMProvider.ts index e677ff821f..501dc6de15 100644 --- a/packages/parameters/src/types/SSMProvider.ts +++ b/packages/parameters/src/types/SSMProvider.ts @@ -19,6 +19,9 @@ import type { * @property {never} [awsSdkV3Client] - This property should never be passed. */ interface SSMProviderOptionsWithClientConfig { + /** + * Optional configuration to pass during client initialization, e.g. AWS region. It accepts the same configuration object as the AWS SDK v3 client (`SSMClient`). + */ clientConfig?: SSMClientConfig; awsSdkV3Client?: never; } @@ -31,6 +34,9 @@ interface SSMProviderOptionsWithClientConfig { * @property {never} [clientConfig] - This property should never be passed. */ interface SSMProviderOptionsWithClientInstance { + /** + * Optional AWS SDK v3 client instance (`SSMClient`) to use for SSM operations. If not provided, we will create a new instance of `SSMClient`. + */ awsSdkV3Client?: SSMClient; clientConfig?: never; } diff --git a/packages/parameters/src/types/SecretsProvider.ts b/packages/parameters/src/types/SecretsProvider.ts index a9e5c1ef98..34129dbb6c 100644 --- a/packages/parameters/src/types/SecretsProvider.ts +++ b/packages/parameters/src/types/SecretsProvider.ts @@ -14,6 +14,9 @@ import type { GetOptionsInterface, TransformOptions } from './BaseProvider'; * @property {never} [awsSdkV3Client] - This property should never be passed. */ interface SecretsProviderOptionsWithClientConfig { + /** + * Optional configuration to pass during client initialization, e.g. AWS region. It accepts the same configuration object as the AWS SDK v3 client (`SecretsManagerClient`). + */ clientConfig?: SecretsManagerClientConfig; awsSdkV3Client?: never; } @@ -27,6 +30,9 @@ interface SecretsProviderOptionsWithClientConfig { * @property {never} [clientConfig] - This property should never be passed. */ interface SecretsProviderOptionsWithClientInstance { + /** + * Optional AWS SDK v3 client instance (`SecretsManagerClient`) to use for Secrets Manager operations. If not provided, we will create a new instance of `SecretsManagerClient`. + */ awsSdkV3Client?: SecretsManagerClient; clientConfig?: never; } diff --git a/packages/parameters/tests/unit/AppConfigProvider.test.ts b/packages/parameters/tests/unit/AppConfigProvider.test.ts index e2844603d8..cb6b5ad237 100644 --- a/packages/parameters/tests/unit/AppConfigProvider.test.ts +++ b/packages/parameters/tests/unit/AppConfigProvider.test.ts @@ -13,9 +13,14 @@ import { } from '@aws-sdk/client-appconfigdata'; import { Uint8ArrayBlobAdapter } from '@smithy/util-stream'; import { mockClient } from 'aws-sdk-client-mock'; -import * as UserAgentMiddleware from '@aws-lambda-powertools/commons/lib/userAgentMiddleware'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; import 'aws-sdk-client-mock-jest'; +jest.mock('@aws-lambda-powertools/commons', () => ({ + ...jest.requireActual('@aws-lambda-powertools/commons'), + addUserAgentMiddleware: jest.fn(), +})); + describe('Class: AppConfigProvider', () => { const client = mockClient(AppConfigDataClient); @@ -35,11 +40,6 @@ describe('Class: AppConfigProvider', () => { environment: 'MyAppProdEnv', }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new AppConfigProvider(options); @@ -49,8 +49,7 @@ describe('Class: AppConfigProvider', () => { serviceId: 'AppConfigData', }) ); - - expect(userAgentSpy).toHaveBeenCalled(); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides a client config in the options, the class instantiates a new client with client config options', async () => { @@ -59,32 +58,23 @@ describe('Class: AppConfigProvider', () => { application: 'MyApp', environment: 'MyAppProdEnv', clientConfig: { - serviceId: 'with-client-config', + region: 'eu-south-2', }, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new AppConfigProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-client-config', - }) - ); - - expect(userAgentSpy).toHaveBeenCalled(); + expect(provider.client.config.region()).resolves.toEqual('eu-south-2'); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides an SDK client in the options, the class instantiates with it', async () => { // Prepare const awsSdkV3Client = new AppConfigDataClient({ - serviceId: 'with-custom-sdk-client', + endpoint: 'http://localhost:8000', + serviceId: 'Foo', }); const options: AppConfigProviderOptions = { @@ -93,25 +83,18 @@ describe('Class: AppConfigProvider', () => { awsSdkV3Client: awsSdkV3Client, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new AppConfigProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-custom-sdk-client', - }) + expect(provider.client).toEqual(awsSdkV3Client); + expect(addUserAgentMiddleware).toHaveBeenCalledWith( + awsSdkV3Client, + 'parameters' ); - - expect(userAgentSpy).toHaveBeenCalledWith(awsSdkV3Client, 'parameters'); }); - test('when the user provides NOT an SDK client in the options, it throws an error', async () => { + it('falls back on a new SDK client and logs a warning when an unknown object is provided instead of a client', async () => { // Prepare const awsSdkV3Client = {}; const options: AppConfigProviderOptions = { @@ -119,11 +102,22 @@ describe('Class: AppConfigProvider', () => { environment: 'MyAppProdEnv', awsSdkV3Client: awsSdkV3Client as AppConfigDataClient, }; + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); - // Act & Assess - expect(() => { - new AppConfigProvider(options); - }).toThrow(); + // Act + const provider = new AppConfigProvider(options); + + // Assess + expect(provider.client.config).toEqual( + expect.objectContaining({ + serviceId: 'AppConfigData', + }) + ); + expect(consoleWarnSpy).toHaveBeenNthCalledWith( + 1, + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); }); diff --git a/packages/parameters/tests/unit/DynamoDBProvider.test.ts b/packages/parameters/tests/unit/DynamoDBProvider.test.ts index 41c7c044fd..b8112b8908 100644 --- a/packages/parameters/tests/unit/DynamoDBProvider.test.ts +++ b/packages/parameters/tests/unit/DynamoDBProvider.test.ts @@ -15,9 +15,13 @@ import type { } from '@aws-sdk/client-dynamodb'; import type { DynamoDBProviderOptions } from '../../src/types/DynamoDBProvider'; import { marshall } from '@aws-sdk/util-dynamodb'; -import * as UserAgentMiddleware from '@aws-lambda-powertools/commons/lib/userAgentMiddleware'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; import { mockClient } from 'aws-sdk-client-mock'; import 'aws-sdk-client-mock-jest'; +jest.mock('@aws-lambda-powertools/commons', () => ({ + ...jest.requireActual('@aws-lambda-powertools/commons'), + addUserAgentMiddleware: jest.fn(), +})); describe('Class: DynamoDBProvider', () => { beforeEach(() => { @@ -31,11 +35,6 @@ describe('Class: DynamoDBProvider', () => { tableName: 'test-table', }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new DynamoDBProvider(options); @@ -45,8 +44,7 @@ describe('Class: DynamoDBProvider', () => { serviceId: 'DynamoDB', }) ); - - expect(userAgentSpy).toHaveBeenCalled(); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides a client config in the options, the class instantiates a new client with client config options', async () => { @@ -54,39 +52,25 @@ describe('Class: DynamoDBProvider', () => { const options: DynamoDBProviderOptions = { tableName: 'test-table', clientConfig: { - serviceId: 'with-client-config', + region: 'eu-south-2', }, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new DynamoDBProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-client-config', - }) - ); - - expect(userAgentSpy).toHaveBeenCalled(); + expect(provider.client.config.region()).resolves.toEqual('eu-south-2'); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides an SDK client in the options, the class instantiates with it', async () => { // Prepare const awsSdkV3Client = new DynamoDBClient({ - serviceId: 'with-custom-sdk-client', + endpoint: 'http://localhost:8000', + serviceId: 'Foo', }); - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - const options: DynamoDBProviderOptions = { tableName: 'test-table', awsSdkV3Client: awsSdkV3Client, @@ -96,26 +80,36 @@ describe('Class: DynamoDBProvider', () => { const provider = new DynamoDBProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-custom-sdk-client', - }) + expect(provider.client).toEqual(awsSdkV3Client); + expect(addUserAgentMiddleware).toHaveBeenCalledWith( + awsSdkV3Client, + 'parameters' ); - expect(userAgentSpy).toHaveBeenCalledWith(awsSdkV3Client, 'parameters'); }); - test('when the user provides NOT an SDK client in the options, it throws an error', async () => { + it('falls back on a new SDK client and logs a warning when an unknown object is provided instead of a client', async () => { // Prepare const awsSdkV3Client = {}; const options: DynamoDBProviderOptions = { tableName: 'test-table', awsSdkV3Client: awsSdkV3Client as DynamoDBClient, }; + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); + + // Act + const provider = new DynamoDBProvider(options); - // Act & Assess - expect(() => { - new DynamoDBProvider(options); - }).toThrow(); + // Assess + expect(provider.client.config).toEqual( + expect.objectContaining({ + serviceId: 'DynamoDB', + }) + ); + expect(consoleWarnSpy).toHaveBeenNthCalledWith( + 1, + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); }); diff --git a/packages/parameters/tests/unit/SSMProvider.test.ts b/packages/parameters/tests/unit/SSMProvider.test.ts index cd48aada3f..4615907750 100644 --- a/packages/parameters/tests/unit/SSMProvider.test.ts +++ b/packages/parameters/tests/unit/SSMProvider.test.ts @@ -22,9 +22,13 @@ import type { } from '../../src/types/SSMProvider'; import { ExpirableValue } from '../../src/base/ExpirableValue'; import { toBase64 } from '@aws-sdk/util-base64-node'; -import * as UserAgentMiddleware from '@aws-lambda-powertools/commons/lib/userAgentMiddleware'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; const encoder = new TextEncoder(); +jest.mock('@aws-lambda-powertools/commons', () => ({ + ...jest.requireActual('@aws-lambda-powertools/commons'), + addUserAgentMiddleware: jest.fn(), +})); describe('Class: SSMProvider', () => { const ENVIRONMENT_VARIABLES = process.env; @@ -38,10 +42,6 @@ describe('Class: SSMProvider', () => { test('when the class instantiates without SDK client and client config it has default options', async () => { // Prepare const options: SSMProviderOptions = {}; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); // Act const provider = new SSMProvider(options); @@ -52,70 +52,69 @@ describe('Class: SSMProvider', () => { serviceId: 'SSM', }) ); - expect(userAgentSpy).toHaveBeenCalled(); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides a client config in the options, the class instantiates a new client with client config options', async () => { // Prepare const options: SSMProviderOptions = { clientConfig: { - serviceId: 'with-client-config', + region: 'eu-south-2', }, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); // Act const provider = new SSMProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-client-config', - }) - ); - expect(userAgentSpy).toHaveBeenCalled(); + expect(provider.client.config.region()).resolves.toEqual('eu-south-2'); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides an SDK client in the options, the class instantiates with it', async () => { // Prepare const awsSdkV3Client = new SSMClient({ - serviceId: 'with-custom-sdk-client', + endpoint: 'http://localhost:3000', + serviceId: 'Foo', }); const options: SSMProviderOptions = { awsSdkV3Client: awsSdkV3Client, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); // Act const provider = new SSMProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-custom-sdk-client', - }) + expect(provider.client).toEqual(awsSdkV3Client); + expect(addUserAgentMiddleware).toHaveBeenCalledWith( + awsSdkV3Client, + 'parameters' ); - expect(userAgentSpy).toHaveBeenCalledWith(awsSdkV3Client, 'parameters'); }); - test('when the user provides NOT an SDK client in the options, it throws an error', async () => { + it('falls back on a new SDK client and logs a warning when an unknown object is provided instead of a client', async () => { // Prepare const awsSdkV3Client = {}; const options: SSMProviderOptions = { awsSdkV3Client: awsSdkV3Client as SSMClient, }; + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); - // Act & Assess - expect(() => { - new SSMProvider(options); - }).toThrow(); + // Act + const provider = new SSMProvider(options); + + // Assess + expect(provider.client.config).toEqual( + expect.objectContaining({ + serviceId: 'SSM', + }) + ); + expect(consoleWarnSpy).toHaveBeenNthCalledWith( + 1, + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); }); diff --git a/packages/parameters/tests/unit/SecretsProvider.test.ts b/packages/parameters/tests/unit/SecretsProvider.test.ts index f3238afcfc..9bfd254537 100644 --- a/packages/parameters/tests/unit/SecretsProvider.test.ts +++ b/packages/parameters/tests/unit/SecretsProvider.test.ts @@ -12,9 +12,13 @@ import type { GetSecretValueCommandInput } from '@aws-sdk/client-secrets-manager import type { SecretsProviderOptions } from '../../src/types/SecretsProvider'; import { mockClient } from 'aws-sdk-client-mock'; import 'aws-sdk-client-mock-jest'; -import * as UserAgentMiddleware from '@aws-lambda-powertools/commons/lib/userAgentMiddleware'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; const encoder = new TextEncoder(); +jest.mock('@aws-lambda-powertools/commons', () => ({ + ...jest.requireActual('@aws-lambda-powertools/commons'), + addUserAgentMiddleware: jest.fn(), +})); describe('Class: SecretsProvider', () => { const client = mockClient(SecretsManagerClient); @@ -28,11 +32,6 @@ describe('Class: SecretsProvider', () => { // Prepare const options: SecretsProviderOptions = {}; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new SecretsProvider(options); @@ -42,72 +41,69 @@ describe('Class: SecretsProvider', () => { serviceId: 'Secrets Manager', }) ); - expect(userAgentSpy).toHaveBeenCalled(); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides a client config in the options, the class instantiates a new client with client config options', async () => { // Prepare const options: SecretsProviderOptions = { clientConfig: { - serviceId: 'with-client-config', + region: 'eu-south-2', }, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new SecretsProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-client-config', - }) - ); - expect(userAgentSpy).toHaveBeenCalled(); + expect(provider.client.config.region()).resolves.toEqual('eu-south-2'); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); test('when the user provides an SDK client in the options, the class instantiates with it', async () => { // Prepare const awsSdkV3Client = new SecretsManagerClient({ - serviceId: 'with-custom-sdk-client', + endpoint: 'http://localhost:3000', + serviceId: 'Foo', }); const options: SecretsProviderOptions = { awsSdkV3Client: awsSdkV3Client, }; - const userAgentSpy = jest.spyOn( - UserAgentMiddleware, - 'addUserAgentMiddleware' - ); - // Act const provider = new SecretsProvider(options); // Assess - expect(provider.client.config).toEqual( - expect.objectContaining({ - serviceId: 'with-custom-sdk-client', - }) + expect(provider.client).toEqual(awsSdkV3Client); + expect(addUserAgentMiddleware).toHaveBeenCalledWith( + awsSdkV3Client, + 'parameters' ); - expect(userAgentSpy).toHaveBeenCalledWith(awsSdkV3Client, 'parameters'); }); - test('when the user provides NOT an SDK client in the options, it throws an error', async () => { + it('falls back on a new SDK client and logs a warning when an unknown object is provided instead of a client', async () => { // Prepare const awsSdkV3Client = {}; const options: SecretsProviderOptions = { awsSdkV3Client: awsSdkV3Client as SecretsManagerClient, }; + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); - // Act & Assess - expect(() => { - new SecretsProvider(options); - }).toThrow(); + // Act + const provider = new SecretsProvider(options); + + // Assess + expect(provider.client.config).toEqual( + expect.objectContaining({ + serviceId: 'Secrets Manager', + }) + ); + expect(consoleWarnSpy).toHaveBeenNthCalledWith( + 1, + 'awsSdkV3Client is not an AWS SDK v3 client, using default client' + ); + expect(addUserAgentMiddleware).toHaveBeenCalled(); }); }); diff --git a/packages/testing/package.json b/packages/testing/package.json index e4834088b4..7a5be71f29 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -44,6 +44,8 @@ "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/packages/testing#readme", "dependencies": { "@aws-cdk/cli-lib-alpha": "^2.96.1-alpha.0", + "@aws-sdk/client-lambda": "^3.418.0", + "@smithy/util-utf8": "^2.0.0", "aws-cdk-lib": "^2.96.1", "esbuild": "^0.19.3" } diff --git a/packages/testing/src/invokeTestFunction.ts b/packages/testing/src/invokeTestFunction.ts index 46a54d9553..4b333d756d 100644 --- a/packages/testing/src/invokeTestFunction.ts +++ b/packages/testing/src/invokeTestFunction.ts @@ -1,5 +1,5 @@ import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; -import { fromUtf8 } from '@aws-sdk/util-utf8-node'; +import { fromUtf8 } from '@smithy/util-utf8'; import { TestInvocationLogs } from './TestInvocationLogs'; type InvokeTestFunctionOptions = { diff --git a/packages/tracer/tests/unit/ProviderService.test.ts b/packages/tracer/tests/unit/ProviderService.test.ts index 6d32f510ec..1b74701b26 100644 --- a/packages/tracer/tests/unit/ProviderService.test.ts +++ b/packages/tracer/tests/unit/ProviderService.test.ts @@ -24,7 +24,7 @@ import { import http from 'http'; import https from 'https'; import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; -import * as UserAgentMiddleware from '@aws-lambda-powertools/commons/lib/userAgentMiddleware'; +import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; jest.mock('aws-xray-sdk-core', () => ({ ...jest.requireActual('aws-xray-sdk-core'), @@ -42,6 +42,11 @@ jest.mock('aws-xray-sdk-core', () => ({ setSegment: jest.fn(), })); +jest.mock('@aws-lambda-powertools/commons', () => ({ + ...jest.requireActual('@aws-lambda-powertools/commons'), + addUserAgentMiddleware: jest.fn(), +})); + describe('Class: ProviderService', () => { beforeEach(() => { jest.clearAllMocks(); @@ -92,16 +97,16 @@ describe('Class: ProviderService', () => { // Prepare const provider: ProviderService = new ProviderService(); - // spy on addUserAgentMiddleware - const spy = jest.spyOn(UserAgentMiddleware, 'addUserAgentMiddleware'); - // Act const dynamoDBClient = new DynamoDBClient({}); provider.captureAWSv3Client(dynamoDBClient); // Assess - expect(spy).toHaveBeenCalledTimes(1); - expect(spy).toHaveBeenCalledWith(dynamoDBClient, 'tracer'); + expect(addUserAgentMiddleware).toHaveBeenNthCalledWith( + 1, + dynamoDBClient, + 'tracer' + ); }); });