@@ -89,17 +89,19 @@ export interface ParseOptions {
89
89
decode ?: ( str : string ) => string | undefined ;
90
90
}
91
91
92
+ /**
93
+ * Cookies object.
94
+ */
95
+ export type Cookies = Record < string , string | undefined > ;
96
+
92
97
/**
93
98
* Parse a cookie header.
94
99
*
95
100
* Parse the given cookie header string into an object
96
101
* The object has the various cookies as keys(names) => values
97
102
*/
98
- export function parse (
99
- str : string ,
100
- options ?: ParseOptions ,
101
- ) : Record < string , string | undefined > {
102
- const obj : Record < string , string | undefined > = new NullObject ( ) ;
103
+ export function parse ( str : string , options ?: ParseOptions ) : Cookies {
104
+ const obj : Cookies = new NullObject ( ) ;
103
105
const len = str . length ;
104
106
// RFC 6265 sec 4.1.1, RFC 2616 2.2 defines a cookie name consists of one char minimum, plus '='.
105
107
if ( len < 2 ) return obj ;
@@ -155,6 +157,46 @@ function endIndex(str: string, index: number, min: number) {
155
157
return min ;
156
158
}
157
159
160
+ export interface StringifyOptions {
161
+ /**
162
+ * Specifies a function that will be used to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1).
163
+ * Since value of a cookie has a limited character set (and must be a simple string), this function can be used to encode
164
+ * a value into a string suited for a cookie's value, and should mirror `decode` when parsing.
165
+ *
166
+ * @default encodeURIComponent
167
+ */
168
+ encode ?: ( str : string ) => string ;
169
+ }
170
+
171
+ /**
172
+ * Stringify a set of cookies into a `Cookie` header string.
173
+ */
174
+ export function stringify (
175
+ cookies : Cookies ,
176
+ options ?: StringifyOptions ,
177
+ ) : string {
178
+ const enc = options ?. encode || encodeURIComponent ;
179
+ const cookieStrings : string [ ] = [ ] ;
180
+
181
+ for ( const [ name , val ] of Object . entries ( cookies ) ) {
182
+ if ( val === undefined ) continue ;
183
+
184
+ if ( ! cookieNameRegExp . test ( name ) ) {
185
+ throw new TypeError ( `cookie name is invalid: ${ name } ` ) ;
186
+ }
187
+
188
+ const value = enc ( val ) ;
189
+
190
+ if ( ! cookieValueRegExp . test ( value ) ) {
191
+ throw new TypeError ( `cookie val is invalid: ${ val } ` ) ;
192
+ }
193
+
194
+ cookieStrings . push ( `${ name } =${ value } ` ) ;
195
+ }
196
+
197
+ return cookieStrings . join ( "; " ) ;
198
+ }
199
+
158
200
/**
159
201
* Serialize options.
160
202
*/
0 commit comments