Repository: h3js/h3 (TypeScript)

Issue:
Merge set cookie value for same name multiple times
### Environment

Nuxt 3.10.3 with Nitro 2.9.1
Node 20.10.0

### Reproduction

```js
setCookie(e, 'session', '123', { httpOnly: true })
// ...
setCookie(e, 'session', '123', { httpOnly: true, maxAge: /* 1m */ 60 * 60 * 24 * 30 })
```



### Describe the bug

will actually set cookie twice:
```http
set-cookie: session=123; Path=/; HttpOnly
set-cookie: session=123; Max-Age=2592000; Path=/; HttpOnly
```


### Additional context

_No response_

### Logs

_No response_


Discussion: send only the last value, or merge the session options would be more reasonable.


Issues with merging cookies will be solved in upcoming h3 v2



Fix (patch):
diff --git a/package.json b/package.json
index e140afe53..172ee2fd5 100644
--- a/package.json
+++ b/package.json
@@ -40,7 +40,7 @@
     "test:types": "tsc --noEmit --skipLibCheck"
   },
   "dependencies": {
-    "cookie-es": "^1.1.0",
+    "cookie-es": "^1.2.1",
     "iron-webcrypto": "^1.2.1",
     "ohash": "^1.1.3",
     "rou3": "^0.4.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 7fcff3739..340951ad5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,8 +9,8 @@ importers:
   .:
     dependencies:
       cookie-es:
-        specifier: ^1.1.0
-        version: 1.1.0
+        specifier: ^1.2.1
+        version: 1.2.1
       crossws:
         specifier: ^0.2.4
         version: 0.2.4
@@ -1268,6 +1268,9 @@ packages:
   cookie-es@1.1.0:
     resolution: {integrity: sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==}
 
+  cookie-es@1.2.1:
+    resolution: {integrity: sha512-ilTPDuxhZX44BSzzRB58gvSY2UevZKQM9fjisn7Z+NJ92CtSU6kO1+22ZN/agbEJANFjK85EiJJbi/gQv18OXA==}
+
   cookie-signature@1.0.6:
     resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
 
@@ -4284,6 +4287,8 @@ snapshots:
 
   cookie-es@1.1.0: {}
 
+  cookie-es@1.2.1: {}
+
   cookie-signature@1.0.6: {}
 
   cookie@0.6.0: {}
@@ -4916,7 +4921,7 @@ snapshots:
 
   h3-nightly@2.0.0-1720699896.4a34c89(crossws@0.2.4):
     dependencies:
-      cookie-es: 1.1.0
+      cookie-es: 1.2.1
       iron-webcrypto: 1.2.1
       ohash: 1.1.3
       rou3: 0.4.0
diff --git a/src/utils/cookie.ts b/src/utils/cookie.ts
index 3779bc604..8ea326cb4 100644
--- a/src/utils/cookie.ts
+++ b/src/utils/cookie.ts
@@ -1,6 +1,10 @@
-import type { CookieSerializeOptions } from "cookie-es";
+import type { CookieSerializeOptions, SetCookie } from "cookie-es";
 import type { H3Event } from "../types";
-import { parse as parseCookie, serialize as serializeCookie } from "cookie-es";
+import {
+  parse as parseCookie,
+  serialize as serializeCookie,
+  parseSetCookie,
+} from "cookie-es";
 
 /**
  * Parse the request to get HTTP Cookie header string and returning an object of all cookie name-value pairs.
@@ -54,12 +58,15 @@ export function setCookie(
   }
 
   // Merge and deduplicate unique set-cookie headers
-  const newCookieKey = _getDistinctCookieKey(name, options || {});
+  const newCookieKey = _getDistinctCookieKey(
+    name,
+    (options || {}) as SetCookie,
+  );
   event.response.headers.delete("set-cookie");
   for (const cookie of currentCookies) {
     const _key = _getDistinctCookieKey(
       cookie.split("=")?.[0],
-      parseCookie(cookie),
+      parseSetCookie(cookie),
     );
     if (_key === newCookieKey) {
       continue;
@@ -175,13 +182,13 @@ export function splitCookiesString(cookiesString: string | string[]): string[] {
   return cookiesStrings;
 }
 
-function _getDistinctCookieKey(name: string, options: CookieSerializeOptions) {
+function _getDistinctCookieKey(name: string, options: Partial<SetCookie>) {
   return [
     name,
     options.domain || "",
-    options.path || "",
-    options.secure || "",
-    options.httpOnly || "",
-    options.sameSite || "",
+    options.path || "/",
+    Boolean(options.secure),
+    Boolean(options.httpOnly),
+    Boolean(options.sameSite),
   ].join(";");
 }