11//data
22import ReadonlyMap from '../data/ReadonlyMap.js' ;
3- //local
4- import type { Revision , CallableSession } from '../types.js' ;
3+ //client
4+ import type {
5+ CallableSession ,
6+ CookieOptions ,
7+ Revision
8+ } from '../types.js' ;
59
610/**
711 * Readonly session controller
812 */
913export class ReadSession extends ReadonlyMap < string , string | string [ ] > {
14+ //Every cookie setting needs a home base of its own so each key can
15+ //carry its own marching orders instead of borrowing one global plan.
16+ protected readonly _options = new Map < string , CookieOptions > ( ) ;
17+
1018 /**
1119 * Returns the session data
1220 */
1321 public get data ( ) {
1422 return Object . fromEntries ( this . _map ) ;
1523 }
24+
25+ /**
26+ * Returns the stored cookie settings
27+ */
28+ public get options ( ) {
29+ return Object . fromEntries ( this . _options ) ;
30+ }
31+
32+ /**
33+ * Returns the cookie settings for a single key
34+ */
35+ public getOptions ( name : string ) {
36+ return this . _options . get ( name ) ;
37+ }
1638}
1739
1840/**
@@ -26,8 +48,11 @@ export class WriteSession extends ReadSession {
2648 * Clear the session
2749 */
2850 public clear ( ) : void {
51+ //When the whole line retreats, clear both the session payload and the
52+ //cookie orders so nothing stale gets left behind on the field.
2953 for ( const name of this . keys ( ) ) {
3054 this . revisions . set ( name , { action : 'remove' } ) ;
55+ this . _options . delete ( name ) ;
3156 }
3257 this . _map . clear ( ) ;
3358 }
@@ -36,15 +61,36 @@ export class WriteSession extends ReadSession {
3661 * Delete a session entry
3762 */
3863 public delete ( name : string ) {
64+ //If a cookie key is removed, retire its settings too so the next write
65+ //does not accidentally reuse an old path, age, or security policy.
3966 this . revisions . set ( name , { action : 'remove' } ) ;
67+ this . _options . delete ( name ) ;
4068 return this . _map . delete ( name ) ;
4169 }
4270
4371 /**
4472 * Set a session entry
4573 */
46- public set ( name : string , value : string | string [ ] ) {
47- this . revisions . set ( name , { action : 'set' , value } ) ;
74+ public set (
75+ name : string ,
76+ value : string | string [ ] ,
77+ options ?: CookieOptions
78+ ) {
79+ //Each cookie gets its own shield here so one session key can be strict
80+ //and another can stay flexible without either stepping on the other.
81+ if ( options ) {
82+ this . _options . set ( name , { ...options } ) ;
83+ }
84+
85+ //Record both the value and the keyed cookie settings so the response
86+ //layer can serialize exactly what changed when the dust settles.
87+ const revisionOptions = this . _options . get ( name ) ;
88+ this . revisions . set ( name , {
89+ action : 'set' ,
90+ ...( revisionOptions ? { options : revisionOptions } : { } ) ,
91+ value
92+ } ) ;
93+
4894 return this . _map . set ( name , value ) ;
4995 }
5096}
@@ -57,22 +103,30 @@ export function session(data?: [string, string|string[]][]): CallableSession {
57103 const callable = Object . assign (
58104 ( name : string ) => store . get ( name ) ,
59105 {
106+ //Expose the same field controls on the callable wrapper so callers do
107+ //not need to care whether they got a class instance or the helper.
60108 clear : ( ) => store . clear ( ) ,
61109 delete : ( name : string ) => store . delete ( name ) ,
62110 entries : ( ) => store . entries ( ) ,
63111 forEach : (
64112 callback : ( value : string | string [ ] , key : string , map : Map < string , string | string [ ] > ) => void
65113 ) => store . forEach ( callback ) ,
66114 get : ( name : string ) => store . get ( name ) ,
115+ getOptions : ( name : string ) => store . getOptions ( name ) ,
67116 has : ( name : string ) => store . has ( name ) ,
68117 keys : ( ) => store . keys ( ) ,
69- set : ( name : string , value : string | string [ ] ) => store . set ( name , value ) ,
118+ set : (
119+ name : string ,
120+ value : string | string [ ] ,
121+ options ?: CookieOptions
122+ ) => store . set ( name , value , options ) ,
70123 values : ( ) => store . values ( )
71124 } as WriteSession
72125 ) ;
73126 //magic size/data property
74127 Object . defineProperty ( callable , 'size' , { get : ( ) => store . size } ) ;
75128 Object . defineProperty ( callable , 'data' , { get : ( ) => store . data } ) ;
129+ Object . defineProperty ( callable , 'options' , { get : ( ) => store . options } ) ;
76130 Object . defineProperty ( callable , 'revisions' , { get : ( ) => store . revisions } ) ;
77131 return callable ;
78- }
132+ }
0 commit comments