@middy/util
Advanced tools
+6
-4
@@ -161,8 +161,10 @@ // Copyright 2017 - 2026 will Farrell, Luciano Mammino, and Middy contributors. | ||
| declare function isJsonStructured(text: unknown): boolean; | ||
| declare const jsonContentTypePattern: RegExp; | ||
| declare function decodeBody(event: { | ||
| body?: string | null; | ||
| isBase64Encoded?: boolean; | ||
| }): string | null | undefined; | ||
| declare function decodeBody( | ||
| body: string | null | undefined, | ||
| isBase64Encoded?: boolean, | ||
| ): string | null | undefined; | ||
@@ -169,0 +171,0 @@ declare const lambdaContextKeys: string[]; |
+63
-3
@@ -439,2 +439,44 @@ // Copyright 2017 - 2026 will Farrell, Luciano Mammino, and Middy contributors. | ||
| // setToContext fast-path | ||
| // | ||
| // Many middlewares (kms/ssm/secrets-manager/dynamodb/s3/sts/…) follow the | ||
| // same pattern: after `processCache` resolves `value`, when `setToContext` | ||
| // is set they re-`await getInternal(fetchDataKeys, request)` solely to copy | ||
| // the same values to `request.context` under sanitized key names. On warm | ||
| // invocations every entry in `value` is already resolved, so the extra | ||
| // await + per-key regex + null-prototype-object allocation in `getInternal` | ||
| // is dead work. | ||
| // | ||
| // `buildSetToContextSpec(options)` is called once at factory time and | ||
| // returns either `null` (when `setToContext` is false) or the precomputed | ||
| // `[[originalKey, sanitizedKey], …]` pairs. | ||
| // | ||
| // `assignSetToContext(spec, value, request)` is called once per invocation. | ||
| // Returns `undefined` synchronously when all entries are resolved (the | ||
| // common warm path), or a Promise when at least one is still pending. The | ||
| // caller should `if (p) await p` so the sync path keeps zero microtask hops. | ||
| export const buildSetToContextSpec = (options) => | ||
| options.setToContext | ||
| ? Object.keys(options.fetchData).map((k) => [k, sanitizeKey(k)]) | ||
| : null; | ||
| export const assignSetToContext = (spec, value, request) => { | ||
| for (let i = 0; i < spec.length; i++) { | ||
| const v = value[spec[i][0]]; | ||
| if (v !== null && typeof v?.then === "function") { | ||
| // Cold path: at least one value still pending; defer to | ||
| // `getInternal` for the standard await+sanitize+assign flow. | ||
| const keys = new Array(spec.length); | ||
| for (let j = 0; j < spec.length; j++) keys[j] = spec[j][0]; | ||
| return getInternal(keys, request).then((data) => { | ||
| Object.assign(request.context, data); | ||
| }); | ||
| } | ||
| } | ||
| const ctx = request.context; | ||
| for (let i = 0; i < spec.length; i++) { | ||
| ctx[spec[i][1]] = value[spec[i][0]]; | ||
| } | ||
| }; | ||
| // fetch Cache | ||
@@ -608,2 +650,16 @@ // Map keyed by cacheKey; value shape: { value:{fetchKey:Promise}, expiry, refresh?, modified? } | ||
| // Cheap structural-JSON heuristic: returns true if `text` starts with `{` | ||
| // or `[`, indicating a JSON object/array body. Use as a Content-Type | ||
| // guard where: | ||
| // - `{...}` / `[...]` → `application/json` | ||
| // - everything else → `text/plain` | ||
| // Deliberately excludes leading `"`: a JSON string `"hi"` parses to a JS | ||
| // string, which callers consistently treat as `text/plain`. Avoids running | ||
| // a full JSON.parse just to inspect the result's type. | ||
| export const isJsonStructured = (text) => { | ||
| if (typeof text !== "string") return false; | ||
| const c = text.charCodeAt(0); | ||
| return c === 123 || c === 91; // 123='{' 91='[' | ||
| }; | ||
| export const jsonSafeStringify = (value, replacer, space) => { | ||
@@ -620,5 +676,9 @@ try { | ||
| export const decodeBody = (event) => { | ||
| const { body, isBase64Encoded } = event; | ||
| if (typeof body === "undefined" || body === null) return body; | ||
| // Decode a request body, transparently handling base64-encoded payloads. | ||
| // Takes `body` and `isBase64Encoded` directly so callers (which already | ||
| // destructure them from `request.event`) don't pay for a second destructure | ||
| // inside this helper. Returns `body` unchanged when it's nullish so callers | ||
| // can decide whether absence is an error. | ||
| export const decodeBody = (body, isBase64Encoded) => { | ||
| if (body == null) return body; | ||
| return isBase64Encoded ? Buffer.from(body, "base64").toString() : body; | ||
@@ -625,0 +685,0 @@ }; |
+2
-2
| { | ||
| "name": "@middy/util", | ||
| "version": "7.6.3", | ||
| "version": "7.6.4", | ||
| "description": "🛵 The stylish Node.js middleware engine for AWS Lambda (util package)", | ||
@@ -60,3 +60,3 @@ "type": "module", | ||
| "@aws-sdk/client-ssm": "^3.0.0", | ||
| "@middy/core": "7.6.3", | ||
| "@middy/core": "7.6.4", | ||
| "@types/aws-lambda": "^8.0.0", | ||
@@ -63,0 +63,0 @@ "@types/node": "^22.0.0", |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
39461
7.56%1059
5.79%4
-20%