@@ -63,10 +63,12 @@ class AstroCookies implements AstroCookiesInterface {
63
63
#request: Request ;
64
64
#requestValues: Record < string , string > | null ;
65
65
#outgoing: Map < string , [ string , string , boolean ] > | null ;
66
+ #consumed: boolean ;
66
67
constructor ( request : Request ) {
67
68
this . #request = request ;
68
69
this . #requestValues = null ;
69
70
this . #outgoing = null ;
71
+ this . #consumed = false ;
70
72
}
71
73
72
74
/**
@@ -148,6 +150,16 @@ class AstroCookies implements AstroCookiesInterface {
148
150
* @param options Options for the cookie, such as the path and security settings.
149
151
*/
150
152
set ( key : string , value : string | Record < string , any > , options ?: AstroCookieSetOptions ) : void {
153
+ if ( this . #consumed) {
154
+ const warning = new Error (
155
+ 'Astro.cookies.set() was called after the cookies had already been sent to the browser.\n' +
156
+ 'This may have happened if this method was called in an imported component.\n' +
157
+ 'Please make sure that Astro.cookies.set() is only called in the frontmatter of the main page.'
158
+ ) ;
159
+ warning . name = "Warning" ;
160
+ // eslint-disable-next-line no-console
161
+ console . warn ( warning ) ;
162
+ }
151
163
let serializedValue : string ;
152
164
if ( typeof value === 'string' ) {
153
165
serializedValue = value ;
@@ -193,6 +205,15 @@ class AstroCookies implements AstroCookiesInterface {
193
205
}
194
206
}
195
207
208
+ /**
209
+ * Behaves the same as AstroCookies.prototype.headers(),
210
+ * but allows a warning when cookies are set after the instance is consumed.
211
+ */
212
+ static consume ( cookies : AstroCookies ) : Generator < string , void , unknown > {
213
+ cookies . #consumed = true ;
214
+ return cookies . headers ( ) ;
215
+ }
216
+
196
217
#ensureParsed( options : AstroCookieGetOptions | undefined = undefined ) : Record < string , string > {
197
218
if ( ! this . #requestValues) {
198
219
this . #parse( options ) ;
0 commit comments