From 54a679aece1676c1f3ec33dd28d314b0ee6598bc Mon Sep 17 00:00:00 2001 From: will Farrell Date: Thu, 30 Apr 2026 05:06:02 -0600 Subject: [PATCH 1/8] chore: dep update Signed-off-by: will Farrell --- package-lock.json | 115 ++++++++++++++++------------------------------ package.json | 1 - 2 files changed, 40 insertions(+), 76 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a9475e12..0c2892e3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2017,15 +2017,15 @@ "license": "MIT OR Apache-2.0" }, "node_modules/@commitlint/cli": { - "version": "20.5.2", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.2.tgz", - "integrity": "sha512-IXr5xd3IX8SEG936P8gcpozRplkDeDSwJlt8UvoY1winwIy2udTbQ/cOCgbaaxcjdDqVoS29VUcz/wkwnSozbA==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-20.5.3.tgz", + "integrity": "sha512-OJdL0EXWD5y9LPa0nr/geOwzaS8BsdaybKkcloB0JgsguGxNv2R+hC2FTPqrAcprg35zF33KOQerY0x8W1aesA==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/format": "^20.5.0", - "@commitlint/lint": "^20.5.0", - "@commitlint/load": "^20.5.2", + "@commitlint/lint": "^20.5.3", + "@commitlint/load": "^20.5.3", "@commitlint/read": "^20.5.0", "@commitlint/types": "^20.5.0", "tinyexec": "^1.0.0", @@ -2039,9 +2039,9 @@ } }, "node_modules/@commitlint/config-conventional": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.0.tgz", - "integrity": "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-20.5.3.tgz", + "integrity": "sha512-j34Qqeaa152chJgz2ysyk0BCpHenJn1lV0Rx0VXf8k3ccQcED+48EZrzMvo9jLmJUyBrrBwvu89I+2er4gW7QQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2067,18 +2067,14 @@ } }, "node_modules/@commitlint/ensure": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.0.tgz", - "integrity": "sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-20.5.3.tgz", + "integrity": "sha512-4i4AgNvH62owG9MwSiWKrle7HGNpBHHdLnWFIp5fTsHUYe5kRuh15t08L/0pdbbrRk8JKXQxxN4hZQcn+szkrw==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^20.5.0", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" + "es-toolkit": "^1.46.0" }, "engines": { "node": ">=v18" @@ -2123,15 +2119,15 @@ } }, "node_modules/@commitlint/lint": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.0.tgz", - "integrity": "sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-20.5.3.tgz", + "integrity": "sha512-M7JbWBNr2gXKaPc4i/KipsuW1gkDHpj35KPjWtKy3Z+2AQw5wu1gBi1LIO0uoaij67CqY4K8PxPZSGens4evCw==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/is-ignored": "^20.5.0", "@commitlint/parse": "^20.5.0", - "@commitlint/rules": "^20.5.0", + "@commitlint/rules": "^20.5.3", "@commitlint/types": "^20.5.0" }, "engines": { @@ -2139,20 +2135,20 @@ } }, "node_modules/@commitlint/load": { - "version": "20.5.2", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.2.tgz", - "integrity": "sha512-zmr0RGDz7vThxW1I8ohb9yBjnGuH9mqwJpn21hInjGla+IlLOkS9ey0+dD5HlkzFlY0lX2NYdA2lDW6/0rO7Gw==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-20.5.3.tgz", + "integrity": "sha512-1FDZWuKyu98Myb8i7Tp31jPU2rZpOwAdYRyJcy2KoGg7Xk2A+bgHN8smhMaaNSNkmE8fwt53BokywZq8Gv/5XQ==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/config-validator": "^20.5.0", "@commitlint/execute-rule": "^20.0.0", - "@commitlint/resolve-extends": "^20.5.2", + "@commitlint/resolve-extends": "^20.5.3", "@commitlint/types": "^20.5.0", "cosmiconfig": "^9.0.1", "cosmiconfig-typescript-loader": "^6.1.0", + "es-toolkit": "^1.46.0", "is-plain-obj": "^4.1.0", - "lodash.mergewith": "^4.6.2", "picocolors": "^1.1.1" }, "engines": { @@ -2202,17 +2198,17 @@ } }, "node_modules/@commitlint/resolve-extends": { - "version": "20.5.2", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.2.tgz", - "integrity": "sha512-8EhSCU9eNos/5cI1yg64GW79UH1c64O69AfStCsj4zqy6An/qIphVEXj4/+2M6056T8coz00f+UXFn4WUUP1HQ==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-20.5.3.tgz", + "integrity": "sha512-+ogW9v/u9JqpvAgTrLra/YTFo0KkjU6iNblF89pPsj4NebNc+DAWctsludwezI8YnsjBmfHpApSwcXprN/f/ew==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/config-validator": "^20.5.0", "@commitlint/types": "^20.5.0", + "es-toolkit": "^1.46.0", "global-directory": "^5.0.0", "import-meta-resolve": "^4.0.0", - "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0" }, "engines": { @@ -2220,13 +2216,13 @@ } }, "node_modules/@commitlint/rules": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.0.tgz", - "integrity": "sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ==", + "version": "20.5.3", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-20.5.3.tgz", + "integrity": "sha512-MPlMnb9D3wbszYMp+1hPtuhtPJndRo6I6yfkZVA4+jR8w7Kqp0u2u/Y+gzbaItx5Lltq5rw7FSZQWJMoXUC4NQ==", "dev": true, "license": "MIT", "dependencies": { - "@commitlint/ensure": "^20.5.0", + "@commitlint/ensure": "^20.5.3", "@commitlint/message": "^20.4.3", "@commitlint/to-lines": "^20.0.0", "@commitlint/types": "^20.5.0" @@ -6570,6 +6566,17 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/es-toolkit": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz", + "integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==", + "dev": true, + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, "node_modules/esbuild": { "version": "0.28.0", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", @@ -8005,48 +8012,6 @@ "dev": true, "license": "MIT" }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", diff --git a/package.json b/package.json index 6d299ab72..f9a237a58 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,6 @@ "@sveltejs/kit": { "cookie": "^0.7.2" }, - "fast-xml-parser": ">=5.7.2", "mathjs": ">=15.2.0" }, "devEngines": { From 6e8617c50de9a0f84f57a92e97c060b23598b33a Mon Sep 17 00:00:00 2001 From: will Farrell Date: Thu, 30 Apr 2026 20:46:08 -0600 Subject: [PATCH 2/8] fix: add in endpoint Signed-off-by: will Farrell --- websites/middy.js.org/static/.well-known/mcp.json | 1 + 1 file changed, 1 insertion(+) diff --git a/websites/middy.js.org/static/.well-known/mcp.json b/websites/middy.js.org/static/.well-known/mcp.json index d922df7d0..016dce36b 100644 --- a/websites/middy.js.org/static/.well-known/mcp.json +++ b/websites/middy.js.org/static/.well-known/mcp.json @@ -2,6 +2,7 @@ "name": "middy", "description": "Middy - The stylish Node.js middleware engine for AWS Lambda", "documentation": "https://middy.js.org/", + "endpoint": "https://middy.js.org/.well-known/mcp.json", "resources": [ { "name": "llms.txt", From 09e5f69e975415672967314fb96c5cac94bf15c9 Mon Sep 17 00:00:00 2001 From: will Farrell Date: Fri, 1 May 2026 06:09:12 -0600 Subject: [PATCH 3/8] feat: add in support for dsql signer Signed-off-by: will Farrell --- package-lock.json | 75 +++ packages/dsql-signer/README.md | 50 ++ packages/dsql-signer/index.d.ts | 54 ++ packages/dsql-signer/index.fuzz.js | 22 + packages/dsql-signer/index.js | 128 +++++ packages/dsql-signer/index.perf.js | 62 +++ packages/dsql-signer/index.test.js | 508 ++++++++++++++++++ packages/dsql-signer/index.tst.ts | 78 +++ packages/dsql-signer/package.json | 82 +++ packages/rds-signer/index.js | 6 +- packages/util/index.js | 10 +- .../src/components/docs/AsideNav.svelte | 1 + .../docs/best-practices/bundling/+page.md | 2 + .../docs/middlewares/dsql-signer/+page.md | 82 +++ .../routes/docs/middlewares/intro/+page.md | 1 + 15 files changed, 1156 insertions(+), 5 deletions(-) create mode 100644 packages/dsql-signer/README.md create mode 100644 packages/dsql-signer/index.d.ts create mode 100644 packages/dsql-signer/index.fuzz.js create mode 100644 packages/dsql-signer/index.js create mode 100644 packages/dsql-signer/index.perf.js create mode 100644 packages/dsql-signer/index.test.js create mode 100644 packages/dsql-signer/index.tst.ts create mode 100644 packages/dsql-signer/package.json create mode 100644 websites/middy.js.org/src/routes/docs/middlewares/dsql-signer/+page.md diff --git a/package-lock.json b/package-lock.json index 0c2892e3b..01f17b0e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1119,6 +1119,30 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/dsql-signer": { + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/dsql-signer/-/dsql-signer-3.1040.0.tgz", + "integrity": "sha512-8j19o9S88i7ZidWWZagJz/TLRMDX3sDauG+8oP3rgdR5R7QPfSW1s+gbRGc/WO27gD2UN0wsaJKnS9cVvTjv8g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/credential-provider-node": "^3.972.38", + "@aws-sdk/util-format-url": "^3.972.10", + "@smithy/config-resolver": "^4.4.17", + "@smithy/hash-node": "^4.2.14", + "@smithy/invalid-dependency": "^4.2.14", + "@smithy/node-config-provider": "^4.3.14", + "@smithy/protocol-http": "^5.3.14", + "@smithy/signature-v4": "^5.3.14", + "@smithy/types": "^4.14.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/dynamodb-codec": { "version": "3.973.7", "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.973.7.tgz", @@ -3530,6 +3554,10 @@ "resolved": "packages/do-not-wait-for-empty-event-loop", "link": true }, + "node_modules/@middy/dsql-signer": { + "resolved": "packages/dsql-signer", + "link": true + }, "node_modules/@middy/dynamodb": { "resolved": "packages/dynamodb", "link": true @@ -10932,6 +10960,53 @@ "dev": true, "license": "MIT" }, + "packages/dsql-signer": { + "name": "@middy/dsql-signer", + "version": "7.3.4", + "license": "MIT", + "dependencies": { + "@middy/util": "7.3.4" + }, + "devDependencies": { + "@aws-sdk/dsql-signer": "^3.0.0", + "@middy/core": "7.3.4", + "@types/aws-lambda": "^8.0.0", + "@types/node": "^22.0.0", + "aws-xray-sdk": "^3.3.3" + }, + "engines": { + "node": ">=22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/willfarrell" + }, + "peerDependencies": { + "@aws-sdk/dsql-signer": "^3.0.0" + }, + "peerDependenciesMeta": { + "@aws-sdk/dsql-signer": { + "optional": true + } + } + }, + "packages/dsql-signer/node_modules/@types/node": { + "version": "22.19.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.17.tgz", + "integrity": "sha512-wGdMcf+vPYM6jikpS/qhg6WiqSV/OhG+jeeHT/KlVqxYfD40iYJf9/AE1uQxVWFvU7MipKRkRv8NSHiCGgPr8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "packages/dsql-signer/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "packages/dynamodb": { "name": "@middy/dynamodb", "version": "7.3.4", diff --git a/packages/dsql-signer/README.md b/packages/dsql-signer/README.md new file mode 100644 index 000000000..5bde2e8a4 --- /dev/null +++ b/packages/dsql-signer/README.md @@ -0,0 +1,50 @@ +
+

Middy `dsql-signer` middleware

+ Middy logo +

Aurora DSQL Signer middleware for the middy framework, the stylish Node.js middleware engine for AWS Lambda

+

+ GitHub Actions unit test status + GitHub Actions dast test status + GitHub Actions perf test status + GitHub Actions sast test status + GitHub Actions lint test status +
+ npm version + npm install size + + npm weekly downloads + + npm provenance +
+ Open Source Security Foundation (OpenSSF) Scorecard + SLSA 3 + + Checked with Biome + Conventional Commits + + code coverage +
+

+

You can read the documentation at: https://middy.js.org/docs/middlewares/dsql-signer

+
+ +## Install + +```bash +npm install --save @middy/dsql-signer @aws-sdk/dsql-signer +``` + + +## Documentation and examples + +For documentation and examples, refer to the main [Middy monorepo on GitHub](https://github.com/middyjs/middy) or [Middy official website](https://middy.js.org/docs/middlewares/dsql-signer). + + +## Contributing + +Everyone is very welcome to contribute to this repository. Feel free to [raise issues](https://github.com/middyjs/middy/issues) or to [submit Pull Requests](https://github.com/middyjs/middy/pulls). + + +## License + +Licensed under [MIT License](https://github.com/middyjs/middy/blob/main/LICENSE). Copyright (c) 2017-2026 [will Farrell](https://github.com/willfarrell), [Luciano Mammino](https://github.com/lmammino), and [Middy contributors](https://github.com/middyjs/middy/graphs/contributors). diff --git a/packages/dsql-signer/index.d.ts b/packages/dsql-signer/index.d.ts new file mode 100644 index 000000000..32fb4e2d1 --- /dev/null +++ b/packages/dsql-signer/index.d.ts @@ -0,0 +1,54 @@ +// Copyright 2017 - 2026 will Farrell, Luciano Mammino, and Middy contributors. +// SPDX-License-Identifier: MIT +import type { DsqlSigner, DsqlSignerConfig } from "@aws-sdk/dsql-signer"; +import type middy from "@middy/core"; +import type { Options as MiddyOptions } from "@middy/util"; +import type { Context as LambdaContext } from "aws-lambda"; + +export type ParamType = string & { __returnType?: T }; +export declare function dsqlSignerParam(name: string): ParamType; + +export type DsqlSignerFetchConfig = DsqlSignerConfig & { username?: string }; + +export type DsqlSignerOptions = Omit< + MiddyOptions, + "fetchData" +> & { + fetchData?: { + [key: string]: DsqlSignerFetchConfig; + }; +}; + +export type Context = + TOptions extends { setToContext: true } + ? TOptions extends { fetchData: infer TFetchData } + ? LambdaContext & { + [Key in keyof TFetchData]: string; + } + : never + : LambdaContext; + +export type Internal = + TOptions extends DsqlSignerOptions + ? TOptions extends { fetchData: infer TFetchData } + ? { + [Key in keyof TFetchData]: string; + } + : {} + : {}; + +declare function dsqlSigner( + options?: TOptions, +): middy.MiddlewareObj< + unknown, + unknown, + Error, + Context, + Internal +>; + +export declare function dsqlSignerValidateOptions( + options?: Record, +): void; + +export default dsqlSigner; diff --git a/packages/dsql-signer/index.fuzz.js b/packages/dsql-signer/index.fuzz.js new file mode 100644 index 000000000..9a028581f --- /dev/null +++ b/packages/dsql-signer/index.fuzz.js @@ -0,0 +1,22 @@ +import { test } from "node:test"; +import fc from "fast-check"; +import middy from "../core/index.js"; +import middleware from "./index.js"; + +const handler = middy((event) => event).use(middleware()); +const defaultContext = { + getRemainingTimeInMillis: () => 1000, +}; + +test("fuzz `event` w/ `object`", async () => { + await fc.assert( + fc.asyncProperty(fc.object(), async (event) => { + await handler(event, defaultContext); + }), + { + numRuns: 100_000, + + examples: [], + }, + ); +}); diff --git a/packages/dsql-signer/index.js b/packages/dsql-signer/index.js new file mode 100644 index 000000000..95244babf --- /dev/null +++ b/packages/dsql-signer/index.js @@ -0,0 +1,128 @@ +// Copyright 2017 - 2026 will Farrell, Luciano Mammino, and Middy contributors. +// SPDX-License-Identifier: MIT +import { DsqlSigner } from "@aws-sdk/dsql-signer"; +import { + canPrefetch, + getCache, + getInternal, + modifyCache, + processCache, + validateOptions, +} from "@middy/util"; + +const name = "dsql-signer"; +const pkg = `@middy/${name}`; + +const defaults = { + AwsClient: DsqlSigner, + awsClientOptions: {}, + fetchData: {}, + disablePrefetch: false, + cacheKey: pkg, + cacheKeyExpiry: {}, + cacheExpiry: -1, + setToContext: false, +}; + +const optionSchema = { + type: "object", + properties: { + AwsClient: { instanceof: "Function" }, + awsClientOptions: { type: "object" }, + fetchData: { + type: "object", + additionalProperties: { + type: "object", + properties: { + hostname: { + type: "string", + pattern: + "^[a-z0-9]+\\.dsql(-[a-z]+)?\\.[a-z]{2}(-[a-z]+){1,2}-\\d+\\.on\\.aws$", + }, + username: { type: "string" }, + }, + required: ["hostname"], + additionalProperties: true, + }, + }, + disablePrefetch: { type: "boolean" }, + cacheKey: { type: "string" }, + cacheKeyExpiry: { + type: "object", + additionalProperties: { type: "number", minimum: -1 }, + }, + cacheExpiry: { type: "number", minimum: -1 }, + setToContext: { type: "boolean" }, + }, + additionalProperties: false, +}; + +export const dsqlSignerValidateOptions = (options) => + validateOptions(pkg, optionSchema, options); + +const dsqlSignerMiddleware = (opts = {}) => { + const options = { ...defaults, ...opts }; + + const fetchDataKeys = Object.keys(options.fetchData); + const clients = {}; + const fetchRequest = (request, cachedValues = {}) => { + const values = {}; + for (const internalKey of fetchDataKeys) { + if (cachedValues[internalKey]) continue; + + const { username, ...signerConfig } = options.fetchData[internalKey]; + clients[internalKey] ??= new options.AwsClient({ + ...options.awsClientOptions, + ...signerConfig, + }); + const method = + username === "admin" + ? "getDbConnectAdminAuthToken" + : "getDbConnectAuthToken"; + values[internalKey] = clients[internalKey] + [method]() + .then((token) => { + // Catch Missing token, this usually means there is something wrong with the credentials + if (!token.includes("X-Amz-Security-Token=")) { + throw new Error("X-Amz-Security-Token Missing", { + cause: { package: pkg, method }, + }); + } + return token; + }) + .catch((e) => { + const value = getCache(options.cacheKey).value ?? {}; + value[internalKey] = undefined; + modifyCache(options.cacheKey, value); + throw e; + }); + } + + return values; + }; + + if (canPrefetch(options)) { + processCache(options, fetchRequest); + } + + const dsqlSignerMiddlewareBefore = async (request) => { + const { value } = processCache(options, fetchRequest, request); + + Object.assign(request.internal, value); + + if (options.setToContext) { + const data = await getInternal(fetchDataKeys, request); + Object.assign(request.context, data); + } + }; + + return { + before: dsqlSignerMiddlewareBefore, + }; +}; +export default dsqlSignerMiddleware; + +// used for TS type inference (see index.d.ts) +export function dsqlSignerParam(name) { + return name; +} diff --git a/packages/dsql-signer/index.perf.js b/packages/dsql-signer/index.perf.js new file mode 100644 index 000000000..4b9ee130d --- /dev/null +++ b/packages/dsql-signer/index.perf.js @@ -0,0 +1,62 @@ +import { Bench } from "tinybench"; +import middy from "../core/index.js"; +import middleware from "./index.js"; + +const bench = new Bench({ + time: 1_000, + warmupTime: 500, + warmupIterations: 1_000, +}); + +const defaultContext = { + getRemainingTimeInMillis: () => 30000, +}; + +class MockDsqlSigner { + getDbConnectAuthToken() { + return Promise.resolve( + "cluster.dsql.us-east-1.on.aws/?Action=DbConnect&X-Amz-Security-Token=mock", + ); + } + getDbConnectAdminAuthToken() { + return Promise.resolve( + "cluster.dsql.us-east-1.on.aws/?Action=DbConnectAdmin&X-Amz-Security-Token=mock", + ); + } +} + +const setupHandler = (options = {}) => { + const baseHandler = () => {}; + return middy(baseHandler).use( + middleware({ + ...options, + AwsClient: MockDsqlSigner, + fetchData: { + token: { + hostname: "cluster.dsql.us-east-1.on.aws", + region: "us-east-1", + }, + }, + }), + ); +}; + +const coldHandler = setupHandler({ cacheExpiry: 0 }); +const warmHandler = setupHandler(); + +const defaultEvent = {}; +await bench + .add("without cache", async () => { + try { + await coldHandler(defaultEvent, defaultContext); + } catch (_e) {} + }) + .add("with cache", async () => { + try { + await warmHandler(defaultEvent, defaultContext); + } catch (_e) {} + }) + + .run(); + +console.table(bench.table()); diff --git a/packages/dsql-signer/index.test.js b/packages/dsql-signer/index.test.js new file mode 100644 index 000000000..2ebe747ea --- /dev/null +++ b/packages/dsql-signer/index.test.js @@ -0,0 +1,508 @@ +import { deepStrictEqual, ok, strictEqual } from "node:assert/strict"; +import { test } from "node:test"; +import middy from "../core/index.js"; +import { clearCache, getInternal } from "../util/index.js"; +import dsqlSigner, { dsqlSignerValidateOptions } from "./index.js"; + +test.afterEach((t) => { + t.mock.reset(); + clearCache(); +}); + +const defaultEvent = {}; +const defaultContext = { + getRemainingTimeInMillis: () => 1000, +}; + +test("It should set token to internal storage (token)", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => + "cluster.dsql.us-east-1.on.aws/?Action=DbConnect&X-Amz-Security-Token=token", + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}); + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual( + values.token, + "cluster.dsql.us-east-1.on.aws/?Action=DbConnect&X-Amz-Security-Token=token", + ); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + }, + }, + disablePrefetch: true, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); +}); + +test("It should call admin token method when username is 'admin'", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=non-admin-token", + ); + const getDbConnectAdminAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=admin-token", + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + getDbConnectAdminAuthToken = getDbConnectAdminAuthToken; + } + const handler = middy(() => {}); + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual(values.token, "X-Amz-Security-Token=admin-token"); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + username: "admin", + }, + }, + disablePrefetch: true, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); + strictEqual(getDbConnectAdminAuthToken.mock.callCount(), 1); + strictEqual(getDbConnectAuthToken.mock.callCount(), 0); +}); + +test("It should call non-admin token method when username is a custom role", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=role-token", + ); + const getDbConnectAdminAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=admin-token", + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + getDbConnectAdminAuthToken = getDbConnectAdminAuthToken; + } + const handler = middy(() => {}); + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual(values.token, "X-Amz-Security-Token=role-token"); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + username: "app_reader", + }, + }, + disablePrefetch: true, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); + strictEqual(getDbConnectAdminAuthToken.mock.callCount(), 0); +}); + +test("It should not pass `username` to the signer constructor", async (t) => { + let receivedConfig; + const getDbConnectAdminAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=admin-token", + ); + class AwsClient { + constructor(config) { + receivedConfig = config; + } + getDbConnectAdminAuthToken = getDbConnectAdminAuthToken; + } + const handler = middy(() => {}); + + handler.use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + hostname: "cluster.dsql.us-east-1.on.aws", + username: "admin", + }, + }, + disablePrefetch: true, + }), + ); + + await handler(defaultEvent, defaultContext); + deepStrictEqual(receivedConfig, { + hostname: "cluster.dsql.us-east-1.on.aws", + }); +}); + +test("It should set tokens to internal storage (multiple keys)", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=token2", + async () => "X-Amz-Security-Token=token1", + { times: 1 }, + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + + const handler = middy(() => {}); + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual(values.token1, "X-Amz-Security-Token=token1"); + strictEqual(values.token2, "X-Amz-Security-Token=token2"); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token1: { + region: "us-east-1", + hostname: "reader.dsql.us-east-1.on.aws", + }, + token2: { + region: "us-east-1", + hostname: "writer.dsql.us-east-1.on.aws", + }, + }, + disablePrefetch: true, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); +}); + +test("It should set DSQL token to context", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=token", + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}); + + const middleware = async (request) => { + strictEqual(request.context.token, "X-Amz-Security-Token=token"); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + }, + }, + setToContext: true, + disablePrefetch: true, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); +}); + +test("It should not call aws-sdk again if parameter is cached", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=token", + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}); + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual(values.token, "X-Amz-Security-Token=token"); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: -1, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + }, + }, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); + await handler(defaultEvent, defaultContext); + + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); +}); + +test("It should call aws-sdk if cache enabled but cached param has expired", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=token", + ); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + + const handler = middy(() => {}); + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual(values.token, "X-Amz-Security-Token=token"); + }; + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + }, + }, + disablePrefetch: true, + }), + ) + .before(middleware); + + await handler(defaultEvent, defaultContext); + await handler(defaultEvent, defaultContext); + + strictEqual(getDbConnectAuthToken.mock.callCount(), 2); +}); + +test("It should catch if an error is returned from fetch", async (t) => { + const getDbConnectAuthToken = t.mock.fn(async () => { + throw new Error("timeout"); + }); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}).use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + }, + }, + setToContext: true, + disablePrefetch: true, + }), + ); + + try { + await handler(defaultEvent, defaultContext); + } catch (e) { + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); + strictEqual(e.message, "Failed to resolve internal values"); + deepStrictEqual(e.cause.data, [new Error("timeout")]); + } +}); + +test("It should catch if a token without X-Amz-Security-Token is returned from fetch", async (t) => { + const getDbConnectAuthToken = t.mock.fn(async () => "no-creds"); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}).use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + region: "us-east-1", + hostname: "cluster.dsql.us-east-1.on.aws", + }, + }, + setToContext: true, + disablePrefetch: true, + }), + ); + + try { + await handler(defaultEvent, defaultContext); + } catch (e) { + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); + strictEqual(e.message, "Failed to resolve internal values"); + deepStrictEqual(e.cause.data, [ + new Error("X-Amz-Security-Token Missing", { + cause: { + package: "@middy/dsql-signer", + method: "getDbConnectAuthToken", + }, + }), + ]); + } +}); + +test("It should skip fetching already cached values when fetching multiple keys", async (t) => { + let callCount = 0; + const getDbConnectAuthToken = t.mock.fn(async () => { + callCount++; + if (callCount === 1) return "X-Amz-Security-Token=token1"; + if (callCount === 2) throw new Error("timeout"); + if (callCount === 3) return "X-Amz-Security-Token=token2"; + }); + class AwsClient { + getDbConnectAuthToken = getDbConnectAuthToken; + } + + const middleware = async (request) => { + const values = await getInternal(true, request); + strictEqual(values.token1, "X-Amz-Security-Token=token1"); + strictEqual(values.token2, "X-Amz-Security-Token=token2"); + }; + + const handler = middy(() => {}); + + handler + .use( + dsqlSigner({ + AwsClient, + cacheExpiry: 1000, + fetchData: { + token1: { + region: "us-east-1", + hostname: "reader.dsql.us-east-1.on.aws", + }, + token2: { + region: "us-east-1", + hostname: "writer.dsql.us-east-1.on.aws", + }, + }, + }), + ) + .before(middleware); + + try { + await handler(defaultEvent, defaultContext); + } catch (_e) {} + + await handler(defaultEvent, defaultContext); + + strictEqual(getDbConnectAuthToken.mock.callCount(), 3); +}); + +test("It should export dsqlSignerParam helper for TypeScript type inference", async (t) => { + const { dsqlSignerParam } = await import("./index.js"); + const paramName = "test-param"; + const result = dsqlSignerParam(paramName); + strictEqual(result, paramName); +}); + +test("dsqlSignerValidateOptions accepts valid options and rejects typos", () => { + dsqlSignerValidateOptions({ cacheKey: "x", cacheExpiry: 0 }); + dsqlSignerValidateOptions({}); + try { + dsqlSignerValidateOptions({ cachExpiry: 60 }); + ok(false, "expected throw"); + } catch (e) { + ok(e instanceof TypeError); + strictEqual(e.cause.package, "@middy/dsql-signer"); + } +}); + +test("dsqlSignerValidateOptions rejects wrong type", () => { + try { + dsqlSignerValidateOptions({ fetchData: 42 }); + ok(false, "expected throw"); + } catch (e) { + ok(e.message.includes("fetchData")); + } +}); + +test("dsqlSignerValidateOptions accepts valid fetchData entry", () => { + dsqlSignerValidateOptions({ + fetchData: { + token: { + hostname: "cluster.dsql.us-east-1.on.aws", + username: "admin", + }, + }, + }); +}); + +test("dsqlSignerValidateOptions rejects fetchData entry missing hostname", () => { + try { + dsqlSignerValidateOptions({ + fetchData: { token: { username: "admin" } }, + }); + ok(false, "expected throw"); + } catch (e) { + ok(e instanceof TypeError); + strictEqual(e.cause.package, "@middy/dsql-signer"); + } +}); + +test("dsqlSignerValidateOptions rejects fetchData entry with non-string username", () => { + try { + dsqlSignerValidateOptions({ + fetchData: { + token: { + hostname: "cluster.dsql.us-east-1.on.aws", + username: true, + }, + }, + }); + ok(false, "expected throw"); + } catch (e) { + ok(e instanceof TypeError); + } +}); + +test("dsqlSignerValidateOptions rejects fetchData entry with non-DSQL hostname", () => { + try { + dsqlSignerValidateOptions({ + fetchData: { + token: { hostname: "db.example.com" }, + }, + }); + ok(false, "expected throw"); + } catch (e) { + ok(e instanceof TypeError); + strictEqual(e.cause.package, "@middy/dsql-signer"); + } +}); diff --git a/packages/dsql-signer/index.tst.ts b/packages/dsql-signer/index.tst.ts new file mode 100644 index 000000000..22ac632aa --- /dev/null +++ b/packages/dsql-signer/index.tst.ts @@ -0,0 +1,78 @@ +import { DsqlSigner } from "@aws-sdk/dsql-signer"; +import middy from "@middy/core"; +import { getInternal } from "@middy/util"; +import type { Context as LambdaContext } from "aws-lambda"; +import { expect, test } from "tstyche"; +import dsqlSigner from "./index.js"; + +test("use with default options", () => { + const middleware = dsqlSigner(); + expect(middleware).type.toBe>(); +}); + +const options = { + AwsClient: DsqlSigner, + awsClientOptions: { + credentials: { + secretAccessKey: "secret", + accessKeyId: "key", + }, + }, + awsClientAssumeRole: "some-role", + fetchData: { + foo: { + hostname: "cluster.dsql.ca-central-1.on.aws", + username: "admin", + }, + }, + disablePrefetch: true, + cacheKey: "some-key", + cacheExpiry: 60 * 60 * 5, + setToContext: true, +}; + +test("use with no options", () => { + expect(dsqlSigner()).type.toBe< + middy.MiddlewareObj + >(); +}); + +test("use with all options", () => { + expect(dsqlSigner(options)).type.toBe< + middy.MiddlewareObj + >(); +}); + +const handler = middy(async (event: {}, context: LambdaContext) => { + return await Promise.resolve({}); +}); + +test("use with setToContext: true", () => { + handler + .use( + dsqlSigner({ + ...options, + setToContext: true, + }), + ) + .before(async (request) => { + expect(request.context.foo).type.toBe(); + + const data = await getInternal("foo", request); + expect(data.foo).type.toBe(); + }); +}); + +test("use with setToContext: false", () => { + handler + .use( + dsqlSigner({ + ...options, + setToContext: false, + }), + ) + .before(async (request) => { + const data = await getInternal("foo", request); + expect(data.foo).type.toBe(); + }); +}); diff --git a/packages/dsql-signer/package.json b/packages/dsql-signer/package.json new file mode 100644 index 000000000..f50f08307 --- /dev/null +++ b/packages/dsql-signer/package.json @@ -0,0 +1,82 @@ +{ + "name": "@middy/dsql-signer", + "version": "7.3.4", + "description": "Aurora DSQL credentials middleware for the middy framework", + "type": "module", + "engines": { + "node": ">=22" + }, + "engineStrict": true, + "publishConfig": { + "access": "public" + }, + "module": "./index.js", + "sideEffects": false, + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./index.js" + } + } + }, + "types": "index.d.ts", + "files": [ + "index.js", + "index.d.ts" + ], + "scripts": { + "test": "npm run test:unit && npm run test:fuzz", + "test:unit": "node --test", + "test:fuzz": "node --test index.fuzz.js", + "test:perf": "node --test index.perf.js" + }, + "license": "MIT", + "keywords": [ + "Lambda", + "Middleware", + "Serverless", + "Framework", + "AWS", + "AWS Lambda", + "Middy", + "DSQL", + "Aurora DSQL", + "Credentials" + ], + "author": { + "name": "Middy contributors", + "url": "https://github.com/middyjs/middy/graphs/contributors" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/middyjs/middy.git", + "directory": "packages/dsql-signer" + }, + "bugs": { + "url": "https://github.com/middyjs/middy/issues" + }, + "homepage": "https://middy.js.org", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/willfarrell" + }, + "peerDependencies": { + "@aws-sdk/dsql-signer": "^3.0.0" + }, + "peerDependenciesMeta": { + "@aws-sdk/dsql-signer": { + "optional": true + } + }, + "dependencies": { + "@middy/util": "7.3.4" + }, + "devDependencies": { + "@aws-sdk/dsql-signer": "^3.0.0", + "@middy/core": "7.3.4", + "@types/aws-lambda": "^8.0.0", + "@types/node": "^22.0.0", + "aws-xray-sdk": "^3.3.3" + } +} diff --git a/packages/rds-signer/index.js b/packages/rds-signer/index.js index cb1aa687c..6cd51f486 100644 --- a/packages/rds-signer/index.js +++ b/packages/rds-signer/index.js @@ -67,12 +67,14 @@ const rdsSignerMiddleware = (opts = {}) => { for (const internalKey of fetchDataKeys) { if (cachedValues[internalKey]) continue; + const signerConfig = options.fetchData[internalKey]; clients[internalKey] ??= new options.AwsClient({ ...options.awsClientOptions, - ...options.fetchData[internalKey], + ...signerConfig, }); + const method = "getAuthToken"; values[internalKey] = clients[internalKey] - .getAuthToken() + [method]() .then((token) => { // Catch Missing token, this usually means there is something wrong with the credentials if (!token.includes("X-Amz-Security-Token=")) { diff --git a/packages/util/index.js b/packages/util/index.js index 12281f73d..06d98f3a4 100644 --- a/packages/util/index.js +++ b/packages/util/index.js @@ -15,7 +15,8 @@ // exclusiveMaximum?, multipleOf?, minLength?, maxLength?, pattern? } // Numeric: `minimum`/`maximum` (inclusive), `exclusiveMinimum`/ // `exclusiveMaximum` (exclusive), `multipleOf` (number/integer). -// String: `minLength`/`maxLength` (string length), `pattern` (regex source). +// String: `minLength`/`maxLength` (string length), `pattern` (regex +// source string per JSON Schema, or a RegExp object). // { type: 'object' | 'object?', properties?: {...}, additionalProperties?: } // `properties` validates known keys with the flat-schema form. // `additionalProperties` validates every other key's value against the @@ -215,8 +216,11 @@ const checkRule = (rule, value, path, fail) => { fail(`Option '${path}' must be a multiple of ${multipleOf}`); } } - if (pattern !== undefined && !pattern.test(value)) { - fail(`Option '${path}' must match pattern ${pattern}`); + if (pattern !== undefined) { + const re = typeof pattern === "string" ? new RegExp(pattern) : pattern; + if (!re.test(value)) { + fail(`Option '${path}' must match pattern ${re}`); + } } if (minLength !== undefined && value.length < minLength) { fail(`Option '${path}' must have length >= ${minLength}`); diff --git a/websites/middy.js.org/src/components/docs/AsideNav.svelte b/websites/middy.js.org/src/components/docs/AsideNav.svelte index c7bdcff80..4be51527a 100644 --- a/websites/middy.js.org/src/components/docs/AsideNav.svelte +++ b/websites/middy.js.org/src/components/docs/AsideNav.svelte @@ -31,6 +31,7 @@ const nav = { "cloudwatch-metrics": "/docs/middlewares/cloudwatch-metrics", "do-not-wait-for-empty-event-loop": "/docs/middlewares/do-not-wait-for-empty-event-loop", + "dsql-signer": "/docs/middlewares/dsql-signer", dynamodb: "/docs/middlewares/dynamodb", "error-logger": "/docs/middlewares/error-logger", "event-normalizer": "/docs/middlewares/event-normalizer", diff --git a/websites/middy.js.org/src/routes/docs/best-practices/bundling/+page.md b/websites/middy.js.org/src/routes/docs/best-practices/bundling/+page.md index 29f953247..d3fc78767 100644 --- a/websites/middy.js.org/src/routes/docs/best-practices/bundling/+page.md +++ b/websites/middy.js.org/src/routes/docs/best-practices/bundling/+page.md @@ -83,6 +83,7 @@ export default (input) => ({ external: [ // AWS SDK '@aws-sdk/client-apigatewaymanagementapi', // @middy/ws-response + '@aws-sdk/dsql-signer', // @middy/dsql-signer '@aws-sdk/client-rds', // @middy/rds-signer '@aws-sdk/client-s3', // @middy/s3-object-response '@aws-sdk/client-secretsmanager', // @middy/sercrets-manager @@ -140,6 +141,7 @@ export default { 'zlib', // @middy/http-content-encoding // AWS SDK '@aws-sdk/client-apigatewaymanagementapi', // @middy/ws-response + '@aws-sdk/dsql-signer', // @middy/dsql-signer '@aws-sdk/client-rds', // @middy/rds-signer '@aws-sdk/client-s3', // @middy/s3-object-response '@aws-sdk/client-secretsmanager', // @middy/sercrets-manager diff --git a/websites/middy.js.org/src/routes/docs/middlewares/dsql-signer/+page.md b/websites/middy.js.org/src/routes/docs/middlewares/dsql-signer/+page.md new file mode 100644 index 000000000..daf92e231 --- /dev/null +++ b/websites/middy.js.org/src/routes/docs/middlewares/dsql-signer/+page.md @@ -0,0 +1,82 @@ +--- +title: dsql-signer +description: "Generate Aurora DSQL IAM authentication tokens for secure database connections in Lambda." +--- + +Fetches Aurora DSQL credentials to be used when connecting to a DSQL cluster with IAM roles. + +## Install + +To install this middleware you can use NPM: + +```bash npm2yarn +npm install --save @middy/dsql-signer +npm install --save-dev @aws-sdk/dsql-signer +``` + +## Options + +- `AwsClient` (object) (default `DsqlSigner`): Signer class constructor (i.e. that has been instrumented with AWS XRay). Must be from `@aws-sdk/dsql-signer`. +- `awsClientOptions` (object) (optional): Options to pass to Signer class constructor. +- `fetchData` (object) (required): Mapping of internal key name to API request parameters. + - `hostname` (string) (required): DSQL cluster endpoint, e.g. `.dsql..on.aws`. Validated against the DSQL hostname format. + - `username` (string) (optional): Database role. When set to `"admin"` the middleware calls `getDbConnectAdminAuthToken`; any other value (or omitted) calls `getDbConnectAuthToken`. +- `disablePrefetch` (boolean) (default `false`): On cold start requests will trigger early if they can. +- `cacheKey` (string) (default `dsql-signer`): Cache key for the fetched data responses. Must be unique across all middleware. +- `cacheExpiry` (number) (default `-1`): How long fetch data responses should be cached for. `-1`: cache forever, `0`: never cache, `n`: cache for n ms. Note: DSQL tokens have a default TTL of 900 s; cache for less than that to avoid using expired tokens on warm invocations. +- `setToContext` (boolean) (default `false`): Store role tokens to `request.context`. + +NOTES: + +- Lambda is required to have IAM permission for `dsql:DbConnect` (non-admin role) or `dsql:DbConnectAdmin` (admin role) on the cluster ARN. +- DSQL connections always use port `5432`, database `postgres`, and require SSL. +- Region is taken from the default credential provider chain (e.g. `AWS_REGION`); cross-region access is not a supported DSQL pattern. + +## Sample usage + +```javascript +import middy from '@middy/core' +import dsqlSigner from '@middy/dsql-signer' +import { getInternal } from '@middy/util' +import pg from 'pg' + +const lambdaHandler = async (event, context) => { + const { dsqlToken } = await getInternal(['dsqlToken'], context) + + const client = new pg.Client({ + host: 'cluster-id.dsql.us-east-1.on.aws', + port: 5432, + database: 'postgres', + user: 'admin', + password: dsqlToken, + ssl: true + }) + await client.connect() + + const { rows } = await client.query('SELECT 1') + await client.end() + + return { + statusCode: 200, + headers: {}, + body: JSON.stringify({ rows }) + } +} + +export const handler = middy() + .use( + dsqlSigner({ + fetchData: { + dsqlToken: { + hostname: 'cluster-id.dsql.us-east-1.on.aws', + username: 'admin' + } + } + }) + ) + .handler(lambdaHandler) +``` + +## Bundling + +To exclude `@aws-sdk` add `@aws-sdk/dsql-signer` to the exclude list. diff --git a/websites/middy.js.org/src/routes/docs/middlewares/intro/+page.md b/websites/middy.js.org/src/routes/docs/middlewares/intro/+page.md index 8b5adf4fb..3a7aee8ee 100644 --- a/websites/middy.js.org/src/routes/docs/middlewares/intro/+page.md +++ b/websites/middy.js.org/src/routes/docs/middlewares/intro/+page.md @@ -49,6 +49,7 @@ Each middleware should do a single task. We try to balance each to be as perform ## Fetch Data - [`appconfig`](/docs/middlewares/appconfig): Fetch JSON configurations from AppConfig. +- [`dsql-signer`](/docs/middlewares/dsql-signer): Fetches token for connecting to Aurora DSQL with IAM users. - [`dynamodb`](/docs/middlewares/dynamodb): Fetch configurations from DynamoDB. - [`rds-signer`](/docs/middlewares/rds-signer): Fetches token for connecting to RDS with IAM users. - [`s3`](/docs/middlewares/s3): Fetch JSON configurations from S3. From 5e6bd0d6d4155e878f0a0f4c12e151072f81bfbf Mon Sep 17 00:00:00 2001 From: will Farrell Date: Fri, 1 May 2026 06:30:18 -0600 Subject: [PATCH 4/8] fix: provide extra context for error Signed-off-by: will Farrell --- packages/rds-signer/index.js | 2 +- packages/rds-signer/index.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rds-signer/index.js b/packages/rds-signer/index.js index 6cd51f486..a037e94d7 100644 --- a/packages/rds-signer/index.js +++ b/packages/rds-signer/index.js @@ -79,7 +79,7 @@ const rdsSignerMiddleware = (opts = {}) => { // Catch Missing token, this usually means there is something wrong with the credentials if (!token.includes("X-Amz-Security-Token=")) { throw new Error("X-Amz-Security-Token Missing", { - cause: { package: pkg }, + cause: { package: pkg, method }, }); } return token; diff --git a/packages/rds-signer/index.test.js b/packages/rds-signer/index.test.js index 8718f6e4a..abc344fd4 100644 --- a/packages/rds-signer/index.test.js +++ b/packages/rds-signer/index.test.js @@ -323,7 +323,7 @@ test("It should catch if an invalid response is returned from fetch", async (t) strictEqual(e.message, "Failed to resolve internal values"); deepStrictEqual(e.cause.data, [ new Error("X-Amz-Security-Token Missing", { - cause: { package: "@middy/rds-signer" }, + cause: { package: "@middy/rds-signer", method: "getAuthToken" }, }), ]); } From ae4621b94940c4987eeefca0aa251dbb1a44a763 Mon Sep 17 00:00:00 2001 From: will Farrell Date: Fri, 1 May 2026 08:59:05 -0600 Subject: [PATCH 5/8] fix: accepted regexp Signed-off-by: will Farrell --- packages/util/index.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/util/index.js b/packages/util/index.js index 06d98f3a4..4775b1d14 100644 --- a/packages/util/index.js +++ b/packages/util/index.js @@ -16,7 +16,7 @@ // Numeric: `minimum`/`maximum` (inclusive), `exclusiveMinimum`/ // `exclusiveMaximum` (exclusive), `multipleOf` (number/integer). // String: `minLength`/`maxLength` (string length), `pattern` (regex -// source string per JSON Schema, or a RegExp object). +// source string per JSON Schema). // { type: 'object' | 'object?', properties?: {...}, additionalProperties?: } // `properties` validates known keys with the flat-schema form. // `additionalProperties` validates every other key's value against the @@ -216,11 +216,8 @@ const checkRule = (rule, value, path, fail) => { fail(`Option '${path}' must be a multiple of ${multipleOf}`); } } - if (pattern !== undefined) { - const re = typeof pattern === "string" ? new RegExp(pattern) : pattern; - if (!re.test(value)) { - fail(`Option '${path}' must match pattern ${re}`); - } + if (pattern !== undefined && !new RegExp(pattern).test(value)) { + fail(`Option '${path}' must match pattern ${pattern}`); } if (minLength !== undefined && value.length < minLength) { fail(`Option '${path}' must have length >= ${minLength}`); From 206f9a1e125838198f95a9f82b9b718a8466772e Mon Sep 17 00:00:00 2001 From: will Farrell Date: Fri, 1 May 2026 09:29:11 -0600 Subject: [PATCH 6/8] feat: add in env defaults Signed-off-by: will Farrell --- packages/dsql-signer/index.js | 10 +- packages/dsql-signer/index.test.js | 135 ++++++++++++------- packages/rds-signer/index.js | 14 +- packages/rds-signer/index.test.js | 209 ++++++++++++++++++----------- 4 files changed, 240 insertions(+), 128 deletions(-) diff --git a/packages/dsql-signer/index.js b/packages/dsql-signer/index.js index 95244babf..f4f90bf70 100644 --- a/packages/dsql-signer/index.js +++ b/packages/dsql-signer/index.js @@ -41,7 +41,7 @@ const optionSchema = { }, username: { type: "string" }, }, - required: ["hostname"], + required: [], additionalProperties: true, }, }, @@ -63,6 +63,14 @@ export const dsqlSignerValidateOptions = (options) => const dsqlSignerMiddleware = (opts = {}) => { const options = { ...defaults, ...opts }; + const defaultFetchData = { + hostname: process.env.PGHOST ?? process.env.DBHOST, + username: process.env.PGUSER ?? process.env.DBUSER, + }; + for (const key of Object.keys(options.fetchData)) { + options.fetchData[key] = { ...defaultFetchData, ...options.fetchData[key] }; + } + const fetchDataKeys = Object.keys(options.fetchData); const clients = {}; const fetchRequest = (request, cachedValues = {}) => { diff --git a/packages/dsql-signer/index.test.js b/packages/dsql-signer/index.test.js index 2ebe747ea..ab846f724 100644 --- a/packages/dsql-signer/index.test.js +++ b/packages/dsql-signer/index.test.js @@ -1,9 +1,17 @@ import { deepStrictEqual, ok, strictEqual } from "node:assert/strict"; -import { test } from "node:test"; +import { after, before, test } from "node:test"; import middy from "../core/index.js"; import { clearCache, getInternal } from "../util/index.js"; import dsqlSigner, { dsqlSignerValidateOptions } from "./index.js"; +before(() => { + process.env.PGHOST = "cluster.dsql.us-east-1.on.aws"; +}); + +after(() => { + delete process.env.PGHOST; +}); + test.afterEach((t) => { t.mock.reset(); clearCache(); @@ -38,10 +46,7 @@ test("It should set token to internal storage (token)", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - }, + token: { region: "us-east-1" }, }, disablePrefetch: true, }), @@ -76,11 +81,7 @@ test("It should call admin token method when username is 'admin'", async (t) => AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - username: "admin", - }, + token: { region: "us-east-1", username: "admin" }, }, disablePrefetch: true, }), @@ -116,11 +117,7 @@ test("It should call non-admin token method when username is a custom role", asy AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - username: "app_reader", - }, + token: { region: "us-east-1", username: "app_reader" }, }, disablePrefetch: true, }), @@ -150,10 +147,7 @@ test("It should not pass `username` to the signer constructor", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - hostname: "cluster.dsql.us-east-1.on.aws", - username: "admin", - }, + token: { username: "admin" }, }, disablePrefetch: true, }), @@ -225,10 +219,7 @@ test("It should set DSQL token to context", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - }, + token: { region: "us-east-1" }, }, setToContext: true, disablePrefetch: true, @@ -259,10 +250,7 @@ test("It should not call aws-sdk again if parameter is cached", async (t) => { AwsClient, cacheExpiry: -1, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - }, + token: { region: "us-east-1" }, }, }), ) @@ -295,10 +283,7 @@ test("It should call aws-sdk if cache enabled but cached param has expired", asy AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - }, + token: { region: "us-east-1" }, }, disablePrefetch: true, }), @@ -323,10 +308,7 @@ test("It should catch if an error is returned from fetch", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - }, + token: { region: "us-east-1" }, }, setToContext: true, disablePrefetch: true, @@ -352,10 +334,7 @@ test("It should catch if a token without X-Amz-Security-Token is returned from f AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "cluster.dsql.us-east-1.on.aws", - }, + token: { region: "us-east-1" }, }, setToContext: true, disablePrefetch: true, @@ -433,6 +412,71 @@ test("It should export dsqlSignerParam helper for TypeScript type inference", as strictEqual(result, paramName); }); +test("It should use DBHOST/DBUSER env var defaults as fallback", async (t) => { + const savedPGHOST = process.env.PGHOST; + delete process.env.PGHOST; + process.env.DBHOST = "cluster.dsql.us-east-1.on.aws"; + process.env.DBUSER = "app_reader"; + t.after(() => { + delete process.env.DBHOST; + delete process.env.DBUSER; + process.env.PGHOST = savedPGHOST; + }); + + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=role-token", + ); + let receivedConfig; + class AwsClient { + constructor(config) { + receivedConfig = config; + } + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}).use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { token: {} }, + disablePrefetch: true, + }), + ); + + await handler(defaultEvent, defaultContext); + strictEqual(receivedConfig.hostname, "cluster.dsql.us-east-1.on.aws"); + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); +}); + +test("It should prefer explicit fetchData values over env var defaults", async (t) => { + const getDbConnectAuthToken = t.mock.fn( + async () => "X-Amz-Security-Token=role-token", + ); + let receivedConfig; + class AwsClient { + constructor(config) { + receivedConfig = config; + } + getDbConnectAuthToken = getDbConnectAuthToken; + } + const handler = middy(() => {}).use( + dsqlSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + hostname: "explicit.dsql.us-east-1.on.aws", + username: "app_reader", + }, + }, + disablePrefetch: true, + }), + ); + + await handler(defaultEvent, defaultContext); + strictEqual(receivedConfig.hostname, "explicit.dsql.us-east-1.on.aws"); + strictEqual(getDbConnectAuthToken.mock.callCount(), 1); +}); + test("dsqlSignerValidateOptions accepts valid options and rejects typos", () => { dsqlSignerValidateOptions({ cacheKey: "x", cacheExpiry: 0 }); dsqlSignerValidateOptions({}); @@ -465,16 +509,9 @@ test("dsqlSignerValidateOptions accepts valid fetchData entry", () => { }); }); -test("dsqlSignerValidateOptions rejects fetchData entry missing hostname", () => { - try { - dsqlSignerValidateOptions({ - fetchData: { token: { username: "admin" } }, - }); - ok(false, "expected throw"); - } catch (e) { - ok(e instanceof TypeError); - strictEqual(e.cause.package, "@middy/dsql-signer"); - } +test("dsqlSignerValidateOptions accepts fetchData entry relying on env var defaults", () => { + dsqlSignerValidateOptions({ fetchData: { token: {} } }); + dsqlSignerValidateOptions({ fetchData: { token: { username: "admin" } } }); }); test("dsqlSignerValidateOptions rejects fetchData entry with non-string username", () => { diff --git a/packages/rds-signer/index.js b/packages/rds-signer/index.js index a037e94d7..cbb390b9e 100644 --- a/packages/rds-signer/index.js +++ b/packages/rds-signer/index.js @@ -38,7 +38,7 @@ const optionSchema = { port: { type: "integer", minimum: 1, maximum: 65535 }, username: { type: "string" }, }, - required: ["hostname", "port", "username"], + required: [], additionalProperties: true, }, }, @@ -60,6 +60,18 @@ export const rdsSignerValidateOptions = (options) => const rdsSignerMiddleware = (opts = {}) => { const options = { ...defaults, ...opts }; + const defaultFetchData = { + hostname: process.env.PGHOST ?? process.env.DBHOST, + port: Number.parseInt( + process.env.PGPORT ?? process.env.DBPORT ?? "5432", + 10, + ), + username: process.env.PGUSER ?? process.env.DBUSER, + }; + for (const key of Object.keys(options.fetchData)) { + options.fetchData[key] = { ...defaultFetchData, ...options.fetchData[key] }; + } + const fetchDataKeys = Object.keys(options.fetchData); const clients = {}; const fetchRequest = (request, cachedValues = {}) => { diff --git a/packages/rds-signer/index.test.js b/packages/rds-signer/index.test.js index abc344fd4..0dd74b396 100644 --- a/packages/rds-signer/index.test.js +++ b/packages/rds-signer/index.test.js @@ -1,9 +1,21 @@ import { deepStrictEqual, ok, strictEqual } from "node:assert/strict"; -import { test } from "node:test"; +import { after, before, test } from "node:test"; import middy from "../core/index.js"; import { clearCache, getInternal } from "../util/index.js"; import rdsSigner, { rdsSignerValidateOptions } from "./index.js"; +before(() => { + process.env.PGHOST = "hostname"; + process.env.PGPORT = "5432"; + process.env.PGUSER = "username"; +}); + +after(() => { + delete process.env.PGHOST; + delete process.env.PGPORT; + delete process.env.PGUSER; +}); + test.afterEach((t) => { t.mock.reset(); clearCache(); @@ -37,12 +49,7 @@ test("It should set token to internal storage (token)", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, disablePrefetch: true, }), @@ -82,18 +89,8 @@ test("It should set tokens to internal storage (token)", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token1: { - region: "us-east-1", - hostname: "hostname-reader", - username: "username", - port: 5432, - }, - token2: { - region: "us-east-1", - hostname: "hostname-writer", - username: "username", - port: 5432, - }, + token1: { region: "us-east-1", hostname: "hostname-reader" }, + token2: { region: "us-east-1", hostname: "hostname-writer" }, }, disablePrefetch: true, }), @@ -126,12 +123,7 @@ test("It should set Signer token to internal storage without prefetch", async (t AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, disablePrefetch: true, }), @@ -163,12 +155,7 @@ test("It should set Signer token to context", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, setToContext: true, disablePrefetch: true, @@ -202,12 +189,7 @@ test("It should not call aws-sdk again if parameter is cached", async (t) => { AwsClient, cacheExpiry: -1, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, }), ) @@ -243,12 +225,7 @@ test("It should call aws-sdk if cache enabled but cached param has expired", asy AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, disablePrefetch: true, }), @@ -273,12 +250,7 @@ test("It should catch if an error is returned from fetch", async (t) => { AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, setToContext: true, disablePrefetch: true, @@ -304,12 +276,7 @@ test("It should catch if an invalid response is returned from fetch", async (t) AwsClient, cacheExpiry: 0, fetchData: { - token: { - region: "us-east-1", - hostname: "hostname", - username: "username", - port: 5432, - }, + token: { region: "us-east-1" }, }, setToContext: true, disablePrefetch: true, @@ -370,18 +337,8 @@ test("It should skip fetching already cached values when fetching multiple keys" AwsClient, cacheExpiry: 1000, fetchData: { - token1: { - region: "us-east-1", - hostname: "hostname-reader", - username: "username", - port: 5432, - }, - token2: { - region: "us-east-1", - hostname: "hostname-writer", - username: "username", - port: 5432, - }, + token1: { region: "us-east-1", hostname: "hostname-reader" }, + token2: { region: "us-east-1", hostname: "hostname-writer" }, }, }), ) @@ -408,6 +365,109 @@ test("It should export rdsSignerParam helper for TypeScript type inference", asy strictEqual(result, paramName); }); +test("It should use DBHOST/DBPORT/DBUSER env var defaults as fallback", async (t) => { + const savedPGHOST = process.env.PGHOST; + const savedPGPORT = process.env.PGPORT; + const savedPGUSER = process.env.PGUSER; + delete process.env.PGHOST; + delete process.env.PGPORT; + delete process.env.PGUSER; + process.env.DBHOST = "db.example.com"; + process.env.DBPORT = "5434"; + process.env.DBUSER = "dbuser"; + t.after(() => { + delete process.env.DBHOST; + delete process.env.DBPORT; + delete process.env.DBUSER; + process.env.PGHOST = savedPGHOST; + process.env.PGPORT = savedPGPORT; + process.env.PGUSER = savedPGUSER; + }); + + let receivedConfig; + class AwsClient { + constructor(config) { + receivedConfig = config; + } + getAuthToken = t.mock.fn( + async () => "https://rds.amazonaws.com?X-Amz-Security-Token=token", + ); + } + const handler = middy(() => {}).use( + rdsSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { token: {} }, + disablePrefetch: true, + }), + ); + + await handler(defaultEvent, defaultContext); + strictEqual(receivedConfig.hostname, "db.example.com"); + strictEqual(receivedConfig.port, 5434); + strictEqual(receivedConfig.username, "dbuser"); +}); + +test("It should use default port 5432 when no PGPORT/DBPORT env var is set", async (t) => { + const savedPGPORT = process.env.PGPORT; + delete process.env.PGPORT; + t.after(() => { + process.env.PGPORT = savedPGPORT; + }); + + let receivedConfig; + class AwsClient { + constructor(config) { + receivedConfig = config; + } + getAuthToken = t.mock.fn( + async () => "https://rds.amazonaws.com?X-Amz-Security-Token=token", + ); + } + const handler = middy(() => {}).use( + rdsSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { token: {} }, + disablePrefetch: true, + }), + ); + + await handler(defaultEvent, defaultContext); + strictEqual(receivedConfig.port, 5432); +}); + +test("It should prefer explicit fetchData values over env var defaults", async (t) => { + let receivedConfig; + class AwsClient { + constructor(config) { + receivedConfig = config; + } + getAuthToken = t.mock.fn( + async () => "https://rds.amazonaws.com?X-Amz-Security-Token=token", + ); + } + const handler = middy(() => {}).use( + rdsSigner({ + AwsClient, + cacheExpiry: 0, + fetchData: { + token: { + hostname: "explicit.example.com", + port: 9999, + username: "explicit", + }, + }, + disablePrefetch: true, + }), + ); + + await handler(defaultEvent, defaultContext); + strictEqual(receivedConfig.hostname, "explicit.example.com"); + strictEqual(receivedConfig.port, 9999); + strictEqual(receivedConfig.username, "explicit"); +}); + test("rdsSignerValidateOptions accepts valid options and rejects typos", () => { rdsSignerValidateOptions({ cacheKey: "x", cacheExpiry: 0 }); rdsSignerValidateOptions({}); @@ -442,16 +502,11 @@ test("rdsSignerValidateOptions accepts valid fetchData entry", () => { }); }); -test("rdsSignerValidateOptions rejects fetchData entry missing required fields", () => { - try { - rdsSignerValidateOptions({ - fetchData: { token: { hostname: "db.example.com" } }, - }); - ok(false, "expected throw"); - } catch (e) { - ok(e instanceof TypeError); - strictEqual(e.cause.package, "@middy/rds-signer"); - } +test("rdsSignerValidateOptions accepts fetchData entry relying on env var defaults", () => { + rdsSignerValidateOptions({ fetchData: { token: {} } }); + rdsSignerValidateOptions({ + fetchData: { token: { hostname: "db.example.com" } }, + }); }); test("rdsSignerValidateOptions rejects fetchData entry with non-integer port", () => { From b043a13f8b725625817bf6d478986fbdaa0aacd9 Mon Sep 17 00:00:00 2001 From: will Farrell Date: Fri, 1 May 2026 09:31:28 -0600 Subject: [PATCH 7/8] feat: add in http-x402 middleware Signed-off-by: will Farrell --- packages/http-x402/index.d.ts | 27 ++ packages/http-x402/index.fuzz.js | 53 ++++ packages/http-x402/index.js | 173 ++++++++++++ packages/http-x402/index.test.js | 453 +++++++++++++++++++++++++++++++ packages/http-x402/index.tst.ts | 40 +++ packages/http-x402/package.json | 76 ++++++ 6 files changed, 822 insertions(+) create mode 100644 packages/http-x402/index.d.ts create mode 100644 packages/http-x402/index.fuzz.js create mode 100644 packages/http-x402/index.js create mode 100644 packages/http-x402/index.test.js create mode 100644 packages/http-x402/index.tst.ts create mode 100644 packages/http-x402/package.json diff --git a/packages/http-x402/index.d.ts b/packages/http-x402/index.d.ts new file mode 100644 index 000000000..697ed419e --- /dev/null +++ b/packages/http-x402/index.d.ts @@ -0,0 +1,27 @@ +import type middy from "@middy/core"; + +export interface Options { + FacilitatorClient?: new (config: { + url?: string; + }) => { + verify(payload: unknown, requirements: unknown): Promise; + settle(payload: unknown, requirements: unknown): Promise; + }; + facilitatorUrl?: string; + price: number; + decimals?: number; + network?: string; + payTo: string; + asset: string; + description?: string; + mimeType?: string; + human?: (request: middy.Request) => boolean; +} + +declare function httpX402(options: Options): middy.MiddlewareObj; + +export declare function httpX402ValidateOptions( + options?: Record, +): void; + +export default httpX402; diff --git a/packages/http-x402/index.fuzz.js b/packages/http-x402/index.fuzz.js new file mode 100644 index 000000000..306ca99d1 --- /dev/null +++ b/packages/http-x402/index.fuzz.js @@ -0,0 +1,53 @@ +import { strictEqual } from "node:assert/strict"; +import { test } from "node:test"; +import fc from "fast-check"; +import middy from "../core/index.js"; +import httpX402 from "./index.js"; + +class AlwaysInvalidFacilitatorClient { + async verify() { + return { isValid: false, invalidReason: "invalid_payload" }; + } + async settle() { + return { success: false, errorReason: "unexpected_settle_error" }; + } +} + +const fuzzOptions = { + price: 0.001, + payTo: "0xpayto", + asset: "0xasset", + FacilitatorClient: AlwaysInvalidFacilitatorClient, +}; +const defaultContext = { getRemainingTimeInMillis: () => 1000 }; + +test("fuzz payment-signature header values never crash", async () => { + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402(fuzzOptions), + ); + + await fc.assert( + fc.asyncProperty(fc.string(), async (headerValue) => { + const response = await handler( + { headers: { "payment-signature": headerValue } }, + defaultContext, + ); + strictEqual(typeof response.statusCode, "number"); + }), + { numRuns: 10_000, examples: [] }, + ); +}); + +test("fuzz arbitrary event objects never crash", async () => { + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402(fuzzOptions), + ); + + await fc.assert( + fc.asyncProperty(fc.object(), async (event) => { + const response = await handler(event, defaultContext); + strictEqual(typeof response.statusCode, "number"); + }), + { numRuns: 10_000, examples: [] }, + ); +}); diff --git a/packages/http-x402/index.js b/packages/http-x402/index.js new file mode 100644 index 000000000..de06e1960 --- /dev/null +++ b/packages/http-x402/index.js @@ -0,0 +1,173 @@ +// Copyright 2017 - 2026 will Farrell, Luciano Mammino, and Middy contributors. +// SPDX-License-Identifier: MIT +import { normalizeHttpResponse, validateOptions } from "@middy/util"; +import { HTTPFacilitatorClient } from "@x402/core/http"; + +const name = "http-x402"; +const pkg = `@middy/${name}`; + +const defaults = { + FacilitatorClient: HTTPFacilitatorClient, + facilitatorUrl: "https://x402.org/facilitator", + price: undefined, + decimals: 6, + network: "eip155:8453", + payTo: undefined, + asset: undefined, + description: "", + mimeType: "application/json", + human: undefined, +}; + +const optionSchema = { + type: "object", + properties: { + FacilitatorClient: { instanceof: "Function" }, + facilitatorUrl: { type: "string" }, + price: { type: "number", exclusiveMinimum: 0 }, + decimals: { type: "integer" }, + network: { type: "string" }, + payTo: { type: "string" }, + asset: { type: "string" }, + description: { type: "string" }, + mimeType: { type: "string" }, + human: (v) => typeof v === "function", + }, + required: ["price", "payTo", "asset"], + additionalProperties: false, +}; + +export const httpX402ValidateOptions = (options) => + validateOptions(pkg, optionSchema, options); + +const httpX402Middleware = (opts = {}) => { + const options = { ...defaults, ...opts }; + const { + FacilitatorClient, + facilitatorUrl, + price, + decimals, + network, + payTo, + asset, + description, + mimeType, + human, + } = options; + + const amount = String(Math.round(price * 10 ** decimals)); + const requirements = { + scheme: "exact", + network, + amount, + asset, + payTo, + maxTimeoutSeconds: 60, + description, + mimeType, + }; + const facilitator = new FacilitatorClient({ url: facilitatorUrl }); + + const httpX402MiddlewareBefore = async (request) => { + if (human?.(request)) return; + + const headers = request.event.headers ?? {}; + const paymentHeader = headers["payment-signature"]; + + const resource = buildResource(request.event); + const fullRequirements = { ...requirements, resource }; + + if (!paymentHeader) { + normalizeHttpResponse(request); + const paymentRequired = { + x402Version: 2, + error: "Payment required", + accepts: [fullRequirements], + }; + request.response.statusCode = 402; + request.response.headers["Content-Type"] = "application/json"; + request.response.headers["PAYMENT-REQUIRED"] = + encodeHeader(paymentRequired); + request.response.body = JSON.stringify(paymentRequired); + return request.response; + } + + let payload; + try { + payload = decodeHeader(paymentHeader); + } catch { + normalizeHttpResponse(request); + request.response.statusCode = 402; + request.response.headers["Content-Type"] = "application/json"; + request.response.body = JSON.stringify({ + x402Version: 2, + error: "invalid_payment", + }); + return request.response; + } + + const verifyResult = await facilitator.verify(payload, fullRequirements); + if (!verifyResult.isValid) { + normalizeHttpResponse(request); + request.response.statusCode = 402; + request.response.headers["Content-Type"] = "application/json"; + request.response.body = JSON.stringify({ + x402Version: 2, + error: verifyResult.invalidReason, + }); + return request.response; + } + + request.internal.x402 = { payload, requirements: fullRequirements }; + }; + + const httpX402MiddlewareAfter = async (request) => { + const stored = request.internal.x402; + if (!stored) return; + + normalizeHttpResponse(request); + if (request.response.statusCode >= 400) return; + + const { payload, requirements: fullRequirements } = stored; + const settleResult = await facilitator.settle(payload, fullRequirements); + + if (!settleResult.success) { + request.response.statusCode = 402; + request.response.headers["Content-Type"] = "application/json"; + request.response.body = JSON.stringify({ + x402Version: 2, + error: settleResult.errorReason, + }); + return; + } + + request.internal.x402 = { + ...stored, + payer: settleResult.payer, + transaction: settleResult.transaction, + network: settleResult.network, + }; + request.response.headers["PAYMENT-RESPONSE"] = encodeHeader(settleResult); + }; + + return { + before: httpX402MiddlewareBefore, + after: httpX402MiddlewareAfter, + }; +}; + +const buildResource = (event) => { + if (event.version === "2.0") { + return `https://${event.requestContext.domainName}${event.requestContext.http.path}`; + } + const host = event.headers?.Host ?? event.headers?.host ?? "localhost"; + return `https://${host}${event.path ?? "/"}`; +}; + +const encodeHeader = (obj) => + Buffer.from(JSON.stringify(obj)).toString("base64"); + +const decodeHeader = (header) => + JSON.parse(Buffer.from(header, "base64").toString()); + +export default httpX402Middleware; diff --git a/packages/http-x402/index.test.js b/packages/http-x402/index.test.js new file mode 100644 index 000000000..1d09ad963 --- /dev/null +++ b/packages/http-x402/index.test.js @@ -0,0 +1,453 @@ +import { ok, strictEqual } from "node:assert/strict"; +import { test } from "node:test"; +import middy from "../core/index.js"; +import httpX402, { httpX402ValidateOptions } from "./index.js"; + +const defaultOptions = { + price: 0.001, + payTo: "0xpayto", + asset: "0xasset", +}; + +const defaultContext = { getRemainingTimeInMillis: () => 1000 }; + +const makePaymentHeader = (payload) => + Buffer.from(JSON.stringify(payload)).toString("base64"); + +const testPayload = { + x402Version: 2, + scheme: "exact", + network: "eip155:8453", + payload: { signature: "0xsig", authorization: {} }, +}; + +const makeMockClient = (t, verifyResult, settleResult) => { + const mockVerify = t.mock.fn(async () => verifyResult); + const mockSettle = t.mock.fn(async () => settleResult); + class MockFacilitatorClient { + verify(...args) { + return mockVerify(...args); + } + settle(...args) { + return mockSettle(...args); + } + } + return { MockFacilitatorClient, mockVerify, mockSettle }; +}; + +const defaultVerifyResult = { isValid: true, payer: "0xpayer" }; +const defaultSettleResult = { + success: true, + payer: "0xpayer", + transaction: "0xtx", + network: "eip155:8453", +}; + +test("no payment-signature header returns 402", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler({ headers: {} }, defaultContext); + + strictEqual(response.statusCode, 402); + ok(response.headers["PAYMENT-REQUIRED"]); + strictEqual(response.headers["Content-Type"], "application/json"); + const body = JSON.parse(response.body); + strictEqual(body.x402Version, 2); + strictEqual(body.error, "Payment required"); + ok(Array.isArray(body.accepts)); + strictEqual(body.accepts[0].scheme, "exact"); + strictEqual(body.accepts[0].amount, "1000"); + strictEqual(body.accepts[0].network, "eip155:8453"); + strictEqual(body.accepts[0].payTo, "0xpayto"); + strictEqual(body.accepts[0].asset, "0xasset"); + strictEqual(mockVerify.mock.callCount(), 0); +}); + +test("missing headers object returns 402", async (t) => { + const { MockFacilitatorClient } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler({}, defaultContext); + strictEqual(response.statusCode, 402); +}); + +test("malformed payment-signature header returns 402", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler( + { headers: { "payment-signature": "not!!valid!!base64" } }, + defaultContext, + ); + + strictEqual(response.statusCode, 402); + const body = JSON.parse(response.body); + strictEqual(body.error, "invalid_payment"); + strictEqual(mockVerify.mock.callCount(), 0); +}); + +test("verify failure returns 402 with invalidReason", async (t) => { + const { MockFacilitatorClient, mockVerify, mockSettle } = makeMockClient( + t, + { isValid: false, invalidReason: "invalid_exact_evm_payload_signature" }, + defaultSettleResult, + ); + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + strictEqual(response.statusCode, 402); + const body = JSON.parse(response.body); + strictEqual(body.error, "invalid_exact_evm_payload_signature"); + strictEqual(mockVerify.mock.callCount(), 1); + strictEqual(mockSettle.mock.callCount(), 0); +}); + +test("verify passes but handler returns 4xx - no settlement", async (t) => { + const { MockFacilitatorClient, mockVerify, mockSettle } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 400, + body: "bad request", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + strictEqual(response.statusCode, 400); + strictEqual(mockVerify.mock.callCount(), 1); + strictEqual(mockSettle.mock.callCount(), 0); +}); + +test("verify passes but handler returns 5xx - no settlement", async (t) => { + const { MockFacilitatorClient, mockSettle } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 500, + body: "error", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + strictEqual(response.statusCode, 500); + strictEqual(mockSettle.mock.callCount(), 0); +}); + +test("verify passes, settle fails - returns 402", async (t) => { + const { MockFacilitatorClient, mockSettle } = makeMockClient( + t, + defaultVerifyResult, + { success: false, errorReason: "insufficient_funds" }, + ); + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + strictEqual(response.statusCode, 402); + const body = JSON.parse(response.body); + strictEqual(body.error, "insufficient_funds"); + strictEqual(mockSettle.mock.callCount(), 1); +}); + +test("verify and settle pass - adds PAYMENT-RESPONSE header", async (t) => { + const { MockFacilitatorClient, mockVerify, mockSettle } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + const response = await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + strictEqual(response.statusCode, 200); + ok(response.headers["PAYMENT-RESPONSE"]); + strictEqual(mockVerify.mock.callCount(), 1); + strictEqual(mockSettle.mock.callCount(), 1); +}); + +test("settle passes - internal state has payer and transaction", async (t) => { + const { MockFacilitatorClient } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + + let capturedInternal; + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })) + .after((request) => { + capturedInternal = request.internal.x402; + }) + .use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + strictEqual(capturedInternal?.payer, "0xpayer"); + strictEqual(capturedInternal?.transaction, "0xtx"); +}); + +test("price conversion: 0.001 with default decimals produces amount 1000", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + const [, requirements] = mockVerify.mock.calls[0].arguments; + strictEqual(requirements.amount, "1000"); +}); + +test("price conversion: 0.01 with decimals:6 produces amount 10000", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })).use( + httpX402({ + ...defaultOptions, + price: 0.01, + decimals: 6, + FacilitatorClient: MockFacilitatorClient, + }), + ); + + await handler( + { headers: { "payment-signature": makePaymentHeader(testPayload) } }, + defaultContext, + ); + + const [, requirements] = mockVerify.mock.calls[0].arguments; + strictEqual(requirements.amount, "10000"); +}); + +test("human returns true - skips payment entirely", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402({ + ...defaultOptions, + FacilitatorClient: MockFacilitatorClient, + human: () => true, + }), + ); + + const response = await handler({ headers: {} }, defaultContext); + + strictEqual(response.statusCode, 200); + strictEqual(mockVerify.mock.callCount(), 0); +}); + +test("human returns false - normal payment flow", async (t) => { + const { MockFacilitatorClient } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ statusCode: 200, body: "ok" })).use( + httpX402({ + ...defaultOptions, + FacilitatorClient: MockFacilitatorClient, + human: () => false, + }), + ); + + const response = await handler({ headers: {} }, defaultContext); + strictEqual(response.statusCode, 402); +}); + +test("API Gateway v1 resource URL from Host header", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + await handler( + { + headers: { + Host: "api.example.com", + "payment-signature": makePaymentHeader(testPayload), + }, + path: "/api/data", + }, + defaultContext, + ); + + const [, requirements] = mockVerify.mock.calls[0].arguments; + strictEqual(requirements.resource, "https://api.example.com/api/data"); +}); + +test("API Gateway v2 resource URL from requestContext", async (t) => { + const { MockFacilitatorClient, mockVerify } = makeMockClient( + t, + defaultVerifyResult, + defaultSettleResult, + ); + const handler = middy(() => ({ + statusCode: 200, + body: "ok", + headers: {}, + })).use( + httpX402({ ...defaultOptions, FacilitatorClient: MockFacilitatorClient }), + ); + + await handler( + { + version: "2.0", + headers: { "payment-signature": makePaymentHeader(testPayload) }, + requestContext: { + domainName: "api.example.com", + http: { path: "/api/data" }, + }, + }, + defaultContext, + ); + + const [, requirements] = mockVerify.mock.calls[0].arguments; + strictEqual(requirements.resource, "https://api.example.com/api/data"); +}); + +test("httpX402ValidateOptions - missing required field payTo throws", () => { + let threw = false; + try { + httpX402ValidateOptions({ price: 0.001, asset: "0x" }); + } catch (e) { + threw = true; + ok(e.message.includes("payTo")); + } + ok(threw); +}); + +test("httpX402ValidateOptions - missing required field asset throws", () => { + let threw = false; + try { + httpX402ValidateOptions({ price: 0.001, payTo: "0x" }); + } catch (e) { + threw = true; + ok(e.message.includes("asset")); + } + ok(threw); +}); + +test("httpX402ValidateOptions - unknown option throws", () => { + let threw = false; + try { + httpX402ValidateOptions({ + price: 0.001, + payTo: "0x", + asset: "0x", + unknown: true, + }); + } catch (e) { + threw = true; + ok(e.message.includes("unknown")); + } + ok(threw); +}); + +test("httpX402ValidateOptions - valid minimal options pass", () => { + httpX402ValidateOptions({ price: 0.001, payTo: "0x", asset: "0x" }); +}); + +test("httpX402ValidateOptions - valid options with human function pass", () => { + httpX402ValidateOptions({ + price: 0.001, + payTo: "0x", + asset: "0x", + human: () => false, + }); +}); diff --git a/packages/http-x402/index.tst.ts b/packages/http-x402/index.tst.ts new file mode 100644 index 000000000..babea9581 --- /dev/null +++ b/packages/http-x402/index.tst.ts @@ -0,0 +1,40 @@ +import type middy from "@middy/core"; +import { expect, test } from "tstyche"; +import httpX402, { type Options } from "./index.js"; + +test("requires price, payTo, and asset", () => { + const middleware = httpX402({ + price: 0.001, + payTo: "0xpayto", + asset: "0xasset", + }); + expect(middleware).type.toBe(); +}); + +test("all options", () => { + const middleware = httpX402({ + facilitatorUrl: "https://my-facilitator.example.com/", + price: 0.001, + decimals: 6, + network: "eip155:8453", + payTo: "0xpayto", + asset: "0xasset", + description: "Premium API access", + mimeType: "application/json", + human: (request) => + (request.event as { headers?: Record })?.headers?.[ + "x-human" + ] === "true", + }); + expect(middleware).type.toBe(); +}); + +test("Options type requires price, payTo, asset", () => { + // @ts-expect-error missing the following properties + const _opts: Options = {}; +}); + +test("Options type allows partial optional fields", () => { + const opts: Options = { price: 0.001, payTo: "0x", asset: "0x" }; + expect(opts).type.toBe(); +}); diff --git a/packages/http-x402/package.json b/packages/http-x402/package.json new file mode 100644 index 000000000..df6ac7910 --- /dev/null +++ b/packages/http-x402/package.json @@ -0,0 +1,76 @@ +{ + "name": "@middy/http-x402", + "version": "7.3.4", + "description": "x402 payment middleware for the middy framework", + "type": "module", + "engines": { + "node": ">=22" + }, + "engineStrict": true, + "publishConfig": { + "access": "public" + }, + "module": "./index.js", + "sideEffects": false, + "exports": { + ".": { + "import": { + "types": "./index.d.ts", + "default": "./index.js" + } + } + }, + "types": "index.d.ts", + "files": [ + "index.js", + "index.d.ts" + ], + "scripts": { + "test": "npm run test:unit && npm run test:fuzz", + "test:unit": "node --test", + "test:fuzz": "node --test index.fuzz.js", + "test:perf": "node --test index.perf.js" + }, + "license": "MIT", + "keywords": [ + "Lambda", + "Middleware", + "Serverless", + "Framework", + "AWS", + "AWS Lambda", + "Middy", + "HTTP", + "x402", + "Payments", + "Web3" + ], + "author": { + "name": "Middy contributors", + "url": "https://github.com/middyjs/middy/graphs/contributors" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/middyjs/middy.git", + "directory": "packages/http-x402" + }, + "bugs": { + "url": "https://github.com/middyjs/middy/issues" + }, + "homepage": "https://middy.js.org", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/willfarrell" + }, + "peerDependencies": { + "@x402/core": "^2.0.0" + }, + "dependencies": { + "@middy/util": "7.3.4" + }, + "devDependencies": { + "@middy/core": "7.3.4", + "@x402/core": "^2.0.0", + "@types/node": "^22.0.0" + } +} From 7627213cdd75a96a1b45ed0a5d8663d8b7dcc360 Mon Sep 17 00:00:00 2001 From: will Farrell Date: Fri, 1 May 2026 09:35:19 -0600 Subject: [PATCH 8/8] chore: version bump Signed-off-by: will Farrell --- .github/package.json | 2 +- package-lock.json | 414 +++++++++--------- package.json | 2 +- packages/appconfig/package.json | 6 +- packages/cloudformation-response/package.json | 4 +- packages/cloudformation-router/package.json | 4 +- packages/cloudwatch-metrics/package.json | 4 +- packages/core/package.json | 4 +- .../package.json | 6 +- packages/dsql-signer/package.json | 6 +- packages/dynamodb/package.json | 6 +- packages/error-logger/package.json | 4 +- packages/event-normalizer/package.json | 6 +- packages/http-content-encoding/package.json | 6 +- .../http-content-negotiation/package.json | 6 +- packages/http-cors/package.json | 6 +- packages/http-error-handler/package.json | 6 +- packages/http-event-normalizer/package.json | 4 +- packages/http-header-normalizer/package.json | 4 +- packages/http-json-body-parser/package.json | 6 +- .../http-multipart-body-parser/package.json | 6 +- packages/http-partial-response/package.json | 6 +- .../http-response-serializer/package.json | 6 +- packages/http-router/package.json | 6 +- packages/http-security-headers/package.json | 6 +- .../http-urlencode-body-parser/package.json | 6 +- .../http-urlencode-path-parser/package.json | 6 +- packages/input-output-logger/package.json | 6 +- packages/rds-signer/package.json | 6 +- packages/s3-object-response/package.json | 6 +- packages/s3/package.json | 6 +- packages/secrets-manager/package.json | 6 +- packages/service-discovery/package.json | 6 +- .../sqs-partial-batch-failure/package.json | 4 +- packages/ssm/package.json | 6 +- packages/sts/package.json | 6 +- packages/util/package.json | 4 +- packages/validator/package.json | 6 +- packages/warmup/package.json | 4 +- packages/ws-json-body-parser/package.json | 6 +- packages/ws-response/package.json | 6 +- packages/ws-router/package.json | 6 +- websites/middy.js.org/package.json | 2 +- 43 files changed, 317 insertions(+), 317 deletions(-) diff --git a/.github/package.json b/.github/package.json index 41be8df67..82c57c793 100644 --- a/.github/package.json +++ b/.github/package.json @@ -1,6 +1,6 @@ { "name": "@middy/github-workflows", - "version": "7.3.4", + "version": "7.4.0", "private": true, "engines": { "node": ">=24.0" diff --git a/package-lock.json b/package-lock.json index 01f17b0e4..7b9d0eadd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@middy/monorepo", - "version": "7.3.4", + "version": "7.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@middy/monorepo", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "workspaces": [ "packages/*", @@ -31,7 +31,7 @@ }, ".github": { "name": "@middy/github-workflows", - "version": "7.3.4", + "version": "7.4.0", "devDependencies": { "license-check-and-add": "4.0.5", "lockfile-lint": "5.0.0" @@ -275,9 +275,9 @@ } }, "node_modules/@aws-sdk/client-apigatewaymanagementapi": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-apigatewaymanagementapi/-/client-apigatewaymanagementapi-3.1039.0.tgz", - "integrity": "sha512-hz0NvJjPkyv26eQxQ6k+civhRdN825O8lbxPVXkGD60DCIyrVcrP7r2OPOFyTAC2Ar1GECCrAfqrKdPYjg1XVw==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-apigatewaymanagementapi/-/client-apigatewaymanagementapi-3.1040.0.tgz", + "integrity": "sha512-1CYjlZ9vLlj8ISjPL9An7irI2wBufXzdbn/jH6vTPH6lDYB6/+GvaMWLTTh+/JvpfhDxpB93/t1g5u0KaVHbRg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -326,9 +326,9 @@ } }, "node_modules/@aws-sdk/client-appconfigdata": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-appconfigdata/-/client-appconfigdata-3.1039.0.tgz", - "integrity": "sha512-AIk6lqgbRhD6lDPTHZP8p5GjUFrgjaKa4iDf4KCz/gA4aQ6eC+9I5BkhVBKy97PXsuG7THwCkPAyrd0pMKc3Zg==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-appconfigdata/-/client-appconfigdata-3.1040.0.tgz", + "integrity": "sha512-UyxDikm5SYclAVEvK7edAgEmyhTxoFsiyHCaQWFLaGoMEq5DNJMTOGSM1SaVMLOj+6i6w7hXm+VQTVxv7hJ0Pw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -378,9 +378,9 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.1039.0.tgz", - "integrity": "sha512-jue1zZeTxtyCzD7vMxw5gq4XE1q8SUDoePqgdPEPPgjg5FTJsmEhpswgeLV2dP4sHkyeap4f4Pf7BCmwkgJuNQ==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.1040.0.tgz", + "integrity": "sha512-7nwgQlDc2brGoPbNP7h3EBXs30zX7sb8m+tLaSQdqnNWpXCpq/AY0H/Fd5BQ5UWPlMB9k3sHAkMkCxm6kZXuLQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -429,9 +429,9 @@ } }, "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.1039.0.tgz", - "integrity": "sha512-eqyrnSj2l0/y89LHENnGparEyKD33Wh8PQszgWbtb6t8bI5oriPaTHHXCdGUmFjOMkiNfqbsLCoo5HhMXlvbxw==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.1040.0.tgz", + "integrity": "sha512-rxWgbYoaUwY11UnajsdJVKYYWp+ZE0AWquI2ImdPTodVcDVdYVhrxmb80my6QH1UFtOUmBCZIndx9fDT/Exp9g==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -483,9 +483,9 @@ } }, "node_modules/@aws-sdk/client-lambda": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1039.0.tgz", - "integrity": "sha512-G6k9MYrrvINhGhHDNheF9NcJlVQ4vbtyLD6pjsgL+vDwugQB84OR95T7bNI9If5DlOxKrLx9s6BGid1YoWQKYA==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1040.0.tgz", + "integrity": "sha512-QEpUqgsKVYZXfNmZs0vREVcxDKVvT1FKYH788s3JkPa6zCmT2wBEgCqqIgKS0QdbFMMTPDYIPkIInmIFu3YWjQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -539,9 +539,9 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1039.0.tgz", - "integrity": "sha512-PVH9v0pHYBQnBADSR/m88NgcuJcYqPXfpmkcME66vRF75Y4swwbEVVFbTBFuvxu0YcZiLFXu3lw0FDK00vEa3A==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1040.0.tgz", + "integrity": "sha512-Ldfby1xDrlZwNY2NxP9pwdVrf8sqHbGBKP1UkoG/oWcePGlGhjY8iVwy8hRy9f1EQfHVFWIFunwHaPQxhYTnWQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -606,9 +606,9 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1039.0.tgz", - "integrity": "sha512-Ew0tUX3tKpzGIMMX+RyRyxR4FHcPTEPMjE9YSemyau3NyNFjlpHQjeTNwFvplLEl/LPCC9A5gk58LcaHtySk7A==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1040.0.tgz", + "integrity": "sha512-qszI/6MUy57rSqA2eSN3jbdjU1RFUDkayw7HbSX02jRmP896mSssWM0BC+mwYXuY7d3s1QntxmMKiNwXEXRdWg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -657,9 +657,9 @@ } }, "node_modules/@aws-sdk/client-servicediscovery": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-servicediscovery/-/client-servicediscovery-3.1039.0.tgz", - "integrity": "sha512-9lL3eJAe/C+jhtgHtgThcD2WaMjNEP8srglAfaarLL3szfrrl2+G+N/4KxvfgN2xC6anpGryomKtHnaR8j8nAQ==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-servicediscovery/-/client-servicediscovery-3.1040.0.tgz", + "integrity": "sha512-c+OnV3SCbykjlY0H0OmD/RqzPaCEwqFY2k6uf6G5EZ4uLL/BN44GQL9jgGEC3BSk++uYkfaTJiIJbRqjlgWbHw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -708,9 +708,9 @@ } }, "node_modules/@aws-sdk/client-sqs": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.1039.0.tgz", - "integrity": "sha512-U8rooijGy5OnSdxEaJ/sIxuGPgHfspxE8K/az22eJJ4qnO2XcVMtkHljvbfQG0yL3wd93XaypNSPI52okdTyCA==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.1040.0.tgz", + "integrity": "sha512-dzmxbJ6swad3IDAR3xTo0ju7HQKm1YMiwxWr5utZ223WagpkxnKhbAUAjPscQRzbPRLMU3ojXTDcrYEZ/IpUiw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -761,9 +761,9 @@ } }, "node_modules/@aws-sdk/client-ssm": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1039.0.tgz", - "integrity": "sha512-UvFJ/9HSIkQWxcLNbq/QaWemhqi7TChLW+ZSWBv8mNmSybTj4ZrMFpzbH2y9gJq38dN1KVR6FyjtOA/+FE6avg==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1040.0.tgz", + "integrity": "sha512-Su6vrzo32lx7jL6Dk/fatQpjrGjBCQIDr7pRdlpHOGOSTfg2L+UFg/XRrZRL5blz7dCNdfhZf2uuuMK1n0hrkg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -813,9 +813,9 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1039.0.tgz", - "integrity": "sha512-FKwfa4agOd6rctrp6D+W/sUKT+c+wI5m23oYR0VyE01oad6ZYff+113JP/X2xbrxIFJtVz7GieQZdVUFqOuMuQ==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1040.0.tgz", + "integrity": "sha512-k5m8ofhqQ2102h6l0iqNFRpuSXdyhk62U9i13kmGmscfqtVX4JeKjg//IK1Mhaz6Owi6WxAl1jQ8vcx81gpzww==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1088,13 +1088,13 @@ } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1039.0.tgz", - "integrity": "sha512-zJdE1J5p3lxk6kw40hZoI7O3aZDy3exFUWyZjjE4BGppXvfM4PQTDFRcq466JxjUc7x3X//H2oNejsH8+UErIg==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1040.0.tgz", + "integrity": "sha512-9CUcij1A7f6i4XOp/7MczdQInHvHZ8KKoNHlXHq+UtR3HOtBbpk4/BzmLF/bSdvd4NI8i2XmQlP5fEUCo+zGPA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-cognito-identity": "3.1039.0", + "@aws-sdk/client-cognito-identity": "3.1040.0", "@aws-sdk/core": "^3.974.7", "@aws-sdk/credential-provider-cognito-identity": "^3.972.30", "@aws-sdk/credential-provider-env": "^3.972.33", @@ -1447,15 +1447,15 @@ } }, "node_modules/@aws-sdk/rds-signer": { - "version": "3.1039.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/rds-signer/-/rds-signer-3.1039.0.tgz", - "integrity": "sha512-dmIZ5Fs92tsew4pmPjq9TeP6dnLrIasZHu4EfIlRKEzBXqqtV+kVEjfnhZsmRZNdm/kd3gVvO5nFaCg3C4TBLQ==", + "version": "3.1040.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/rds-signer/-/rds-signer-3.1040.0.tgz", + "integrity": "sha512-O5qQzhYKjm+8ARZRAdqTpZmbcaY35cNvjRAcJboBkLNyNgjZ5KLSc4vxgX/WqS7qo0b4qZYnXwdippdaMV01LQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/credential-providers": "3.1039.0", + "@aws-sdk/credential-providers": "3.1040.0", "@aws-sdk/util-format-url": "^3.972.10", "@smithy/config-resolver": "^4.4.17", "@smithy/hash-node": "^4.2.14", @@ -1669,9 +1669,9 @@ } }, "node_modules/@aws/durable-execution-sdk-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@aws/durable-execution-sdk-js/-/durable-execution-sdk-js-1.1.1.tgz", - "integrity": "sha512-ubuZu494xiZsIDjjZupGoVJwh8fSfeibZVp/4SjgejdXOetzd9w1V8AmB4bzAwcgsmhHbk3BPdg2cmvTebGBpA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@aws/durable-execution-sdk-js/-/durable-execution-sdk-js-1.1.2.tgz", + "integrity": "sha512-STJU58rInEBfsPyUDtH/XIL8/jaCfpkTkx37EAwee7fFO1tdaXwInCmkOjxtIrImhSdkPJU8bRORKTij/N0I8A==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1923,13 +1923,13 @@ } }, "node_modules/@cloudflare/kv-asset-handler": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.4.2.tgz", - "integrity": "sha512-SIOD2DxrRRwQ+jgzlXCqoEFiKOFqaPjhnNTGKXSRLvp1HiOvapLaFG2kEr9dYQTYe8rKrd9uvDUzmAITeNyaHQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz", + "integrity": "sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==", "dev": true, "license": "MIT OR Apache-2.0", "engines": { - "node": ">=18.0.0" + "node": ">=22.0.0" } }, "node_modules/@cloudflare/unenv-preset": { @@ -1949,9 +1949,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260426.1.tgz", - "integrity": "sha512-Ch7DqsmYzSQRTY87pZpsGsFVz9VVBnLPnCBOHxKt1HH25a7oMu1w1PbPWqVmE0VerCLsj/TScX7Ob3v6E14TZw==", + "version": "1.20260430.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260430.1.tgz", + "integrity": "sha512-ADohZUHf7NBvPp2PdZig2Opxx+hDkk3ve7jrTne3JRx9kDSB73zc4LzcEeEN8LKkbAcqZmvfRJfpChSlusu0lA==", "cpu": [ "x64" ], @@ -1966,9 +1966,9 @@ } }, "node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260426.1.tgz", - "integrity": "sha512-0m0U8vaPRH25SpKjbSyRql6gmPe4rCsETRV2WW0qBnuMdKNr5Vh5/Uez80xVrfiCCRMTULGeg63Nqg2vg6CDOA==", + "version": "1.20260430.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260430.1.tgz", + "integrity": "sha512-/DoYC/1wHs+YRZzzqSQg1/EHB4hiv1yV5U8FnmapRRIzVaPtnt+ApeOXeMrIdKidgKOI8TqQzgBU8xbIM7Cl4Q==", "cpu": [ "arm64" ], @@ -1983,9 +1983,9 @@ } }, "node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260426.1.tgz", - "integrity": "sha512-C8LlC8uSYzg49y51n++75esxZmMp+Uz1OKHHA/4lkv6rjOTbcHQJuEwSLppjybVIXpv7A8MBhbu9iyCTvyv1mw==", + "version": "1.20260430.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260430.1.tgz", + "integrity": "sha512-koJhBWvEVZPKCVFtMLp2iMHlYr+lFCF47wGbnlKdHVlemV0zTxJEyHI8aLlrhPLhBmOmYLp46rXw09/qJkRIhQ==", "cpu": [ "x64" ], @@ -2000,9 +2000,9 @@ } }, "node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260426.1.tgz", - "integrity": "sha512-ESVp/OIFMAqjQsa8BOP2BQQz5Vpfv6ncN6lNnIuNeOgsISQBdYk+LA60bwQHMud9tvmnSYtONp1zkZ8OQz+x6w==", + "version": "1.20260430.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260430.1.tgz", + "integrity": "sha512-hMdapNAzNQZDXGGkg4Slydc3fRJP5FUZLJVVcZCW/+imhhJro9Z1rv5n/wfR+txKoSWhTYR8eOp8Pyi2bzLzlw==", "cpu": [ "arm64" ], @@ -2017,9 +2017,9 @@ } }, "node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260426.1.tgz", - "integrity": "sha512-d3Xj/IjINRgNVwH+eKhpUn4xkkcEewbWXbOvBlapiirKWh5zl9m0Epi3qOqmjyRYK6MICqIGXg4qZBEt0lxudw==", + "version": "1.20260430.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260430.1.tgz", + "integrity": "sha512-jS3ffixjb5USOwz4frw4WzCz0HrjVxkgyU3WiYb06N7hBAfN6eOrveAJ4QRef0+suK4V1vQFoB1oKdRBsXe9Dw==", "cpu": [ "x64" ], @@ -2034,9 +2034,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "4.20260430.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260430.1.tgz", - "integrity": "sha512-Rguf/SdQNm1HG2yZi8m57K4qvVh2fic+Xny4UidY1pCgHagOAq7Cy0WIp1JKQx54T8lgOgOWFzIaCK4iwLpxlg==", + "version": "4.20260501.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260501.1.tgz", + "integrity": "sha512-B/VX2w3my/sCqxKyWOX7SxUpFC1uD8Gh7I2zbI1d3zA8p7Tx03AFsnuEx8lYLmcd8yONAA93YsAZb1wAaLK83w==", "dev": true, "license": "MIT OR Apache-2.0" }, @@ -6358,9 +6358,9 @@ } }, "node_modules/devalue": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.7.1.tgz", - "integrity": "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.0.tgz", + "integrity": "sha512-2zA9pFEsnp7vWBZbXF5JAgAq0fsUIt/1XPbRiAmRV3lp/2C3upzH+sADiyy66aFCihoLEsrQHxNM5w1gIDfsBg==", "license": "MIT" }, "node_modules/diff": { @@ -8166,16 +8166,16 @@ "link": true }, "node_modules/miniflare": { - "version": "4.20260426.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260426.0.tgz", - "integrity": "sha512-KM+v76d04qT+NsPfVKVQEgnnuLNE3uzCCl2QKMTJ5OXor5JbBm1vpkQwQ+l7o5ELCrZ74RnyKhJKLiJyUA39Tw==", + "version": "4.20260430.0", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-4.20260430.0.tgz", + "integrity": "sha512-MWvMm3Siho9Yj7lbJZidLs8hbrRvIcOrif2mnsHQZdvoKfedpea+GaN8XJxbpRcq0B2WzNI1BB1ihdnqes3/ZA==", "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "^0.34.5", "undici": "7.24.8", - "workerd": "1.20260426.1", + "workerd": "1.20260430.1", "ws": "8.18.0", "youch": "4.1.0-beta.10" }, @@ -8183,7 +8183,7 @@ "miniflare": "bootstrap.js" }, "engines": { - "node": ">=18.0.0" + "node": ">=22.0.0" } }, "node_modules/miniflare/node_modules/undici": { @@ -8262,9 +8262,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -8701,9 +8701,9 @@ } }, "node_modules/postcss": { - "version": "8.5.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz", - "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==", + "version": "8.5.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.13.tgz", + "integrity": "sha512-qif0+jGGZoLWdHey3UFHHWP0H7Gbmsk8T5VEqyYFbWqPr1XqvLGBbk/sl8V5exGmcYJklJOhOQq1pV9IcsiFag==", "dev": true, "funding": [ { @@ -10005,9 +10005,9 @@ "license": "ISC" }, "node_modules/workerd": { - "version": "1.20260426.1", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260426.1.tgz", - "integrity": "sha512-ELvGgN8c9oo+E6EPyecxk1TEf6/eAK4TxxQTW5mQ87C7jbjCzhMbg0P2ije49UBHV0dkBYPJcJvcklUltipl2A==", + "version": "1.20260430.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260430.1.tgz", + "integrity": "sha512-KEgIWyiw3Jmn+DCd/L3ePo5fmiiYb/UcwKvDWPf/nLLOiwShDFzDSsegU5NY/JcwgvO/QsLHVi2FYrbkcXNY5Q==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -10018,11 +10018,11 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260426.1", - "@cloudflare/workerd-darwin-arm64": "1.20260426.1", - "@cloudflare/workerd-linux-64": "1.20260426.1", - "@cloudflare/workerd-linux-arm64": "1.20260426.1", - "@cloudflare/workerd-windows-64": "1.20260426.1" + "@cloudflare/workerd-darwin-64": "1.20260430.1", + "@cloudflare/workerd-darwin-arm64": "1.20260430.1", + "@cloudflare/workerd-linux-64": "1.20260430.1", + "@cloudflare/workerd-linux-arm64": "1.20260430.1", + "@cloudflare/workerd-windows-64": "1.20260430.1" } }, "node_modules/worktop": { @@ -10040,33 +10040,33 @@ } }, "node_modules/wrangler": { - "version": "4.86.0", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.86.0.tgz", - "integrity": "sha512-9aa/gbF/HiUeeUEwyQpW5LDPBEzyt7iaE6xHwm0vk2Ly8A6J+jh03pzchqVnCCWR832mNyA28MD8oAYt0Kfvlw==", + "version": "4.87.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.87.0.tgz", + "integrity": "sha512-lfhfKwLfQlowwgV0xhlYgE9fU3n0I30d4ccGY/rTCEm/n42Mjvlr0Ng3ZPNqlsrsKBcDR531V7dsPkgELvrk/Q==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { - "@cloudflare/kv-asset-handler": "0.4.2", + "@cloudflare/kv-asset-handler": "0.5.0", "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.27.3", - "miniflare": "4.20260426.0", + "miniflare": "4.20260430.0", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", - "workerd": "1.20260426.1" + "workerd": "1.20260430.1" }, "bin": { "wrangler": "bin/wrangler.js", "wrangler2": "bin/wrangler.js" }, "engines": { - "node": ">=20.3.0" + "node": ">=22.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { - "@cloudflare/workers-types": "^4.20260426.1" + "@cloudflare/workers-types": "^4.20260430.1" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -10726,14 +10726,14 @@ }, "packages/appconfig": { "name": "@middy/appconfig", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-appconfigdata": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -10773,10 +10773,10 @@ }, "packages/cloudformation-response": { "name": "@middy/cloudformation-response", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -10807,10 +10807,10 @@ }, "packages/cloudformation-router": { "name": "@middy/cloudformation-router", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -10841,13 +10841,13 @@ }, "packages/cloudwatch-metrics": { "name": "@middy/cloudwatch-metrics", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { "aws-embedded-metrics": "4.2.1" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -10878,10 +10878,10 @@ }, "packages/core": { "name": "@middy/core", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws/durable-execution-sdk-js": "^1.0.0", @@ -10925,13 +10925,13 @@ }, "packages/do-not-wait-for-empty-event-loop": { "name": "@middy/do-not-wait-for-empty-event-loop", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -10962,14 +10962,14 @@ }, "packages/dsql-signer": { "name": "@middy/dsql-signer", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/dsql-signer": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11009,15 +11009,15 @@ }, "packages/dynamodb": { "name": "@middy/dynamodb", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-dynamodb": "^3.0.0", "@aws-sdk/util-dynamodb": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11061,10 +11061,10 @@ }, "packages/error-logger": { "name": "@middy/error-logger", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11095,13 +11095,13 @@ }, "packages/event-normalizer": { "name": "@middy/event-normalizer", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@serverless/event-mocks": "^1.1.1", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" @@ -11133,14 +11133,14 @@ }, "packages/http-content-encoding": { "name": "@middy/http-content-encoding", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@datastream/core": "0.4.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11171,14 +11171,14 @@ }, "packages/http-content-negotiation": { "name": "@middy/http-content-negotiation", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4", + "@middy/util": "7.4.0", "negotiator": "1.0.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11209,13 +11209,13 @@ }, "packages/http-cors": { "name": "@middy/http-cors", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11246,13 +11246,13 @@ }, "packages/http-error-handler": { "name": "@middy/http-error-handler", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/http-errors": "^2.0.0", "@types/node": "^22.0.0" }, @@ -11283,10 +11283,10 @@ }, "packages/http-event-normalizer": { "name": "@middy/http-event-normalizer", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11317,10 +11317,10 @@ }, "packages/http-header-normalizer": { "name": "@middy/http-header-normalizer", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/node": "^22.0.0" }, "engines": { @@ -11350,13 +11350,13 @@ }, "packages/http-json-body-parser": { "name": "@middy/http-json-body-parser", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" @@ -11388,14 +11388,14 @@ }, "packages/http-multipart-body-parser": { "name": "@middy/http-multipart-body-parser", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { "@fastify/busboy": "3.2.0", - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" @@ -11427,14 +11427,14 @@ }, "packages/http-partial-response": { "name": "@middy/http-partial-response", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4", + "@middy/util": "7.4.0", "json-mask": "2.0.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11465,13 +11465,13 @@ }, "packages/http-response-serializer": { "name": "@middy/http-response-serializer", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11502,13 +11502,13 @@ }, "packages/http-router": { "name": "@middy/http-router", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11539,13 +11539,13 @@ }, "packages/http-security-headers": { "name": "@middy/http-security-headers", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11576,13 +11576,13 @@ }, "packages/http-urlencode-body-parser": { "name": "@middy/http-urlencode-body-parser", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" @@ -11614,13 +11614,13 @@ }, "packages/http-urlencode-path-parser": { "name": "@middy/http-urlencode-path-parser", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" @@ -11652,14 +11652,14 @@ }, "packages/input-output-logger": { "name": "@middy/input-output-logger", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@datastream/core": "0.4.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -11690,14 +11690,14 @@ }, "packages/rds-signer": { "name": "@middy/rds-signer", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/rds-signer": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11737,14 +11737,14 @@ }, "packages/s3": { "name": "@middy/s3", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-s3": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11767,14 +11767,14 @@ }, "packages/s3-object-response": { "name": "@middy/s3-object-response", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-s3": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11831,14 +11831,14 @@ }, "packages/secrets-manager": { "name": "@middy/secrets-manager", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-secrets-manager": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11878,14 +11878,14 @@ }, "packages/service-discovery": { "name": "@middy/service-discovery", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-servicediscovery": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -11925,11 +11925,11 @@ }, "packages/sqs-partial-batch-failure": { "name": "@middy/sqs-partial-batch-failure", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { "@aws-sdk/client-sqs": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@serverless/event-mocks": "^1.1.1", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" @@ -11961,14 +11961,14 @@ }, "packages/ssm": { "name": "@middy/ssm", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-ssm": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -12008,14 +12008,14 @@ }, "packages/sts": { "name": "@middy/sts", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-sts": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -12055,11 +12055,11 @@ }, "packages/util": { "name": "@middy/util", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { "@aws-sdk/client-ssm": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -12091,10 +12091,10 @@ }, "packages/validator": { "name": "@middy/validator", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4", + "@middy/util": "7.4.0", "@silverbucket/ajv-formats-draft2019": "1.6.5", "ajv": "8.20.0", "ajv-errors": "3.0.0", @@ -12103,7 +12103,7 @@ "ajv-keywords": "5.1.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/http-errors": "^2.0.0", "@types/node": "^22.0.0", @@ -12137,10 +12137,10 @@ }, "packages/warmup": { "name": "@middy/warmup", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -12171,13 +12171,13 @@ }, "packages/ws-json-body-parser": { "name": "@middy/ws-json-body-parser", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" @@ -12209,14 +12209,14 @@ }, "packages/ws-response": { "name": "@middy/ws-response", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-apigatewaymanagementapi": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" @@ -12256,13 +12256,13 @@ }, "packages/ws-router": { "name": "@middy/ws-router", - "version": "7.3.4", + "version": "7.4.0", "license": "MIT", "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" }, @@ -12292,7 +12292,7 @@ "license": "MIT" }, "websites/middy.js.org": { - "version": "7.3.4", + "version": "7.4.0", "dependencies": { "@plausible-analytics/tracker": "0.4.4", "@willfarrell-ds/svelte": "0.0.0-alpha.6", diff --git a/package.json b/package.json index f9a237a58..fb7980d2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@middy/monorepo", - "version": "7.3.4", + "version": "7.4.0", "description": "🛵 The stylish Node.js middleware engine for AWS Lambda", "private": true, "type": "module", diff --git a/packages/appconfig/package.json b/packages/appconfig/package.json index 9249dd64d..e260de2f0 100644 --- a/packages/appconfig/package.json +++ b/packages/appconfig/package.json @@ -1,6 +1,6 @@ { "name": "@middy/appconfig", - "version": "7.3.4", + "version": "7.4.0", "description": "AppConfig middleware for the middy framework", "type": "module", "engines": { @@ -68,11 +68,11 @@ } }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-appconfigdata": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/cloudformation-response/package.json b/packages/cloudformation-response/package.json index d7caa724e..2cf17856e 100644 --- a/packages/cloudformation-response/package.json +++ b/packages/cloudformation-response/package.json @@ -1,6 +1,6 @@ { "name": "@middy/cloudformation-response", - "version": "7.3.4", + "version": "7.4.0", "description": "CloudFormation Custom Response event response handling for the middy framework", "type": "module", "engines": { @@ -61,7 +61,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/cloudformation-router/package.json b/packages/cloudformation-router/package.json index 18e44daf6..5462b5909 100644 --- a/packages/cloudformation-router/package.json +++ b/packages/cloudformation-router/package.json @@ -1,6 +1,6 @@ { "name": "@middy/cloudformation-router", - "version": "7.3.4", + "version": "7.4.0", "description": "CloudFormation Custom Response event router for the middy framework", "type": "module", "engines": { @@ -62,7 +62,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/cloudwatch-metrics/package.json b/packages/cloudwatch-metrics/package.json index 239a888f6..8d1a15954 100644 --- a/packages/cloudwatch-metrics/package.json +++ b/packages/cloudwatch-metrics/package.json @@ -1,6 +1,6 @@ { "name": "@middy/cloudwatch-metrics", - "version": "7.3.4", + "version": "7.4.0", "description": "Embedded CloudWatch metrics middleware for the middy framework", "type": "module", "engines": { @@ -68,7 +68,7 @@ "aws-embedded-metrics": "4.2.1" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/core/package.json b/packages/core/package.json index 9a15f93cd..fbf73f70f 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@middy/core", - "version": "7.3.4", + "version": "7.4.0", "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (core package)", "type": "module", "engines": { @@ -103,7 +103,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "peerDependencies": { "@aws/durable-execution-sdk-js": "^1.0.0" diff --git a/packages/do-not-wait-for-empty-event-loop/package.json b/packages/do-not-wait-for-empty-event-loop/package.json index 409c247c8..1222fda19 100644 --- a/packages/do-not-wait-for-empty-event-loop/package.json +++ b/packages/do-not-wait-for-empty-event-loop/package.json @@ -1,6 +1,6 @@ { "name": "@middy/do-not-wait-for-empty-event-loop", - "version": "7.3.4", + "version": "7.4.0", "description": "Middleware for the middy framework that allows to easily disable the wait for empty event loop in a Lambda function", "type": "module", "engines": { @@ -60,10 +60,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/dsql-signer/package.json b/packages/dsql-signer/package.json index f50f08307..7bb5648fc 100644 --- a/packages/dsql-signer/package.json +++ b/packages/dsql-signer/package.json @@ -1,6 +1,6 @@ { "name": "@middy/dsql-signer", - "version": "7.3.4", + "version": "7.4.0", "description": "Aurora DSQL credentials middleware for the middy framework", "type": "module", "engines": { @@ -70,11 +70,11 @@ } }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/dsql-signer": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/dynamodb/package.json b/packages/dynamodb/package.json index d5b45880b..e1d64f0db 100644 --- a/packages/dynamodb/package.json +++ b/packages/dynamodb/package.json @@ -1,6 +1,6 @@ { "name": "@middy/dynamodb", - "version": "7.3.4", + "version": "7.4.0", "description": "DynamoDB middleware for the middy framework", "type": "module", "engines": { @@ -72,12 +72,12 @@ } }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-dynamodb": "^3.0.0", "@aws-sdk/util-dynamodb": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/error-logger/package.json b/packages/error-logger/package.json index 1d023c557..44ddac727 100644 --- a/packages/error-logger/package.json +++ b/packages/error-logger/package.json @@ -1,6 +1,6 @@ { "name": "@middy/error-logger", - "version": "7.3.4", + "version": "7.4.0", "description": "Error logger middleware for the middy framework", "type": "module", "engines": { @@ -61,7 +61,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/event-normalizer/package.json b/packages/event-normalizer/package.json index 88c9495d4..2849d2f39 100644 --- a/packages/event-normalizer/package.json +++ b/packages/event-normalizer/package.json @@ -1,6 +1,6 @@ { "name": "@middy/event-normalizer", - "version": "7.3.4", + "version": "7.4.0", "description": "Parse and normalize AWS events middleware for the middy framework", "type": "module", "engines": { @@ -64,10 +64,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@serverless/event-mocks": "^1.1.1", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" diff --git a/packages/http-content-encoding/package.json b/packages/http-content-encoding/package.json index 85fbb1e24..edd390bcb 100644 --- a/packages/http-content-encoding/package.json +++ b/packages/http-content-encoding/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-content-encoding", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP content encoding middleware for the middy framework", "type": "module", "engines": { @@ -65,11 +65,11 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@datastream/core": "0.4.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-content-negotiation/package.json b/packages/http-content-negotiation/package.json index 06a2b195c..be693f19e 100644 --- a/packages/http-content-negotiation/package.json +++ b/packages/http-content-negotiation/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-content-negotiation", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP content negotiation middleware for the middy framework", "type": "module", "engines": { @@ -62,11 +62,11 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4", + "@middy/util": "7.4.0", "negotiator": "1.0.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-cors/package.json b/packages/http-cors/package.json index fb0741230..c36ca9407 100644 --- a/packages/http-cors/package.json +++ b/packages/http-cors/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-cors", - "version": "7.3.4", + "version": "7.4.0", "description": "CORS (Cross-Origin Resource Sharing) middleware for the middy framework", "type": "module", "engines": { @@ -61,10 +61,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-error-handler/package.json b/packages/http-error-handler/package.json index 4d9bcb298..d67e187b3 100644 --- a/packages/http-error-handler/package.json +++ b/packages/http-error-handler/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-error-handler", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP error handler middleware for the middy framework", "type": "module", "engines": { @@ -63,10 +63,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/http-errors": "^2.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-event-normalizer/package.json b/packages/http-event-normalizer/package.json index b4dbeaaca..1a8172e0f 100644 --- a/packages/http-event-normalizer/package.json +++ b/packages/http-event-normalizer/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-event-normalizer", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP event normalizer middleware for the middy framework", "type": "module", "engines": { @@ -62,7 +62,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-header-normalizer/package.json b/packages/http-header-normalizer/package.json index 9dab9e9e3..c4a7da7d3 100644 --- a/packages/http-header-normalizer/package.json +++ b/packages/http-header-normalizer/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-header-normalizer", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP header normalizer middleware for the middy framework", "type": "module", "engines": { @@ -64,7 +64,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/node": "^22.0.0" } } diff --git a/packages/http-json-body-parser/package.json b/packages/http-json-body-parser/package.json index 70b367e22..7ff202207 100644 --- a/packages/http-json-body-parser/package.json +++ b/packages/http-json-body-parser/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-json-body-parser", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP JSON body parser middleware for the middy framework", "type": "module", "engines": { @@ -64,10 +64,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" diff --git a/packages/http-multipart-body-parser/package.json b/packages/http-multipart-body-parser/package.json index b926ec576..c7937f01f 100644 --- a/packages/http-multipart-body-parser/package.json +++ b/packages/http-multipart-body-parser/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-multipart-body-parser", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP multipart body parser middleware for the middy framework", "type": "module", "engines": { @@ -63,10 +63,10 @@ }, "dependencies": { "@fastify/busboy": "3.2.0", - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" diff --git a/packages/http-partial-response/package.json b/packages/http-partial-response/package.json index 513e1d6f3..ae416df1b 100644 --- a/packages/http-partial-response/package.json +++ b/packages/http-partial-response/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-partial-response", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP partial response middleware for the middy framework", "type": "module", "engines": { @@ -63,11 +63,11 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4", + "@middy/util": "7.4.0", "json-mask": "2.0.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-response-serializer/package.json b/packages/http-response-serializer/package.json index a15430fa8..d43a3e639 100644 --- a/packages/http-response-serializer/package.json +++ b/packages/http-response-serializer/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-response-serializer", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP response serializer middleware for the middy framework", "type": "module", "engines": { @@ -65,10 +65,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-router/package.json b/packages/http-router/package.json index c1f8a270a..a0ef51d0d 100644 --- a/packages/http-router/package.json +++ b/packages/http-router/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-router", - "version": "7.3.4", + "version": "7.4.0", "description": "HTTP event router for the middy framework", "type": "module", "engines": { @@ -62,10 +62,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-security-headers/package.json b/packages/http-security-headers/package.json index 58bd21ac5..a21519d8b 100644 --- a/packages/http-security-headers/package.json +++ b/packages/http-security-headers/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-security-headers", - "version": "7.3.4", + "version": "7.4.0", "description": "Applies best practice security headers to responses. It's a simplified port of HelmetJS", "type": "module", "engines": { @@ -65,10 +65,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/http-urlencode-body-parser/package.json b/packages/http-urlencode-body-parser/package.json index adf2b494f..b9ad1668a 100644 --- a/packages/http-urlencode-body-parser/package.json +++ b/packages/http-urlencode-body-parser/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-urlencode-body-parser", - "version": "7.3.4", + "version": "7.4.0", "description": "Urlencode body parser middleware for the middy framework", "type": "module", "engines": { @@ -63,10 +63,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" diff --git a/packages/http-urlencode-path-parser/package.json b/packages/http-urlencode-path-parser/package.json index b29eb71f1..b02a73626 100644 --- a/packages/http-urlencode-path-parser/package.json +++ b/packages/http-urlencode-path-parser/package.json @@ -1,6 +1,6 @@ { "name": "@middy/http-urlencode-path-parser", - "version": "7.3.4", + "version": "7.4.0", "description": "Urlencode path parser middleware for the middy framework", "type": "module", "engines": { @@ -63,10 +63,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" diff --git a/packages/input-output-logger/package.json b/packages/input-output-logger/package.json index 5892b3ae5..bb133ef63 100644 --- a/packages/input-output-logger/package.json +++ b/packages/input-output-logger/package.json @@ -1,6 +1,6 @@ { "name": "@middy/input-output-logger", - "version": "7.3.4", + "version": "7.4.0", "description": "Input and output logger middleware for the middy framework", "type": "module", "engines": { @@ -62,11 +62,11 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@datastream/core": "0.4.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/rds-signer/package.json b/packages/rds-signer/package.json index 2b288e7de..a6ea8fb0a 100644 --- a/packages/rds-signer/package.json +++ b/packages/rds-signer/package.json @@ -1,6 +1,6 @@ { "name": "@middy/rds-signer", - "version": "7.3.4", + "version": "7.4.0", "description": "RDS (Relational Database Service) credentials middleware for the middy framework", "type": "module", "engines": { @@ -70,11 +70,11 @@ } }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/rds-signer": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/s3-object-response/package.json b/packages/s3-object-response/package.json index 9c94451ab..ec2f354eb 100644 --- a/packages/s3-object-response/package.json +++ b/packages/s3-object-response/package.json @@ -1,6 +1,6 @@ { "name": "@middy/s3-object-response", - "version": "7.3.4", + "version": "7.4.0", "description": "S3 object response handling middleware for the middy framework", "type": "module", "engines": { @@ -70,11 +70,11 @@ } }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-s3": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/s3/package.json b/packages/s3/package.json index c8fde916b..66c776f36 100644 --- a/packages/s3/package.json +++ b/packages/s3/package.json @@ -1,6 +1,6 @@ { "name": "@middy/s3", - "version": "7.3.4", + "version": "7.4.0", "description": "S3 middleware for the middy framework", "type": "module", "engines": { @@ -60,7 +60,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "peerDependencies": { "@aws-sdk/client-s3": "^3.0.0" @@ -72,7 +72,7 @@ }, "devDependencies": { "@aws-sdk/client-s3": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/secrets-manager/package.json b/packages/secrets-manager/package.json index 63f77bd38..522defbac 100644 --- a/packages/secrets-manager/package.json +++ b/packages/secrets-manager/package.json @@ -1,6 +1,6 @@ { "name": "@middy/secrets-manager", - "version": "7.3.4", + "version": "7.4.0", "description": "Secrets Manager middleware for the middy framework", "type": "module", "engines": { @@ -60,7 +60,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "peerDependencies": { "@aws-sdk/client-secrets-manager": "^3.0.0" @@ -72,7 +72,7 @@ }, "devDependencies": { "@aws-sdk/client-secrets-manager": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/service-discovery/package.json b/packages/service-discovery/package.json index 26d2221c8..acb98f3bc 100644 --- a/packages/service-discovery/package.json +++ b/packages/service-discovery/package.json @@ -1,6 +1,6 @@ { "name": "@middy/service-discovery", - "version": "7.3.4", + "version": "7.4.0", "description": "Service Discovery (Cloud Map) instances middleware for the middy framework", "type": "module", "engines": { @@ -70,11 +70,11 @@ } }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { "@aws-sdk/client-servicediscovery": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/sqs-partial-batch-failure/package.json b/packages/sqs-partial-batch-failure/package.json index e0ec6acec..2d2eb5f7d 100644 --- a/packages/sqs-partial-batch-failure/package.json +++ b/packages/sqs-partial-batch-failure/package.json @@ -1,6 +1,6 @@ { "name": "@middy/sqs-partial-batch-failure", - "version": "7.3.4", + "version": "7.4.0", "description": "SQS partial batch failure middleware for the middy framework", "type": "module", "engines": { @@ -63,7 +63,7 @@ }, "devDependencies": { "@aws-sdk/client-sqs": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@serverless/event-mocks": "^1.1.1", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" diff --git a/packages/ssm/package.json b/packages/ssm/package.json index c86741e64..d8e9ca59a 100644 --- a/packages/ssm/package.json +++ b/packages/ssm/package.json @@ -1,6 +1,6 @@ { "name": "@middy/ssm", - "version": "7.3.4", + "version": "7.4.0", "description": "SSM (EC2 Systems Manager) parameters middleware for the middy framework", "type": "module", "engines": { @@ -62,7 +62,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "peerDependencies": { "@aws-sdk/client-ssm": "^3.0.0" @@ -74,7 +74,7 @@ }, "devDependencies": { "@aws-sdk/client-ssm": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/sts/package.json b/packages/sts/package.json index e21c2078c..59dae742e 100644 --- a/packages/sts/package.json +++ b/packages/sts/package.json @@ -1,6 +1,6 @@ { "name": "@middy/sts", - "version": "7.3.4", + "version": "7.4.0", "description": "STS (Security Token Service) credentials middleware for the middy framework", "type": "module", "engines": { @@ -62,7 +62,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "peerDependencies": { "@aws-sdk/client-sts": "^3.0.0" @@ -74,7 +74,7 @@ }, "devDependencies": { "@aws-sdk/client-sts": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/util/package.json b/packages/util/package.json index e1bca6712..9ab892a89 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,6 +1,6 @@ { "name": "@middy/util", - "version": "7.3.4", + "version": "7.4.0", "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (util package)", "type": "module", "engines": { @@ -57,7 +57,7 @@ }, "devDependencies": { "@aws-sdk/client-ssm": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/validator/package.json b/packages/validator/package.json index 66fdee114..d3b43a873 100644 --- a/packages/validator/package.json +++ b/packages/validator/package.json @@ -1,6 +1,6 @@ { "name": "@middy/validator", - "version": "7.3.4", + "version": "7.4.0", "description": "Validator middleware for the middy framework", "type": "module", "engines": { @@ -69,7 +69,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4", + "@middy/util": "7.4.0", "ajv": "8.20.0", "ajv-errors": "3.0.0", "ajv-formats": "3.0.1", @@ -78,7 +78,7 @@ "ajv-keywords": "5.1.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/http-errors": "^2.0.0", "@types/node": "^22.0.0", diff --git a/packages/warmup/package.json b/packages/warmup/package.json index 7518bdecb..1e024dfa0 100644 --- a/packages/warmup/package.json +++ b/packages/warmup/package.json @@ -1,6 +1,6 @@ { "name": "@middy/warmup", - "version": "7.3.4", + "version": "7.4.0", "description": "Warmup (cold start mitigation) middleware for the middy framework", "type": "module", "engines": { @@ -62,7 +62,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/packages/ws-json-body-parser/package.json b/packages/ws-json-body-parser/package.json index 9d00dedd3..0bdcb154d 100644 --- a/packages/ws-json-body-parser/package.json +++ b/packages/ws-json-body-parser/package.json @@ -1,6 +1,6 @@ { "name": "@middy/ws-json-body-parser", - "version": "7.3.4", + "version": "7.4.0", "description": "WebSocket JSON body parser middleware for the middy framework", "type": "module", "engines": { @@ -64,10 +64,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "type-fest": "^5.0.0" diff --git a/packages/ws-response/package.json b/packages/ws-response/package.json index 8d1367139..0fad8b7e2 100644 --- a/packages/ws-response/package.json +++ b/packages/ws-response/package.json @@ -1,6 +1,6 @@ { "name": "@middy/ws-response", - "version": "7.3.4", + "version": "7.4.0", "description": "WebSocket response handling middleware for the middy framework", "type": "module", "engines": { @@ -62,7 +62,7 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "peerDependencies": { "@aws-sdk/client-apigatewaymanagementapi": "^3.0.0" @@ -74,7 +74,7 @@ }, "devDependencies": { "@aws-sdk/client-apigatewaymanagementapi": "^3.0.0", - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0", "aws-xray-sdk": "^3.3.3" diff --git a/packages/ws-router/package.json b/packages/ws-router/package.json index aed714c5b..8dee4e917 100644 --- a/packages/ws-router/package.json +++ b/packages/ws-router/package.json @@ -1,6 +1,6 @@ { "name": "@middy/ws-router", - "version": "7.3.4", + "version": "7.4.0", "description": "WebSocket event router for the middy framework", "type": "module", "engines": { @@ -62,10 +62,10 @@ "url": "https://github.com/sponsors/willfarrell" }, "dependencies": { - "@middy/util": "7.3.4" + "@middy/util": "7.4.0" }, "devDependencies": { - "@middy/core": "7.3.4", + "@middy/core": "7.4.0", "@types/aws-lambda": "^8.0.0", "@types/node": "^22.0.0" } diff --git a/websites/middy.js.org/package.json b/websites/middy.js.org/package.json index c172c56be..dab5f11a5 100644 --- a/websites/middy.js.org/package.json +++ b/websites/middy.js.org/package.json @@ -2,7 +2,7 @@ "name": "middy.js.org", "description": "SvelteKit SSR", "private": true, - "version": "7.3.4", + "version": "7.4.0", "type": "module", "scripts": { "start": "vite dev",