@prairielearn/session 3.0.4 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @prairielearn/session
2
2
 
3
+ ## 3.0.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 4ab7483: Remove remnants of `express-session` package
8
+
9
+ ## 3.0.5
10
+
11
+ ### Patch Changes
12
+
13
+ - 852c2e2: Upgrade all JavaScript dependencies
14
+
3
15
  ## 3.0.4
4
16
 
5
17
  ### Patch Changes
@@ -251,10 +251,13 @@ describe('session middleware', () => {
251
251
  await withServer(app, async ({ url }) => {
252
252
  const fetchWithCookies = fetchCookie(fetch);
253
253
  // Generate a new session.
254
- await fetchWithCookies(url);
254
+ const res = await fetchWithCookies(url);
255
+ assert.equal(res.status, 200);
256
+ await res.text();
255
257
  // Destroy the session.
256
258
  const destroyRes = await fetchWithCookies(`${url}/destroy`);
257
259
  assert.equal(destroyRes.status, 200);
260
+ await destroyRes.text();
258
261
  // Ensure the session cookie was cleared in the response.
259
262
  const header = destroyRes.headers.get('set-cookie');
260
263
  const cookies = parseSetCookie(header ?? '');
@@ -280,7 +283,7 @@ describe('session middleware', () => {
280
283
  app.get('/regenerate', asyncHandler(async (req, res) => {
281
284
  await req.session.regenerate();
282
285
  req.session.regenerated = true;
283
- res.sendStatus(200);
286
+ res.send('true');
284
287
  }));
285
288
  await withServer(app, async ({ url }) => {
286
289
  const fetchWithCookies = fetchCookie(fetch);
@@ -296,6 +299,7 @@ describe('session middleware', () => {
296
299
  // Regenerate the session.
297
300
  res = await fetchWithCookies(`${url}/regenerate`);
298
301
  assert.equal(res.status, 200);
302
+ assert.equal(await res.text(), 'true');
299
303
  // Ensure that the session cookie was changed.
300
304
  header = res.headers.get('set-cookie');
301
305
  cookies = parseSetCookie(header ?? '');
@@ -373,7 +377,7 @@ describe('session middleware', () => {
373
377
  }));
374
378
  app.get('/', (_req, res) => res.sendStatus(200));
375
379
  app.get('/extend', (req, res) => {
376
- req.session.setExpiration(Date.now() + 10000);
380
+ req.session.setExpiration(10000);
377
381
  res.sendStatus(200);
378
382
  });
379
383
  await withServer(app, async ({ url }) => {
@@ -381,6 +385,7 @@ describe('session middleware', () => {
381
385
  // Generate a new session.
382
386
  let res = await fetchWithCookies(url);
383
387
  assert.equal(res.status, 200);
388
+ await res.text();
384
389
  // Grab the original expiration date.
385
390
  let header = res.headers.get('set-cookie');
386
391
  let cookies = parseSetCookie(header ?? '');
@@ -388,16 +393,15 @@ describe('session middleware', () => {
388
393
  assert.isUndefined(cookies[0].maxAge);
389
394
  const originalExpirationDate = cookies[0].expires;
390
395
  assert(originalExpirationDate);
391
- // Also grab the expiration date from the store.
396
+ // Grab the session ID from the cookie.
392
397
  const sessionId = cookies[0].value.split('.')[0];
398
+ // Ensure that the expiration dates are consistent between the cookie and the store.
393
399
  const session = await store.get(sessionId);
394
- assert(session);
395
- const originalStoreExpirationDate = session.expiresAt;
396
- // Ensure that the expiration dates are consistent.
397
- assert.equal(originalExpirationDate.getTime(), originalStoreExpirationDate.getTime());
400
+ assert.equal(originalExpirationDate.getTime(), session?.expiresAt.getTime());
398
401
  // Make another request with the same session.
399
402
  res = await fetchWithCookies(`${url}/extend`);
400
403
  assert.equal(res.status, 200);
404
+ await res.text();
401
405
  // Ensure that the cookie was set again.
402
406
  header = res.headers.get('set-cookie');
403
407
  cookies = parseSetCookie(header ?? '');
@@ -407,12 +411,9 @@ describe('session middleware', () => {
407
411
  assert(newExpirationDate);
408
412
  // Ensure that the expiration date was extended.
409
413
  assert.notEqual(newExpirationDate.getTime(), originalExpirationDate.getTime());
410
- // Also grab the new expiration date from the store.
414
+ // Ensure that the expiration dates are consistent between the cookie and the store.
411
415
  const newSession = await store.get(sessionId);
412
- assert(newSession);
413
- const newStoreExpirationDate = newSession.expiresAt;
414
- // Ensure that the expiration dates are consistent.
415
- assert.equal(newExpirationDate.getTime(), newStoreExpirationDate.getTime());
416
+ assert.equal(newExpirationDate.getTime(), newSession?.expiresAt.getTime());
416
417
  });
417
418
  });
418
419
  it('does not persist session data if the session did not change', async () => {
@@ -434,11 +435,13 @@ describe('session middleware', () => {
434
435
  // Generate a new session.
435
436
  let res = await fetchWithCookies(url);
436
437
  assert.equal(res.status, 200);
438
+ await res.text();
437
439
  // Ensure the session was persisted.
438
440
  assert.equal(setCount, 1);
439
441
  // Make another request with the same session.
440
442
  res = await fetchWithCookies(url);
441
443
  assert.equal(res.status, 200);
444
+ await res.text();
442
445
  // Ensure the session was not persisted.
443
446
  assert.equal(setCount, 1);
444
447
  });
@@ -1 +1 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAC9B,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,YAAY,MAAM,uBAAuB,CAAC;AACjD,OAAO,WAAW,MAAM,cAAc,CAAC;AACvC,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,SAAS,cAAc,CAAC,MAAc;IACpC,OAAO,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;QACrC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC;QACpF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE;gBACN,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,IAAI;gBACd,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,QAAQ;gBAClB,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;YACtD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE;gBACN,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO,EAAE;oBACP,mBAAmB,EAAE,OAAO;iBAC7B;aACF,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE;gBACN,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO,EAAE;oBACP,mBAAmB,EAAE,MAAM;iBAC5B;aACF,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE;gBACN,MAAM,EAAE,MAAM;aACf;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO,EAAE;oBACP,mBAAmB,EAAE,OAAO;iBAC7B;aACF,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE;gBACN,MAAM,EAAE,MAAM;aACf;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,OAAO,EAAE;oBACP,mBAAmB,EAAE,MAAM;iBAC5B;aACF,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;QACtD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC1B,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,MAAM,EAAE,WAAW;YACnB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE;gBACN,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;aAChD;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBACnC,OAAO,EAAE;oBACP,kBAAkB,EAAE,uBAAuB;oBAC3C,mBAAmB,EAAE,MAAM;iBAC5B;aACF,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAEtC,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7D,MAAM,cAAc,GAAG,cAAc,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;YAC5D,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAE7C,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBACjC,OAAO,EAAE;oBACP,kBAAkB,EAAE,aAAa;oBACjC,mBAAmB,EAAE,OAAO;iBAC7B;aACF,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAEpC,MAAM,YAAY,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACzD,MAAM,aAAa,GAAG,cAAc,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;QACrD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACxB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC;YACxB,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC;YACvB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAE5C,IAAI,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;YAEpC,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACzB,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC;YAC1B,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACxB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,UAAU,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE;gBACxC,MAAM,EAAE,MAAM;aACf,CAAC,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QAChC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,GAAG,CAAC,GAAG,CACL,UAAU,EACV,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YAC9B,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CACH,CAAC;QAEF,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAE5C,0BAA0B;YAC1B,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAE5B,uBAAuB;YACvB,MAAM,UAAU,GAAG,MAAM,gBAAgB,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC;YAC5D,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAErC,yDAAyD;YACzD,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;YAE/C,yDAAyD;YACzD,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAI,EAAE;QACnC,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACxB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,GAAG,CACL,aAAa,EACb,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YAC9B,MAAM,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAC/B,GAAG,CAAC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;YAC/B,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CACH,CAAC;QAEF,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAE5C,0BAA0B;YAC1B,IAAI,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;YAExC,qCAAqC;YACrC,IAAI,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC3C,IAAI,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAE7C,0BAA0B;YAC1B,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,GAAG,aAAa,CAAC,CAAC;YAClD,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,8CAA8C;YAC9C,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACvC,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YACxC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;YAErD,yEAAyE;YACzE,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5D,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;YAElD,0DAA0D;YAC1D,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QAErD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,SAAS,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;YAC1D,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAEvD,0BAA0B;YAC1B,IAAI,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAE3C,kCAAkC;YAClC,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,GAAG,UAAU,CAAC;YAC1B,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAErC,kCAAkC;YAClC,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC9B,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YACtC,MAAM,CAAC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;YAEjD,yEAAyE;YACzE,wEAAwE;YACxE,WAAW;YACX,MAAM,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK,EAAE,IAAI,WAAW,EAAE;YACxB,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAE5C,0BAA0B;YAC1B,IAAI,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,8CAA8C;YAC9C,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,2CAA2C;YAC3C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE;gBACN,MAAM,EAAE,IAAI;aACb;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QACjD,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC9B,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC;YAC9C,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAE5C,0BAA0B;YAC1B,IAAI,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,qCAAqC;YACrC,IAAI,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC3C,IAAI,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC3C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,sBAAsB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAClD,MAAM,CAAC,sBAAsB,CAAC,CAAC;YAE/B,gDAAgD;YAChD,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,CAAC;YAChB,MAAM,2BAA2B,GAAG,OAAO,CAAC,SAAS,CAAC;YAEtD,mDAAmD;YACnD,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,OAAO,EAAE,EAAE,2BAA2B,CAAC,OAAO,EAAE,CAAC,CAAC;YAEtF,8CAA8C;YAC9C,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,wCAAwC;YACxC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YACvC,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACvC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7C,MAAM,CAAC,iBAAiB,CAAC,CAAC;YAE1B,gDAAgD;YAChD,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,sBAAsB,CAAC,OAAO,EAAE,CAAC,CAAC;YAE/E,oDAAoD;YACpD,MAAM,UAAU,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC9C,MAAM,CAAC,UAAU,CAAC,CAAC;YACnB,MAAM,sBAAsB,GAAG,UAAU,CAAC,SAAS,CAAC;YAEpD,mDAAmD;YACnD,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,OAAO,EAAE,EAAE,sBAAsB,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC3E,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,MAAM,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/C,KAAK,CAAC,GAAG,GAAG,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE;YAC5B,QAAQ,IAAI,CAAC,CAAC;YACd,MAAM,gBAAgB,CAAC,GAAG,IAAI,CAAC,CAAC;QAClC,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAC5C,0BAA0B;YAC1B,IAAI,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,oCAAoC;YACpC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAE1B,8CAA8C;YAC9C,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,wCAAwC;YACxC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,iCAAiC;QACjC,MAAM,SAAS,GAAG,OAAO,EAAE,CAAC;QAC5B,SAAS,CAAC,GAAG,CACX,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE;gBACN,IAAI,EAAE,gBAAgB;aACvB;SACF,CAAC,CACH,CAAC;QACF,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEtE,4DAA4D;QAC5D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;YACnB,MAAM,EAAE;gBACN,IAAI,EAAE,gBAAgB;gBACtB,UAAU,EAAE,CAAC,gBAAgB,EAAE,SAAS,CAAC;gBACzC,cAAc,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;aACpE;SACF,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEhE,IAAI,eAAe,GAAkB,IAAI,CAAC;QAE1C,MAAM,UAAU,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YAC5C,6BAA6B;YAC7B,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,eAAe,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAE9B,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAEtC,8CAA8C;YAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACzB,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;YAEhD,+DAA+D;YAC/D,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,KAAK,GAAG,IAAI,WAAW,EAAE,CAAC;QAEhC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,GAAG,CAAC,GAAG,CACL,uBAAuB,CAAC;YACtB,KAAK;YACL,MAAM,EAAE,WAAW;SACpB,CAAC,CACH,CAAC;QACF,GAAG,CAAC,GAAG,CACL,GAAG,EACH,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;YAC9B,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACzD,GAAG,CAAC,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,CAAC,CAAC,CACH,CAAC;QAEF,MAAM,UAAU,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;YACtC,MAAM,gBAAgB,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;YAE5C,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;YACxC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { assert } from 'chai';\nimport express from 'express';\nimport asyncHandler from 'express-async-handler';\nimport fetchCookie from 'fetch-cookie';\nimport fetch from 'node-fetch';\nimport setCookie from 'set-cookie-parser';\n\nimport { withServer } from '@prairielearn/express-test-utils';\n\nimport { MemoryStore } from './memory-store.js';\n\nimport { createSessionMiddleware } from './index.js';\n\nconst TEST_SECRET = 'test-secret';\n\nfunction parseSetCookie(header: string) {\n return setCookie.parse(setCookie.splitCookiesString(header));\n}\n\ndescribe('session middleware', () => {\n it('sets a session cookie', async () => {\n const app = express();\n app.use(createSessionMiddleware({ secret: TEST_SECRET, store: new MemoryStore() }));\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url);\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n });\n });\n\n it('sets a session cookie with options', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n name: 'prairielearn_session',\n httpOnly: true,\n domain: '.localhost',\n sameSite: 'strict',\n maxAge: 1000,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url);\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'prairielearn_session');\n assert.equal(cookies[0].path, '/');\n assert.isTrue(cookies[0].httpOnly);\n assert.equal(cookies[0].domain, '.localhost');\n assert.equal(cookies[0].sameSite, 'Strict');\n });\n });\n\n it('sets a secure cookie for proxied HTTPS request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: true,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'https',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.isTrue(cookies[0].secure);\n });\n });\n\n it('does not set a secure cookie for proxied HTTP request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: true,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'http',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n assert.isNull(header);\n });\n });\n\n it('automatically sets secure for proxied HTTPS request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: 'auto',\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'https',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.isTrue(cookies[0].secure);\n });\n });\n\n it('automatically sets secure for proxied HTTP request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: 'auto',\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'http',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.isUndefined(cookies[0].secure);\n });\n });\n\n it('sets secure cookie based on a function', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: (req) => req.hostname === 'example.com',\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const insecureRes = await fetch(url, {\n headers: {\n 'X-Forwarded-Host': 'subdomain.example.com',\n 'X-Forwarded-Proto': 'http',\n },\n });\n assert.equal(insecureRes.status, 200);\n\n const insecureHeader = insecureRes.headers.get('set-cookie');\n const insecureCookie = parseSetCookie(insecureHeader ?? '');\n assert.equal(insecureCookie.length, 1);\n assert.equal(insecureCookie[0].name, 'session');\n assert.equal(insecureCookie[0].path, '/');\n assert.isUndefined(insecureCookie[0].secure);\n\n const secureRes = await fetch(url, {\n headers: {\n 'X-Forwarded-Host': 'example.com',\n 'X-Forwarded-Proto': 'https',\n },\n });\n assert.equal(secureRes.status, 200);\n\n const secureHeader = secureRes.headers.get('set-cookie');\n const secureCookies = parseSetCookie(secureHeader ?? '');\n assert.equal(secureCookies.length, 1);\n assert.equal(secureCookies[0].name, 'session');\n assert.equal(secureCookies[0].path, '/');\n assert.isTrue(secureCookies[0].secure);\n });\n });\n\n it('persists session data across requests', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n store: new MemoryStore(),\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (req, res) => {\n req.session.count ??= 0;\n req.session.count += 1;\n res.send(req.session.count.toString());\n });\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), '1');\n\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), '2');\n });\n });\n\n it('commits the session before sending a redirect', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n store: new MemoryStore(),\n secret: TEST_SECRET,\n }),\n );\n app.post('/', (req, res) => {\n req.session.test = 'test';\n res.redirect(req.originalUrl);\n });\n app.get('/', (req, res) => {\n res.send(req.session.test ?? 'NO VALUE');\n });\n\n await withServer(app, async ({ url }) => {\n const res = await fetchCookie(fetch)(url, {\n method: 'POST',\n });\n assert.equal(res.status, 200);\n\n const body = await res.text();\n assert.equal(body, 'test');\n });\n });\n\n it('destroys session', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n app.use(\n '/destroy',\n asyncHandler(async (req, res) => {\n await req.session.destroy();\n res.sendStatus(200);\n }),\n );\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n await fetchWithCookies(url);\n\n // Destroy the session.\n const destroyRes = await fetchWithCookies(`${url}/destroy`);\n assert.equal(destroyRes.status, 200);\n\n // Ensure the session cookie was cleared in the response.\n const header = destroyRes.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.equal(cookies[0].expires?.getTime(), 0);\n\n // Ensure the session was destroyed in the session store.\n const sessionId = cookies[0].value.split('.')[0];\n assert.isNull(await store.get(sessionId));\n });\n });\n\n it('regenerates session', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (req, res) => {\n res.send(req.session.regenerated ? 'true' : 'false');\n });\n app.get(\n '/regenerate',\n asyncHandler(async (req, res) => {\n await req.session.regenerate();\n req.session.regenerated = true;\n res.sendStatus(200);\n }),\n );\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), 'false');\n\n // Extract the original cookie value.\n let header = res.headers.get('set-cookie');\n let cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n const originalCookieValue = cookies[0].value;\n\n // Regenerate the session.\n res = await fetchWithCookies(`${url}/regenerate`);\n assert.equal(res.status, 200);\n\n // Ensure that the session cookie was changed.\n header = res.headers.get('set-cookie');\n cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n const newCookieValue = cookies[0].value;\n assert.notEqual(newCookieValue, originalCookieValue);\n\n // Ensure the original session is no longer present in the session store.\n const originalSessionId = originalCookieValue.split('.')[0];\n assert.isNull(await store.get(originalSessionId));\n\n // Ensure that the regenerated session data was persisted.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), 'true');\n });\n });\n\n it('creates a new session if signature checks fail', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (req, res) => res.send(req.session.id));\n\n await withServer(app, async ({ url }) => {\n const cookieJar = new fetchCookie.toughCookie.CookieJar();\n const fetchWithCookies = fetchCookie(fetch, cookieJar);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n const originalSessionId = await res.text();\n\n // Tamper with the session cookie.\n const cookie = cookieJar.getCookiesSync(url)[0];\n cookie.value = 'tampered';\n cookieJar.setCookieSync(cookie, url);\n\n // Make sure we get a new session.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n const newSessionId = await res.text();\n assert.notEqual(newSessionId, originalSessionId);\n\n // Make sure the existing session is still present in the store. We don't\n // want someone to be able to evict other sessions by submitting invalid\n // cookies.\n assert.isNotNull(await store.get(originalSessionId));\n });\n });\n\n it('does not re-set the cookie on subsequent requests', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n store: new MemoryStore(),\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Make another request with the same session.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Ensure that the cookie wasn't set again.\n const header = res.headers.get('set-cookie');\n assert.isNull(header);\n });\n });\n\n it('extends the expiration date of the cookie', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n cookie: {\n maxAge: 1000,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n app.get('/extend', (req, res) => {\n req.session.setExpiration(Date.now() + 10000);\n res.sendStatus(200);\n });\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Grab the original expiration date.\n let header = res.headers.get('set-cookie');\n let cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.isUndefined(cookies[0].maxAge);\n const originalExpirationDate = cookies[0].expires;\n assert(originalExpirationDate);\n\n // Also grab the expiration date from the store.\n const sessionId = cookies[0].value.split('.')[0];\n const session = await store.get(sessionId);\n assert(session);\n const originalStoreExpirationDate = session.expiresAt;\n\n // Ensure that the expiration dates are consistent.\n assert.equal(originalExpirationDate.getTime(), originalStoreExpirationDate.getTime());\n\n // Make another request with the same session.\n res = await fetchWithCookies(`${url}/extend`);\n assert.equal(res.status, 200);\n\n // Ensure that the cookie was set again.\n header = res.headers.get('set-cookie');\n cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.isUndefined(cookies[0].maxAge);\n const newExpirationDate = cookies[0].expires;\n assert(newExpirationDate);\n\n // Ensure that the expiration date was extended.\n assert.notEqual(newExpirationDate.getTime(), originalExpirationDate.getTime());\n\n // Also grab the new expiration date from the store.\n const newSession = await store.get(sessionId);\n assert(newSession);\n const newStoreExpirationDate = newSession.expiresAt;\n\n // Ensure that the expiration dates are consistent.\n assert.equal(newExpirationDate.getTime(), newStoreExpirationDate.getTime());\n });\n });\n\n it('does not persist session data if the session did not change', async () => {\n const store = new MemoryStore();\n\n let setCount = 0;\n const originalStoreSet = store.set.bind(store);\n store.set = async (...args) => {\n setCount += 1;\n await originalStoreSet(...args);\n };\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Ensure the session was persisted.\n assert.equal(setCount, 1);\n\n // Make another request with the same session.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Ensure the session was not persisted.\n assert.equal(setCount, 1);\n });\n });\n\n it('rotates to a new cookie when needed', async () => {\n const fetchWithCookies = fetchCookie(fetch);\n const store = new MemoryStore();\n\n // Will create \"legacy\" sessions.\n const legacyApp = express();\n legacyApp.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n cookie: {\n name: 'legacy_session',\n },\n }),\n );\n legacyApp.get('/', (req, res) => res.send(req.session.id.toString()));\n\n // Will create \"new\" sessions and upgrade \"legacy\" sessions.\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n cookie: {\n name: 'legacy_session',\n writeNames: ['legacy_session', 'session'],\n writeOverrides: [{ domain: undefined }, { domain: '.example.com' }],\n },\n }),\n );\n app.get('/', (req, res) => res.send(req.session.id.toString()));\n\n let legacySessionId: string | null = null;\n\n await withServer(legacyApp, async ({ url }) => {\n // Generate a legacy session.\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n legacySessionId = await res.text();\n });\n\n await withServer(app, async ({ url }) => {\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n const newSessionId = await res.text();\n\n // Ensure that the new session cookie was set.\n const header = res.headers.get('set-cookie');\n assert.isNotNull(header);\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 2);\n assert.equal(cookies[0].name, 'legacy_session');\n assert.isUndefined(cookies[0].domain);\n assert.equal(cookies[1].name, 'session');\n assert.equal(cookies[1].domain, '.example.com');\n\n // Ensure that the legacy session is migrated to a new session.\n assert.equal(newSessionId, legacySessionId);\n });\n });\n\n it('persists the session immediately after creation', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get(\n '/',\n asyncHandler(async (req, res) => {\n const persistedSession = await store.get(req.session.id);\n res.status(persistedSession == null ? 500 : 200).send();\n }),\n );\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n });\n });\n});\n"]}
1
+ {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert } from 'chai';\nimport express from 'express';\nimport asyncHandler from 'express-async-handler';\nimport fetchCookie from 'fetch-cookie';\nimport fetch from 'node-fetch';\nimport setCookie from 'set-cookie-parser';\n\nimport { withServer } from '@prairielearn/express-test-utils';\n\nimport { MemoryStore } from './memory-store.js';\n\nimport { createSessionMiddleware } from './index.js';\n\nconst TEST_SECRET = 'test-secret';\n\nfunction parseSetCookie(header: string) {\n return setCookie.parse(setCookie.splitCookiesString(header));\n}\n\ndescribe('session middleware', () => {\n it('sets a session cookie', async () => {\n const app = express();\n app.use(createSessionMiddleware({ secret: TEST_SECRET, store: new MemoryStore() }));\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url);\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n });\n });\n\n it('sets a session cookie with options', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n name: 'prairielearn_session',\n httpOnly: true,\n domain: '.localhost',\n sameSite: 'strict',\n maxAge: 1000,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url);\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'prairielearn_session');\n assert.equal(cookies[0].path, '/');\n assert.isTrue(cookies[0].httpOnly);\n assert.equal(cookies[0].domain, '.localhost');\n assert.equal(cookies[0].sameSite, 'Strict');\n });\n });\n\n it('sets a secure cookie for proxied HTTPS request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: true,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'https',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.isTrue(cookies[0].secure);\n });\n });\n\n it('does not set a secure cookie for proxied HTTP request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: true,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'http',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n assert.isNull(header);\n });\n });\n\n it('automatically sets secure for proxied HTTPS request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: 'auto',\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'https',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.isTrue(cookies[0].secure);\n });\n });\n\n it('automatically sets secure for proxied HTTP request', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: 'auto',\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const res = await fetch(url, {\n headers: {\n 'X-Forwarded-Proto': 'http',\n },\n });\n assert.equal(res.status, 200);\n\n const header = res.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.isUndefined(cookies[0].secure);\n });\n });\n\n it('sets secure cookie based on a function', async () => {\n const app = express();\n app.enable('trust proxy');\n app.use(\n createSessionMiddleware({\n secret: TEST_SECRET,\n store: new MemoryStore(),\n cookie: {\n secure: (req) => req.hostname === 'example.com',\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const insecureRes = await fetch(url, {\n headers: {\n 'X-Forwarded-Host': 'subdomain.example.com',\n 'X-Forwarded-Proto': 'http',\n },\n });\n assert.equal(insecureRes.status, 200);\n\n const insecureHeader = insecureRes.headers.get('set-cookie');\n const insecureCookie = parseSetCookie(insecureHeader ?? '');\n assert.equal(insecureCookie.length, 1);\n assert.equal(insecureCookie[0].name, 'session');\n assert.equal(insecureCookie[0].path, '/');\n assert.isUndefined(insecureCookie[0].secure);\n\n const secureRes = await fetch(url, {\n headers: {\n 'X-Forwarded-Host': 'example.com',\n 'X-Forwarded-Proto': 'https',\n },\n });\n assert.equal(secureRes.status, 200);\n\n const secureHeader = secureRes.headers.get('set-cookie');\n const secureCookies = parseSetCookie(secureHeader ?? '');\n assert.equal(secureCookies.length, 1);\n assert.equal(secureCookies[0].name, 'session');\n assert.equal(secureCookies[0].path, '/');\n assert.isTrue(secureCookies[0].secure);\n });\n });\n\n it('persists session data across requests', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n store: new MemoryStore(),\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (req, res) => {\n req.session.count ??= 0;\n req.session.count += 1;\n res.send(req.session.count.toString());\n });\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), '1');\n\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), '2');\n });\n });\n\n it('commits the session before sending a redirect', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n store: new MemoryStore(),\n secret: TEST_SECRET,\n }),\n );\n app.post('/', (req, res) => {\n req.session.test = 'test';\n res.redirect(req.originalUrl);\n });\n app.get('/', (req, res) => {\n res.send(req.session.test ?? 'NO VALUE');\n });\n\n await withServer(app, async ({ url }) => {\n const res = await fetchCookie(fetch)(url, {\n method: 'POST',\n });\n assert.equal(res.status, 200);\n\n const body = await res.text();\n assert.equal(body, 'test');\n });\n });\n\n it('destroys session', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n app.use(\n '/destroy',\n asyncHandler(async (req, res) => {\n await req.session.destroy();\n res.sendStatus(200);\n }),\n );\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n await res.text();\n\n // Destroy the session.\n const destroyRes = await fetchWithCookies(`${url}/destroy`);\n assert.equal(destroyRes.status, 200);\n await destroyRes.text();\n\n // Ensure the session cookie was cleared in the response.\n const header = destroyRes.headers.get('set-cookie');\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.equal(cookies[0].name, 'session');\n assert.equal(cookies[0].path, '/');\n assert.equal(cookies[0].expires?.getTime(), 0);\n\n // Ensure the session was destroyed in the session store.\n const sessionId = cookies[0].value.split('.')[0];\n assert.isNull(await store.get(sessionId));\n });\n });\n\n it('regenerates session', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (req, res) => {\n res.send(req.session.regenerated ? 'true' : 'false');\n });\n app.get(\n '/regenerate',\n asyncHandler(async (req, res) => {\n await req.session.regenerate();\n req.session.regenerated = true;\n res.send('true');\n }),\n );\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), 'false');\n\n // Extract the original cookie value.\n let header = res.headers.get('set-cookie');\n let cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n const originalCookieValue = cookies[0].value;\n\n // Regenerate the session.\n res = await fetchWithCookies(`${url}/regenerate`);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), 'true');\n\n // Ensure that the session cookie was changed.\n header = res.headers.get('set-cookie');\n cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n const newCookieValue = cookies[0].value;\n assert.notEqual(newCookieValue, originalCookieValue);\n\n // Ensure the original session is no longer present in the session store.\n const originalSessionId = originalCookieValue.split('.')[0];\n assert.isNull(await store.get(originalSessionId));\n\n // Ensure that the regenerated session data was persisted.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n assert.equal(await res.text(), 'true');\n });\n });\n\n it('creates a new session if signature checks fail', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (req, res) => res.send(req.session.id));\n\n await withServer(app, async ({ url }) => {\n const cookieJar = new fetchCookie.toughCookie.CookieJar();\n const fetchWithCookies = fetchCookie(fetch, cookieJar);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n const originalSessionId = await res.text();\n\n // Tamper with the session cookie.\n const cookie = cookieJar.getCookiesSync(url)[0];\n cookie.value = 'tampered';\n cookieJar.setCookieSync(cookie, url);\n\n // Make sure we get a new session.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n const newSessionId = await res.text();\n assert.notEqual(newSessionId, originalSessionId);\n\n // Make sure the existing session is still present in the store. We don't\n // want someone to be able to evict other sessions by submitting invalid\n // cookies.\n assert.isNotNull(await store.get(originalSessionId));\n });\n });\n\n it('does not re-set the cookie on subsequent requests', async () => {\n const app = express();\n app.use(\n createSessionMiddleware({\n store: new MemoryStore(),\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Make another request with the same session.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n // Ensure that the cookie wasn't set again.\n const header = res.headers.get('set-cookie');\n assert.isNull(header);\n });\n });\n\n it('extends the expiration date of the cookie', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n cookie: {\n maxAge: 1000,\n },\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n app.get('/extend', (req, res) => {\n req.session.setExpiration(10000);\n res.sendStatus(200);\n });\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n await res.text();\n\n // Grab the original expiration date.\n let header = res.headers.get('set-cookie');\n let cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.isUndefined(cookies[0].maxAge);\n const originalExpirationDate = cookies[0].expires;\n assert(originalExpirationDate);\n\n // Grab the session ID from the cookie.\n const sessionId = cookies[0].value.split('.')[0];\n\n // Ensure that the expiration dates are consistent between the cookie and the store.\n const session = await store.get(sessionId);\n assert.equal(originalExpirationDate.getTime(), session?.expiresAt.getTime());\n\n // Make another request with the same session.\n res = await fetchWithCookies(`${url}/extend`);\n assert.equal(res.status, 200);\n await res.text();\n\n // Ensure that the cookie was set again.\n header = res.headers.get('set-cookie');\n cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 1);\n assert.isUndefined(cookies[0].maxAge);\n const newExpirationDate = cookies[0].expires;\n assert(newExpirationDate);\n\n // Ensure that the expiration date was extended.\n assert.notEqual(newExpirationDate.getTime(), originalExpirationDate.getTime());\n\n // Ensure that the expiration dates are consistent between the cookie and the store.\n const newSession = await store.get(sessionId);\n assert.equal(newExpirationDate.getTime(), newSession?.expiresAt.getTime());\n });\n });\n\n it('does not persist session data if the session did not change', async () => {\n const store = new MemoryStore();\n\n let setCount = 0;\n const originalStoreSet = store.set.bind(store);\n store.set = async (...args) => {\n setCount += 1;\n await originalStoreSet(...args);\n };\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get('/', (_req, res) => res.sendStatus(200));\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n // Generate a new session.\n let res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n await res.text();\n\n // Ensure the session was persisted.\n assert.equal(setCount, 1);\n\n // Make another request with the same session.\n res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n await res.text();\n\n // Ensure the session was not persisted.\n assert.equal(setCount, 1);\n });\n });\n\n it('rotates to a new cookie when needed', async () => {\n const fetchWithCookies = fetchCookie(fetch);\n const store = new MemoryStore();\n\n // Will create \"legacy\" sessions.\n const legacyApp = express();\n legacyApp.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n cookie: {\n name: 'legacy_session',\n },\n }),\n );\n legacyApp.get('/', (req, res) => res.send(req.session.id.toString()));\n\n // Will create \"new\" sessions and upgrade \"legacy\" sessions.\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n cookie: {\n name: 'legacy_session',\n writeNames: ['legacy_session', 'session'],\n writeOverrides: [{ domain: undefined }, { domain: '.example.com' }],\n },\n }),\n );\n app.get('/', (req, res) => res.send(req.session.id.toString()));\n\n let legacySessionId: string | null = null;\n\n await withServer(legacyApp, async ({ url }) => {\n // Generate a legacy session.\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n legacySessionId = await res.text();\n });\n\n await withServer(app, async ({ url }) => {\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n\n const newSessionId = await res.text();\n\n // Ensure that the new session cookie was set.\n const header = res.headers.get('set-cookie');\n assert.isNotNull(header);\n const cookies = parseSetCookie(header ?? '');\n assert.equal(cookies.length, 2);\n assert.equal(cookies[0].name, 'legacy_session');\n assert.isUndefined(cookies[0].domain);\n assert.equal(cookies[1].name, 'session');\n assert.equal(cookies[1].domain, '.example.com');\n\n // Ensure that the legacy session is migrated to a new session.\n assert.equal(newSessionId, legacySessionId);\n });\n });\n\n it('persists the session immediately after creation', async () => {\n const store = new MemoryStore();\n\n const app = express();\n app.use(\n createSessionMiddleware({\n store,\n secret: TEST_SECRET,\n }),\n );\n app.get(\n '/',\n asyncHandler(async (req, res) => {\n const persistedSession = await store.get(req.session.id);\n res.status(persistedSession == null ? 500 : 200).send();\n }),\n );\n\n await withServer(app, async ({ url }) => {\n const fetchWithCookies = fetchCookie(fetch);\n\n const res = await fetchWithCookies(url);\n assert.equal(res.status, 200);\n });\n });\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prairielearn/session",
3
- "version": "3.0.4",
3
+ "version": "3.0.6",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "repository": {
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@types/express": "^4.17.21",
18
- "cookie": "^0.6.0",
18
+ "cookie": "^0.7.1",
19
19
  "cookie-signature": "^1.2.1",
20
20
  "express-async-handler": "^1.2.0",
21
21
  "on-headers": "^1.0.2",
@@ -24,10 +24,10 @@
24
24
  "devDependencies": {
25
25
  "@prairielearn/express-test-utils": "^2.0.0",
26
26
  "@prairielearn/tsconfig": "^0.0.0",
27
- "@types/chai": "^4.3.17",
27
+ "@types/chai": "^4.3.19",
28
28
  "@types/cookie": "^0.6.0",
29
29
  "@types/cookie-signature": "^1.1.2",
30
- "@types/node": "^20.14.13",
30
+ "@types/node": "^20.16.2",
31
31
  "@types/node-fetch": "^2.6.11",
32
32
  "@types/on-headers": "^1.0.3",
33
33
  "@types/set-cookie-parser": "^2.4.10",
@@ -36,11 +36,11 @@
36
36
  "chai": "^5.1.1",
37
37
  "express": "^4.19.2",
38
38
  "fetch-cookie": "^3.0.1",
39
- "mocha": "^10.7.0",
39
+ "mocha": "^10.7.3",
40
40
  "node-fetch": "^3.3.2",
41
- "set-cookie-parser": "^2.6.0",
41
+ "set-cookie-parser": "^2.7.0",
42
42
  "source-map-support": "^0.5.21",
43
- "tsx": "^4.16.5",
43
+ "tsx": "^4.19.0",
44
44
  "typescript": "^5.5.4"
45
45
  },
46
46
  "c8": {
package/src/index.test.ts CHANGED
@@ -311,11 +311,14 @@ describe('session middleware', () => {
311
311
  const fetchWithCookies = fetchCookie(fetch);
312
312
 
313
313
  // Generate a new session.
314
- await fetchWithCookies(url);
314
+ const res = await fetchWithCookies(url);
315
+ assert.equal(res.status, 200);
316
+ await res.text();
315
317
 
316
318
  // Destroy the session.
317
319
  const destroyRes = await fetchWithCookies(`${url}/destroy`);
318
320
  assert.equal(destroyRes.status, 200);
321
+ await destroyRes.text();
319
322
 
320
323
  // Ensure the session cookie was cleared in the response.
321
324
  const header = destroyRes.headers.get('set-cookie');
@@ -349,7 +352,7 @@ describe('session middleware', () => {
349
352
  asyncHandler(async (req, res) => {
350
353
  await req.session.regenerate();
351
354
  req.session.regenerated = true;
352
- res.sendStatus(200);
355
+ res.send('true');
353
356
  }),
354
357
  );
355
358
 
@@ -370,6 +373,7 @@ describe('session middleware', () => {
370
373
  // Regenerate the session.
371
374
  res = await fetchWithCookies(`${url}/regenerate`);
372
375
  assert.equal(res.status, 200);
376
+ assert.equal(await res.text(), 'true');
373
377
 
374
378
  // Ensure that the session cookie was changed.
375
379
  header = res.headers.get('set-cookie');
@@ -470,7 +474,7 @@ describe('session middleware', () => {
470
474
  );
471
475
  app.get('/', (_req, res) => res.sendStatus(200));
472
476
  app.get('/extend', (req, res) => {
473
- req.session.setExpiration(Date.now() + 10000);
477
+ req.session.setExpiration(10000);
474
478
  res.sendStatus(200);
475
479
  });
476
480
 
@@ -480,6 +484,7 @@ describe('session middleware', () => {
480
484
  // Generate a new session.
481
485
  let res = await fetchWithCookies(url);
482
486
  assert.equal(res.status, 200);
487
+ await res.text();
483
488
 
484
489
  // Grab the original expiration date.
485
490
  let header = res.headers.get('set-cookie');
@@ -489,18 +494,17 @@ describe('session middleware', () => {
489
494
  const originalExpirationDate = cookies[0].expires;
490
495
  assert(originalExpirationDate);
491
496
 
492
- // Also grab the expiration date from the store.
497
+ // Grab the session ID from the cookie.
493
498
  const sessionId = cookies[0].value.split('.')[0];
494
- const session = await store.get(sessionId);
495
- assert(session);
496
- const originalStoreExpirationDate = session.expiresAt;
497
499
 
498
- // Ensure that the expiration dates are consistent.
499
- assert.equal(originalExpirationDate.getTime(), originalStoreExpirationDate.getTime());
500
+ // Ensure that the expiration dates are consistent between the cookie and the store.
501
+ const session = await store.get(sessionId);
502
+ assert.equal(originalExpirationDate.getTime(), session?.expiresAt.getTime());
500
503
 
501
504
  // Make another request with the same session.
502
505
  res = await fetchWithCookies(`${url}/extend`);
503
506
  assert.equal(res.status, 200);
507
+ await res.text();
504
508
 
505
509
  // Ensure that the cookie was set again.
506
510
  header = res.headers.get('set-cookie');
@@ -513,13 +517,9 @@ describe('session middleware', () => {
513
517
  // Ensure that the expiration date was extended.
514
518
  assert.notEqual(newExpirationDate.getTime(), originalExpirationDate.getTime());
515
519
 
516
- // Also grab the new expiration date from the store.
520
+ // Ensure that the expiration dates are consistent between the cookie and the store.
517
521
  const newSession = await store.get(sessionId);
518
- assert(newSession);
519
- const newStoreExpirationDate = newSession.expiresAt;
520
-
521
- // Ensure that the expiration dates are consistent.
522
- assert.equal(newExpirationDate.getTime(), newStoreExpirationDate.getTime());
522
+ assert.equal(newExpirationDate.getTime(), newSession?.expiresAt.getTime());
523
523
  });
524
524
  });
525
525
 
@@ -547,6 +547,7 @@ describe('session middleware', () => {
547
547
  // Generate a new session.
548
548
  let res = await fetchWithCookies(url);
549
549
  assert.equal(res.status, 200);
550
+ await res.text();
550
551
 
551
552
  // Ensure the session was persisted.
552
553
  assert.equal(setCount, 1);
@@ -554,6 +555,7 @@ describe('session middleware', () => {
554
555
  // Make another request with the same session.
555
556
  res = await fetchWithCookies(url);
556
557
  assert.equal(res.status, 200);
558
+ await res.text();
557
559
 
558
560
  // Ensure the session was not persisted.
559
561
  assert.equal(setCount, 1);