From 1a73c16ccfd5eb98a8b10d6ab887993a0fea4f2a Mon Sep 17 00:00:00 2001 From: barbapapazes Date: Sat, 28 Mar 2026 02:07:01 +0000 Subject: [PATCH] content: create monthly updates --- .../blog/2026-03-28-march-monthly-updates.md | 446 ++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 content/blog/2026-03-28-march-monthly-updates.md diff --git a/content/blog/2026-03-28-march-monthly-updates.md b/content/blog/2026-03-28-march-monthly-updates.md new file mode 100644 index 00000000..51edf4a4 --- /dev/null +++ b/content/blog/2026-03-28-march-monthly-updates.md @@ -0,0 +1,446 @@ +--- +title: Monthly updates (March 2026) +description: 38 releases this month! What's new in the UnJS ecosystem? +authors: + - name: + picture: + twitter: +category: + - releases +packages: + - c12 + - cookie-es + - env-runner + - giget + - hookable + - httpxy + - impound + - magic-regexp + - mlly + - nf3 + - obuild + - ocache + - std-env + - unhead + - unimport + - unrouting + - unstorage +publishedAt: 2026-03-28T02:07:01.583Z +modifiedAt: 2026-03-28T02:07:01.583Z +--- + +## c12 + +This month, we release 1 new release (0 major release, 0 minor release and 1 patch release): + +- [v4.0.0-beta.4](https://github.com/unjs/c12/releases/tag/v4.0.0-beta.4) + +### fixes + +- Bust ESM module cache for native js config imports ([#306](https://github.com/unjs/c12/pull/306)) +- **loader:** Use statSync to detect directories with dots in name ([#305](https://github.com/unjs/c12/pull/305)) + +## cookie-es + +This month, we release 4 new releases (1 major release, 1 minor release and 2 patch releases): + +- [v3.1.1](https://github.com/unjs/cookie-es/releases/tag/v3.1.1) +- [v3.1.0](https://github.com/unjs/cookie-es/releases/tag/v3.1.0) +- [v3.0.1](https://github.com/unjs/cookie-es/releases/tag/v3.0.1) +- [v3.0.0](https://github.com/unjs/cookie-es/releases/tag/v3.0.0) + +### enhancements + +- **serialize:** Support custom `stringify` option for value coercion ([6f659f8](https://github.com/unjs/cookie-es/commit/6f659f8)) + +### fixes + +- Accept non-string values in serializeCookie ([55855c6](https://github.com/unjs/cookie-es/commit/55855c6)) + +### refactors + +- Optimize serialize arg resolution ([8597643](https://github.com/unjs/cookie-es/commit/8597643)) + +### `serialize()` accepts a `setcookie` object + +In addition to `serialize(name, val, opts?)`, you can now pass a single object: +```ts +// v2 (still works) +serialize("session", "abc", { httpOnly: true, secure: true }); +// v3 +serialize({ name: "session", value: "abc", httpOnly: true, secure: true }); +``` + +### stricter validation in `serialize()` + +- `maxAge` must be an integer, clamped to `[0, 400 days]` +- `SameSite=None` requires `Secure` — `serialize({ name: "x", value: "y", sameSite: "none" })` now throws +- `Partitioned` requires `Secure` — `serialize({ name: "x", value: "y", partitioned: true })` now throws +- `__Secure-`/`__Host-` prefix cookies must have `Secure`; `__Host-` must also have `Path=/` and no `Domain` +- Cookie name, value, domain, and path are validated against stricter regexps (was the looser `field-content` pattern) + +### `parsesetcookie()` returns `undefined` for invalid input + +Previously always returned an object: +```ts +// v2: { name: "", value: "" } +// v3: undefined +parseSetCookie(""); +``` + +### `parsesetcookie()` enforces stricter limits + +- Returns `undefined` if name+value exceeds 4096 octets +- Ignores attribute values exceeding 1024 octets +- Caps `Max-Age` to 400-day limit +- Strips leading dot and lowercases `Domain` values +- Defaults unknown `SameSite` to `"lax"` +- Rejects prototype-polluting names (`__proto__`, `constructor`, etc.) + +### `cookieserializeoptions` is now a compat alias + +The canonical type is `CookieStringifyOptions`. `CookieSerializeOptions` is `CookieStringifyOptions & Omit`. + +### `stringifycookie()` + +The inverse of `parse()`: converts a `Cookies` object back into a `Cookie` header string: +```ts +const cookies = parse("session=abc; theme=dark"); +// => { session: "abc", theme: "dark" } +stringifyCookie(cookies); +// => "session=abc; theme=dark" +``` +> **`stringifyCookie()` vs `serialize()`**: `serialize()` builds a `Set-Cookie` header for a single cookie with attributes (e.g. `HttpOnly`, `Secure`). `stringifyCookie()` is the roundtrip companion to `parse()` for the `Cookie` header. + +### `parse()` new options + + + +### `allowmultiple` + +When enabled, duplicate cookie names return an array of values instead of only the first: +```ts +// v2: { id: "first" } (last duplicate wins) +// v3: +parse("id=first; id=second", { allowMultiple: true }); +// => { id: ["first", "second"] } +``` + +### `filter` + +Skip specific keys during parsing: +```ts +parse("session=abc; theme=dark; debug=1", { +filter: (key) => key !== "debug", +}); +// => { session: "abc", theme: "dark" } +``` + +### `decode` return type widened + +Custom `decode` can now return `undefined` to exclude a cookie from the result: +```ts +parse("session=abc; token=secret", { +decode: (val) => (val === "secret" ? undefined : val), +}); +// => { session: "abc", token: undefined } +``` + +## env-runner + +This month, we release 4 new releases (0 major release, 0 minor release and 4 patch releases): + +- [v0.1.7](https://github.com/unjs/env-runner/releases/tag/v0.1.7) +- [v0.1.6](https://github.com/unjs/env-runner/releases/tag/v0.1.6) +- [v0.1.3](https://github.com/unjs/env-runner/releases/tag/v0.1.3) +- [v0.1.2](https://github.com/unjs/env-runner/releases/tag/v0.1.2) + +### enhancements + +- Support custom export conditions ([#5](https://github.com/unjs/env-runner/pull/5)) +- **vercel:** Add vercel runner ([#3](https://github.com/unjs/env-runner/pull/3)) +- Netlify runner ([7e47106](https://github.com/unjs/env-runner/commit/7e47106)) +- **vercel:** Shim full `@vercel/request-context` for `@vercel/functions` compat ([cb9a358](https://github.com/unjs/env-runner/commit/cb9a358)) + +### fixes + +- **miniflare:** Pass through cloudflare:* imports to workerd ([#6](https://github.com/unjs/env-runner/pull/6)) +- **deno:** Use stdin/stdout IPC and prevent `deno.lock` creation ([1df4340](https://github.com/unjs/env-runner/commit/1df4340)) + +### refactors + +- Remove graceful shutdowns ([6e969b1](https://github.com/unjs/env-runner/commit/6e969b1)) + +## giget + +This month, we release 1 new release (0 major release, 1 minor release and 0 patch release): + +- [v3.2.0](https://github.com/unjs/giget/releases/tag/v3.2.0) + +### enhancements + +- `git:` provider with sparse cloning support ([#211](https://github.com/unjs/giget/pull/211)) + +### fixes + +- **_utils:** Move hyphens to start of character classes in parseGitURI regex ([#256](https://github.com/unjs/giget/pull/256)) +- **cli:** Prevent duplicate error messages ([#220](https://github.com/unjs/giget/pull/220)) +- **gitlab:** Support subgroups and `::` subdir delimiter ([#141](https://github.com/unjs/giget/pull/141)) + +## hookable + +This month, we release 1 new release (0 major release, 1 minor release and 0 patch release): + +- [v6.1.0](https://github.com/unjs/hookable/releases/tag/v6.1.0) + +### enhancements + +- Add `clearHook(name)` ([#135](https://github.com/unjs/hookable/pull/135)) + +## httpxy + +This month, we release 2 new releases (0 major release, 2 minor releases and 0 patch release): + +- [v0.5.0](https://github.com/unjs/httpxy/releases/tag/v0.5.0) +- [v0.4.0](https://github.com/unjs/httpxy/releases/tag/v0.4.0) + +### ⚠️ breaking: default keep-alive connection pooling + +`ProxyServer` and `proxyFetch` now use shared `http.Agent` / `https.Agent` instances with `keepAlive: true` (256 max sockets, 64 max free sockets) instead of creating a new socket per request. Set `agent: false` to restore previous per-request connection behavior. + +### performance improvements + +- **Default keep-alive agents** — Connection reuse via shared agent pools for both `ProxyServer` and `proxyFetch`. HTTP/2 incoming requests are excluded to avoid stream lifecycle conflicts. +- **Streaming request bodies in `proxyFetch`** — `ReadableStream` and `Blob` bodies are piped directly to upstream instead of buffering in memory. Bodies are still buffered when `followRedirects` is enabled for 307/308 replay. +- **Single-pass header merge** — `setupOutgoing` merges `req.headers` and `options.headers` in one pass instead of two spread operations. +- **Raw header pairs for response** — `proxyFetch` builds response headers from `rawHeaders` pairs instead of iterating a `Headers` object. +- **Plain-object header fast path** — When `init.headers` is a plain `Record`, headers are merged with `Object.assign` instead of wrapping in `Headers`. + +### bug fixes + +- Fix header merge regression preserving `:authority` → host override order for HTTP/2 +- Destroy outgoing request on readable body stream error in `proxyFetch` + +### benchmarks + +`bench/bench.ts -s -d 60s -c 128` +> Duration: **60s** | Connections: **128** | Mode: **sequential** + +### get (no body) + +| Proxy | Req/s | Scale | Avg | P50 | P99 | Throughput | +| :------------------ | ----: | ----: | ---: | ---: | ---: | ---------: | +| httpxy.server | 19694 | 1.00x | 6µs | 5µs | 33µs | 3.6MB/s | +| fast-proxy | 19664 | 1.00x | 7µs | 4µs | 38µs | 3.6MB/s | +| @fastify/http-proxy | 18957 | 0.96x | 7µs | 4µs | 44µs | 3.5MB/s | +| httpxy.proxyFetch | 15433 | 0.78x | 8µs | 6µs | 34µs | 2.8MB/s | +| http-proxy-3 | 13010 | 0.66x | 10µs | 10µs | 13µs | 2.0MB/s | +| http-proxy | 12893 | 0.65x | 10µs | 10µs | 13µs | 2.0MB/s | + +### post (~1kb json) + +| Proxy | Req/s | Scale | Avg | P50 | P99 | Throughput | +| :------------------ | ----: | ----: | ---: | ---: | ---: | ---------: | +| httpxy.server | 17316 | 1.00x | 7µs | 6µs | 31µs | 20.6MB/s | +| fast-proxy | 15365 | 0.89x | 8µs | 5µs | 42µs | 18.3MB/s | +| @fastify/http-proxy | 15117 | 0.87x | 8µs | 5µs | 47µs | 18.1MB/s | +| httpxy.proxyFetch | 13179 | 0.76x | 10µs | 7µs | 41µs | 15.7MB/s | +| http-proxy-3 | 11487 | 0.66x | 11µs | 11µs | 15µs | 13.4MB/s | +| http-proxy | 11052 | 0.64x | 12µs | 11µs | 14µs | 12.9MB/s | + +### enhancements + +- HTTP/2 listener support ([#102](https://github.com/unjs/httpxy/pull/102)) +- **fetch:** Add proxyFetch options for timeout, xfwd, changeOrigin, agent, followRedirects, HTTPS, and path merging ([efa9711](https://github.com/unjs/httpxy/commit/efa9711)) + +### fixes + +- **web-incoming:** Close downstream stream when upstream SSE aborts ([#103](https://github.com/unjs/httpxy/pull/103)) +- Handle relative Location URLs in redirect rewriting ([#20](https://github.com/unjs/httpxy/pull/20), [#104](https://github.com/unjs/httpxy/pull/104)) +- **web-outgoing:** Handle invalid response header characters gracefully ([#106](https://github.com/unjs/httpxy/pull/106)) +- **web-incoming:** Remove deprecated `req.abort()` and `req.on("aborted")` ([#107](https://github.com/unjs/httpxy/pull/107)) +- **web-outgoing:** Handle object target in redirect host rewrite ([#108](https://github.com/unjs/httpxy/pull/108)) +- **web-incoming:** Remove deprecated `req.on('aborted')` listener ([#110](https://github.com/unjs/httpxy/pull/110)) +- **ws:** Skip writing to closed socket on non-upgrade response ([#114](https://github.com/unjs/httpxy/pull/114)) +- **web-incoming:** Guard `req.socket` access in error handler ([#112](https://github.com/unjs/httpxy/pull/112)) +- **web-incoming:** Defer pipe until socket connects ([#111](https://github.com/unjs/httpxy/pull/111)) +- **server:** Catch synchronous exceptions in middleware passes ([#109](https://github.com/unjs/httpxy/pull/109)) +- **web-incoming:** Emit econnreset on client disconnect ([#115](https://github.com/unjs/httpxy/pull/115)) +- **ws:** Handle response stream errors on failed WS upgrade ([#116](https://github.com/unjs/httpxy/pull/116)) +- **web-outgoing:** Include HTTP 303 in redirect location rewriting ([#119](https://github.com/unjs/httpxy/pull/119)) +- **web-outgoing:** Skip empty header names ([#121](https://github.com/unjs/httpxy/pull/121)) +- **ssl:** Prevent undefined target values from overwriting ssl options ([#118](https://github.com/unjs/httpxy/pull/118)) +- **utils:** Preserve target URL query string in path merging ([#117](https://github.com/unjs/httpxy/pull/117)) +- **middleware:** Do not append duplicate x-forwarded-* header values ([#120](https://github.com/unjs/httpxy/pull/120)) +- **web-outgoing:** Strip transfer-encoding on 204/304 ([#122](https://github.com/unjs/httpxy/pull/122)) +- **web-incoming:** Use `isSSL` regex for consistent https/wss protocol checks ([#123](https://github.com/unjs/httpxy/pull/123)) +- **ws:** Preserve wss:// protocol and fix error handling in proxyUpgrade ([cb01605](https://github.com/unjs/httpxy/commit/cb01605)) + +## impound + +This month, we release 6 new releases (0 major release, 1 minor release and 5 patch releases): + +- [v1.1.5](https://github.com/unjs/impound/releases/tag/v1.1.5) +- [v1.1.4](https://github.com/unjs/impound/releases/tag/v1.1.4) +- [v1.1.3](https://github.com/unjs/impound/releases/tag/v1.1.3) +- [v1.1.2](https://github.com/unjs/impound/releases/tag/v1.1.2) +- [v1.1.1](https://github.com/unjs/impound/releases/tag/v1.1.1) +- [v1.1.0](https://github.com/unjs/impound/releases/tag/v1.1.0) + +### bug fixes + +- Deduplicate warnedMessages - by @danielroe [(30fd6)](https://github.com/unjs/impound/commit/30fd696) +- Strip queries when printing importer - by @danielroe [(70e6e)](https://github.com/unjs/impound/commit/70e6e24) + +### features + +- Pass importer as second argument to functional patterns - by @danielroe [(af00c)](https://github.com/unjs/impound/commit/af00c39) +- Add warn option for log deduplication - by @danielroe [(64d94)](https://github.com/unjs/impound/commit/64d94a3) +- Add onViolation callback - by @danielroe [(12882)](https://github.com/unjs/impound/commit/12882f0) +- Support suggestions in pattern error messages - by @danielroe [(e54d6)](https://github.com/unjs/impound/commit/e54d6a4) +- Add import tracing for rich violation diagnostics - by @danielroe [(4a936)](https://github.com/unjs/impound/commit/4a936ab) +- Add `excludeFiles` option - by @danielroe [(40885)](https://github.com/unjs/impound/commit/4088521) + +### 🏎 performance + +- Inline proxy code - by @danielroe [(205b9)](https://github.com/unjs/impound/commit/205b9fa) + +## magic-regexp + +This month, we release 1 new release (0 major release, 1 minor release and 0 patch release): + +- [v0.11.0](https://github.com/unjs/magic-regexp/releases/tag/v0.11.0) + +### 🏎 performance + +- Drop some dependencies 🚀 - by @danielroe [(58af7)](https://github.com/unjs/magic-regexp/commit/58af770) + +## mlly + +This month, we release 2 new releases (0 major release, 0 minor release and 2 patch releases): + +- [v1.8.2](https://github.com/unjs/mlly/releases/tag/v1.8.2) +- [v1.8.1](https://github.com/unjs/mlly/releases/tag/v1.8.1) + +### fixes + +- Generic angle bracket parsing ([#341](https://github.com/unjs/mlly/pull/341)) + +### documentation + +- Fix typo ([#333](https://github.com/unjs/mlly/pull/333)) + +## nf3 + +This month, we release 4 new releases (0 major release, 0 minor release and 4 patch releases): + +- [v0.3.14](https://github.com/unjs/nf3/releases/tag/v0.3.14) +- [v0.3.13](https://github.com/unjs/nf3/releases/tag/v0.3.13) +- [v0.3.12](https://github.com/unjs/nf3/releases/tag/v0.3.12) +- [v0.3.11](https://github.com/unjs/nf3/releases/tag/v0.3.11) + +### fixes + +- Add `@takumi-rs/core` to `NodeNativePackages` ([#31](https://github.com/unjs/nf3/pull/31)) +- Add zigpty and md4x to node native pkgs ([ce71d9a](https://github.com/unjs/nf3/commit/ce71d9a)) + +### enhancements + +- Add `fullTraceInclude` option ([#4](https://github.com/unjs/nf3/pull/4)) +### fixes +- **plugin:** Use `traceInclude` ([#27](https://github.com/unjs/nf3/pull/27)) + +## obuild + +This month, we release 1 new release (0 major release, 0 minor release and 1 patch release): + +- [v0.4.32](https://github.com/unjs/obuild/releases/tag/v0.4.32) + +### fixes + +- **bundle:** Mark `#` subpath imports as external ([5841515](https://github.com/unjs/obuild/commit/5841515)) + +## ocache + +This month, we release 2 new releases (0 major release, 0 minor release and 2 patch releases): + +- [v0.1.4](https://github.com/unjs/ocache/releases/tag/v0.1.4) +- [v0.1.3](https://github.com/unjs/ocache/releases/tag/v0.1.3) + +### 🔥 performance + +- **cache:** Skip writing to lower tiers on multi-tier cache hit ([4fe0de7](https://github.com/unjs/ocache/commit/4fe0de7)) + +### enhancements + +- Respect `staleMaxAge` ([8915db3](https://github.com/unjs/ocache/commit/8915db3)) +- **cache:** Add `resolveCacheKey` and `.resolveKey()` ([#6](https://github.com/unjs/ocache/pull/6)) +- **storage:** Nullish `set` deletes entry instead of storing dead weight ([71d5f11](https://github.com/unjs/ocache/commit/71d5f11)) +- Multi-tier cache base ([#7](https://github.com/unjs/ocache/pull/7)) +- **cache:** Add `invalidateCache()` and `.invalidate()` ([#8](https://github.com/unjs/ocache/pull/8)) + +### fixes + +- Respect zero ttl ([#5](https://github.com/unjs/ocache/pull/5)) +- **http:** Merge default options when partial opts are provided ([#2](https://github.com/unjs/ocache/pull/2)) +- **cache:** Catch sync storage errors in get/set ([ee1bb02](https://github.com/unjs/ocache/commit/ee1bb02)) +- **cache:** Evict stale entry on SWR revalidation failure ([#9](https://github.com/unjs/ocache/pull/9)) +- **storage:** Proactively flush expired memory entries ([#10](https://github.com/unjs/ocache/pull/10)) + +## std-env + +This month, we release 1 new release (1 major release, 0 minor release and 0 patch release): + +- [v4.0.0](https://github.com/unjs/std-env/releases/tag/v4.0.0) + + + +## unhead + +This month, we release 3 new releases (0 major release, 0 minor release and 3 patch releases): + +- [v2.1.12](https://github.com/unjs/unhead/releases/tag/v2.1.12) +- [v2.1.11](https://github.com/unjs/unhead/releases/tag/v2.1.11) +- [v2.1.10](https://github.com/unjs/unhead/releases/tag/v2.1.10) + +### bug fixes + +- Harden prototype pollution - by @harlan-zw [(a6ed9)](https://github.com/unjs/unhead/commit/a6ed9f98) +- Case insensitive attr dedupe - by @harlan-zw [(3146b)](https://github.com/unjs/unhead/commit/3146b90c) + +### :warning: security + +- Fixed XSS bypass in useHeadSafe via attribute name injection (GHSA-g5xx-pwrp-g3fv). Users handling untrusted input with useHeadSafe should upgrade immediately. +### bug fixes +- **addons,schema-org**: Permissive peer dependencies - by @harlan-zw [(4c5d1)](https://github.com/unjs/unhead/commit/4c5d1818) + +## unimport + +This month, we release 2 new releases (0 major release, 0 minor release and 2 patch releases): + +- [v6.0.2](https://github.com/unjs/unimport/releases/tag/v6.0.2) +- [v6.0.1](https://github.com/unjs/unimport/releases/tag/v6.0.1) + +### bug fixes + +- Make `injectionUsage` non-enumerable - by @antfu [(6652f)](https://github.com/unjs/unimport/commit/6652f09) + +## unrouting + +This month, we release 1 new release (0 major release, 0 minor release and 1 patch release): + +- [v0.1.7](https://github.com/unjs/unrouting/releases/tag/v0.1.7) + + + +## unstorage + +This month, we release 2 new releases (0 major release, 0 minor release and 2 patch releases): + +- [v1.17.5](https://github.com/unjs/unstorage/releases/tag/v1.17.5) +- [v2.0.0-alpha.7](https://github.com/unjs/unstorage/releases/tag/v2.0.0-alpha.7) + +### fixes + +- **memory:** Proactively flush expired entries after ttl ([#759](https://github.com/unjs/unstorage/pull/759)) +- **fs:** Resolve ignore pattern matching for dot-prefix paths ([#751](https://github.com/unjs/unstorage/pull/751)) \ No newline at end of file