lambder 7.3.1 → 8.1.1

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.
Files changed (237) hide show
  1. package/CHANGELOG.md +1047 -3
  2. package/README.md +46 -21
  3. package/dist/api/LambderApiAnswer.d.ts +18 -22
  4. package/dist/api/LambderApiAnswer.js +6 -7
  5. package/dist/api/LambderApiCallContext.d.ts +21 -8
  6. package/dist/api/LambderApiCallContext.js +22 -4
  7. package/dist/api/LambderApiDefinition.d.ts +4 -3
  8. package/dist/api/LambderApiEnvelope.d.ts +14 -9
  9. package/dist/api/LambderApiEnvelope.js +33 -34
  10. package/dist/api/LambderApiGuards.d.ts +78 -51
  11. package/dist/api/LambderApiGuards.js +34 -36
  12. package/dist/api/LambderApiIdempotency.d.ts +68 -62
  13. package/dist/api/LambderApiIdempotency.js +214 -151
  14. package/dist/api/LambderApiOutputValidationError.d.ts +32 -0
  15. package/dist/api/LambderApiOutputValidationError.js +50 -0
  16. package/dist/api/LambderApiPipeline.d.ts +47 -38
  17. package/dist/api/LambderApiPipeline.js +122 -63
  18. package/dist/api/LambderApiRateLimits.d.ts +201 -54
  19. package/dist/api/LambderApiRateLimits.js +185 -108
  20. package/dist/api/LambderApiRequest.d.ts +27 -21
  21. package/dist/api/LambderApiRequest.js +26 -19
  22. package/dist/api/LambderApiSignature.d.ts +12 -15
  23. package/dist/api/LambderApiSignature.js +28 -51
  24. package/dist/api/LambderApiValidationRefusal.d.ts +9 -9
  25. package/dist/api/LambderApiValidationRefusal.js +10 -10
  26. package/dist/build/ContractTypePrinter.d.ts +85 -0
  27. package/dist/build/ContractTypePrinter.js +402 -0
  28. package/dist/build/freshProcessVerifier.d.ts +13 -0
  29. package/dist/build/freshProcessVerifier.js +19 -0
  30. package/dist/build/moduleLocation.d.ts +11 -0
  31. package/dist/build/moduleLocation.js +6 -0
  32. package/dist/build/writeApiContract.d.ts +78 -0
  33. package/dist/build/writeApiContract.js +302 -0
  34. package/dist/build/writeApiSignatures.d.ts +114 -0
  35. package/dist/build/writeApiSignatures.js +217 -0
  36. package/dist/build/writeFileAtomically.d.ts +8 -0
  37. package/dist/build/writeFileAtomically.js +22 -0
  38. package/dist/build.d.ts +14 -0
  39. package/dist/build.js +11 -0
  40. package/dist/client/LambderCaller.d.ts +13 -44
  41. package/dist/client/LambderCaller.js +77 -84
  42. package/dist/client/LambderReloadLoopBreaker.d.ts +56 -26
  43. package/dist/client/LambderReloadLoopBreaker.js +90 -46
  44. package/dist/client/LambderUploadRunner.d.ts +96 -0
  45. package/dist/client/LambderUploadRunner.js +234 -0
  46. package/dist/client/lambderFetchTransport.d.ts +4 -1
  47. package/dist/client/lambderFetchTransport.js +52 -28
  48. package/dist/client.d.ts +9 -3
  49. package/dist/client.js +6 -1
  50. package/dist/core/Lambder.d.ts +143 -79
  51. package/dist/core/Lambder.js +350 -231
  52. package/dist/core/LambderContext.d.ts +82 -15
  53. package/dist/core/LambderContext.js +107 -20
  54. package/dist/core/LambderCors.d.ts +21 -3
  55. package/dist/core/LambderCors.js +35 -16
  56. package/dist/core/LambderCrashHandling.d.ts +40 -0
  57. package/dist/core/LambderCrashHandling.js +97 -0
  58. package/dist/core/LambderCreateOptions.d.ts +151 -75
  59. package/dist/core/LambderCreateOptions.js +16 -23
  60. package/dist/core/LambderFiles.d.ts +21 -7
  61. package/dist/core/LambderFiles.js +62 -34
  62. package/dist/core/LambderIndexHtml.js +12 -11
  63. package/dist/core/LambderPolicyBuilders.d.ts +17 -5
  64. package/dist/core/LambderPolicyBuilders.js +17 -5
  65. package/dist/core/LambderPublicFiles.d.ts +11 -5
  66. package/dist/core/LambderPublicFiles.js +32 -4
  67. package/dist/core/LambderRequestPath.d.ts +43 -0
  68. package/dist/core/LambderRequestPath.js +63 -0
  69. package/dist/core/LambderResponse.d.ts +26 -5
  70. package/dist/core/LambderResponse.js +157 -70
  71. package/dist/core/LambderResponseBuilder.d.ts +49 -4
  72. package/dist/core/LambderResponseBuilder.js +64 -3
  73. package/dist/core/LambderRouting.d.ts +2 -3
  74. package/dist/core/LambderRouting.js +22 -7
  75. package/dist/core/LambderTemplatingEngine.js +211 -32
  76. package/dist/index.d.ts +25 -8
  77. package/dist/index.js +13 -4
  78. package/dist/invoke/LambderInvokeCaller.d.ts +37 -42
  79. package/dist/invoke/LambderInvokeCaller.js +76 -66
  80. package/dist/invoke/LambderInvokeOutcome.d.ts +27 -26
  81. package/dist/invoke/LambderInvokeOutcome.js +9 -22
  82. package/dist/invoke/LambderLambdaEvent.d.ts +29 -9
  83. package/dist/invoke/LambderLambdaEvent.js +40 -22
  84. package/dist/invoke/lambderHandlerTransport.d.ts +9 -10
  85. package/dist/invoke/lambderHandlerTransport.js +15 -18
  86. package/dist/mock/LambderMockApp.d.ts +67 -83
  87. package/dist/mock/LambderMockApp.js +167 -153
  88. package/dist/mock/LambderMockBrowserCookies.d.ts +24 -28
  89. package/dist/mock/LambderMockBrowserCookies.js +24 -28
  90. package/dist/mock/LambderMockCallRecorder.d.ts +15 -22
  91. package/dist/mock/LambderMockCallRecorder.js +19 -28
  92. package/dist/mock/LambderMockCreateOptions.d.ts +42 -24
  93. package/dist/mock/LambderMockEntryRegistry.d.ts +11 -12
  94. package/dist/mock/LambderMockEntryRegistry.js +24 -29
  95. package/dist/mock/LambderMockFailureInjector.d.ts +3 -6
  96. package/dist/mock/LambderMockFailureInjector.js +3 -6
  97. package/dist/mock/LambderMockTypes.d.ts +78 -108
  98. package/dist/mock/lambderMockInvokeTransport.d.ts +11 -13
  99. package/dist/mock/lambderMockInvokeTransport.js +11 -10
  100. package/dist/mock/lambderMockMswHandler.d.ts +43 -33
  101. package/dist/mock/lambderMockMswHandler.js +50 -39
  102. package/dist/mock/lambderMockUploadMswHandler.d.ts +26 -0
  103. package/dist/mock/lambderMockUploadMswHandler.js +28 -0
  104. package/dist/mock.d.ts +4 -1
  105. package/dist/mock.js +6 -3
  106. package/dist/session/LambderSessionController.d.ts +108 -89
  107. package/dist/session/LambderSessionController.js +187 -168
  108. package/dist/session/LambderSessionCrypto.d.ts +16 -7
  109. package/dist/session/LambderSessionCrypto.js +26 -12
  110. package/dist/session/LambderSessionManager.d.ts +124 -46
  111. package/dist/session/LambderSessionManager.js +262 -137
  112. package/dist/shared/LambderHtml.d.ts +42 -3
  113. package/dist/shared/LambderHtml.js +127 -7
  114. package/dist/shared/LambderHtmlPositions.d.ts +173 -0
  115. package/dist/shared/LambderHtmlPositions.js +652 -0
  116. package/dist/shared/LambderI18n.d.ts +10 -11
  117. package/dist/shared/LambderI18n.js +33 -21
  118. package/dist/shared/contracts/LambderCache.d.ts +66 -0
  119. package/dist/shared/contracts/LambderCache.js +11 -0
  120. package/dist/shared/contracts/LambderFileSource.d.ts +6 -6
  121. package/dist/shared/contracts/LambderFileSource.js +5 -8
  122. package/dist/shared/contracts/LambderIdempotencyStore.d.ts +51 -22
  123. package/dist/shared/contracts/LambderIdempotencyStore.js +4 -5
  124. package/dist/shared/contracts/LambderRateLimiter.d.ts +27 -15
  125. package/dist/shared/contracts/LambderRateLimiter.js +4 -5
  126. package/dist/shared/contracts/LambderSessionStore.d.ts +65 -26
  127. package/dist/shared/contracts/LambderSessionStore.js +5 -6
  128. package/dist/shared/contracts/LambderUploadBucket.d.ts +154 -0
  129. package/dist/shared/contracts/LambderUploadBucket.js +74 -0
  130. package/dist/shared/transport/LambderApiTransport.d.ts +27 -27
  131. package/dist/shared/transport/LambderApiTransport.js +7 -7
  132. package/dist/shared/transport/LambderCookieJar.d.ts +28 -35
  133. package/dist/shared/transport/LambderCookieJar.js +54 -66
  134. package/dist/shared/transport/lambderCookieJarTransport.d.ts +11 -13
  135. package/dist/shared/transport/lambderCookieJarTransport.js +24 -23
  136. package/dist/shared/util/LambderCallAbort.d.ts +5 -5
  137. package/dist/shared/util/LambderCallAbort.js +5 -5
  138. package/dist/shared/util/LambderClientIp.d.ts +27 -11
  139. package/dist/shared/util/LambderClientIp.js +96 -13
  140. package/dist/shared/util/LambderContentDisposition.d.ts +10 -0
  141. package/dist/shared/util/LambderContentDisposition.js +13 -0
  142. package/dist/shared/util/LambderExpiringMap.d.ts +35 -49
  143. package/dist/shared/util/LambderExpiringMap.js +41 -57
  144. package/dist/shared/util/LambderNodeModules.js +6 -7
  145. package/dist/shared/util/LambderOptionChecks.d.ts +4 -4
  146. package/dist/shared/util/LambderOptionChecks.js +4 -4
  147. package/dist/shared/util/LambderResponseBrand.d.ts +5 -5
  148. package/dist/shared/util/LambderResponseBrand.js +5 -5
  149. package/dist/shared/util/LambderTextDigest.d.ts +7 -5
  150. package/dist/shared/util/LambderTextDigest.js +11 -5
  151. package/dist/shared/util/LambderTypeUtilities.d.ts +7 -8
  152. package/dist/shared/util/LambderTypeUtilities.js +3 -3
  153. package/dist/shared/util/boundKeyField.d.ts +20 -0
  154. package/dist/shared/util/boundKeyField.js +34 -0
  155. package/dist/shared/util/canonicalJson.d.ts +11 -0
  156. package/dist/shared/util/canonicalJson.js +28 -0
  157. package/dist/shared/util/joinKeyFields.d.ts +20 -0
  158. package/dist/shared/util/joinKeyFields.js +22 -0
  159. package/dist/shared/wire/LambderAnswerHeaders.d.ts +12 -16
  160. package/dist/shared/wire/LambderAnswerHeaders.js +12 -16
  161. package/dist/shared/wire/LambderApiContract.d.ts +98 -53
  162. package/dist/shared/wire/LambderApiOutcome.d.ts +43 -31
  163. package/dist/shared/wire/LambderApiOutcome.js +48 -23
  164. package/dist/shared/wire/LambderApiRefusal.d.ts +45 -27
  165. package/dist/shared/wire/LambderApiRefusal.js +42 -7
  166. package/dist/shared/wire/LambderApiSignature.d.ts +18 -22
  167. package/dist/shared/wire/LambderApiSignature.js +16 -19
  168. package/dist/shared/wire/LambderCallOptions.d.ts +38 -47
  169. package/dist/shared/wire/LambderCallOptions.js +9 -11
  170. package/dist/shared/wire/LambderCompressionCodec.d.ts +29 -34
  171. package/dist/shared/wire/LambderCompressionCodec.js +31 -36
  172. package/dist/shared/wire/LambderCompressionOption.d.ts +9 -9
  173. package/dist/shared/wire/LambderCompressionOption.js +9 -9
  174. package/dist/shared/wire/LambderCrashDetail.d.ts +12 -15
  175. package/dist/shared/wire/LambderCrashDetail.js +12 -15
  176. package/dist/shared/wire/LambderDefaultApiPath.d.ts +6 -0
  177. package/dist/shared/wire/LambderDefaultApiPath.js +6 -0
  178. package/dist/shared/wire/LambderHttpStatus.d.ts +6 -7
  179. package/dist/shared/wire/LambderIdempotencyKeyScope.d.ts +89 -0
  180. package/dist/shared/wire/LambderIdempotencyKeyScope.js +146 -0
  181. package/dist/shared/wire/LambderInvokeApiId.d.ts +27 -0
  182. package/dist/shared/wire/LambderInvokeApiId.js +27 -0
  183. package/dist/shared/wire/LambderOutcomeAssertions.d.ts +6 -7
  184. package/dist/shared/wire/LambderOutcomeAssertions.js +6 -7
  185. package/dist/shared/wire/LambderRequestPayload.d.ts +18 -20
  186. package/dist/shared/wire/LambderRequestPayload.js +4 -6
  187. package/dist/shared/wire/LambderUploadObjectFields.d.ts +10 -0
  188. package/dist/shared/wire/LambderUploadObjectFields.js +24 -0
  189. package/dist/shared/wire/LambderUploadRefusal.d.ts +9 -0
  190. package/dist/shared/wire/LambderUploadRefusal.js +18 -0
  191. package/dist/shared/wire/LambderUploadSchemas.d.ts +12 -0
  192. package/dist/shared/wire/LambderUploadSchemas.js +30 -0
  193. package/dist/stores/LambderCacheFiller.d.ts +48 -0
  194. package/dist/stores/LambderCacheFiller.js +119 -0
  195. package/dist/stores/LambderCacheKeys.d.ts +26 -0
  196. package/dist/stores/LambderCacheKeys.js +54 -0
  197. package/dist/stores/LambderCacheValues.d.ts +45 -0
  198. package/dist/stores/LambderCacheValues.js +74 -0
  199. package/dist/stores/LambderDdbCache.d.ts +121 -56
  200. package/dist/stores/LambderDdbCache.js +528 -225
  201. package/dist/stores/LambderDdbIdempotencyStore.d.ts +33 -22
  202. package/dist/stores/LambderDdbIdempotencyStore.js +75 -50
  203. package/dist/stores/LambderDdbRateLimiter.d.ts +76 -20
  204. package/dist/stores/LambderDdbRateLimiter.js +151 -39
  205. package/dist/stores/LambderDdbSdk.d.ts +43 -31
  206. package/dist/stores/LambderDdbSdk.js +80 -38
  207. package/dist/stores/LambderDdbSessionStore.d.ts +27 -14
  208. package/dist/stores/LambderDdbSessionStore.js +119 -47
  209. package/dist/stores/LambderHttpFileSource.d.ts +15 -6
  210. package/dist/stores/LambderHttpFileSource.js +15 -13
  211. package/dist/stores/LambderMemoryCache.d.ts +49 -0
  212. package/dist/stores/LambderMemoryCache.js +113 -0
  213. package/dist/stores/LambderMemoryIdempotencyStore.d.ts +13 -12
  214. package/dist/stores/LambderMemoryIdempotencyStore.js +31 -30
  215. package/dist/stores/LambderMemoryRateLimiter.d.ts +8 -9
  216. package/dist/stores/LambderMemoryRateLimiter.js +14 -13
  217. package/dist/stores/LambderMemorySessionStore.d.ts +14 -11
  218. package/dist/stores/LambderMemorySessionStore.js +38 -19
  219. package/dist/stores/LambderMemoryUploadBucket.d.ts +99 -0
  220. package/dist/stores/LambderMemoryUploadBucket.js +219 -0
  221. package/dist/stores/LambderS3FileSource.d.ts +21 -6
  222. package/dist/stores/LambderS3FileSource.js +12 -7
  223. package/dist/stores/LambderS3UploadBucket.d.ts +73 -0
  224. package/dist/stores/LambderS3UploadBucket.js +144 -0
  225. package/dist/stores/LambderSdkInstallHint.d.ts +11 -0
  226. package/dist/stores/LambderSdkInstallHint.js +14 -0
  227. package/dist/testing/LambderTestApp.d.ts +23 -25
  228. package/dist/testing/LambderTestApp.js +22 -24
  229. package/dist/testing/LambderTestVisitor.d.ts +10 -12
  230. package/dist/testing/LambderTestVisitor.js +15 -15
  231. package/dist/testing.d.ts +3 -0
  232. package/dist/testing.js +2 -0
  233. package/package.json +26 -3
  234. package/dist/api/LambderApiPolicyEngine.d.ts +0 -47
  235. package/dist/api/LambderApiPolicyEngine.js +0 -85
  236. package/dist/shared/util/LambderKeyFields.d.ts +0 -32
  237. package/dist/shared/util/LambderKeyFields.js +0 -34
@@ -1,5 +1,5 @@
1
1
  import { LambderMockTransportError } from "./LambderMockFailureInjector.js";
2
- import { readApiEnvelope, cookieValuesByName, lowercaseHeaderNames } from "../api/LambderApiRequest.js";
2
+ import { readApiEnvelope, cookieValuesByName, isApiCallContentType, lowercaseHeaderNames } from "../api/LambderApiRequest.js";
3
3
  import { getAnswerHeader } from "../shared/wire/LambderAnswerHeaders.js";
4
4
  import { LambderCookieJar } from "../shared/transport/LambderCookieJar.js";
5
5
  import { normalizeClientIp } from "../shared/util/LambderClientIp.js";
@@ -7,25 +7,31 @@ import { normalizeClientIp } from "../shared/util/LambderClientIp.js";
7
7
  * ONE MSW request handler for the whole API path, over the mock app: the
8
8
  * opt-in that makes mocked calls appear in the browser's network panel as
9
9
  * genuine requests, with real method, status, timing and bodies. The request
10
- * is read the way the server reads it, its headers and Cookie header
11
- * included.
10
+ * is read the way the server reads it, headers included, with the cookies a
11
+ * browser would send.
12
12
  *
13
- * Session cookies are held in a jar here rather than by the browser, because
14
- * the browser will not hold them: a response a service worker synthesizes
15
- * never reaches the cookie store, and MSW's own jar comma-joins the
16
- * Set-Cookie headers before parsing them, which loses every cookie after the
17
- * first. So the answer's cookies go into the jar, the next request carries
18
- * them back, and the ones a page's scripts may see are mirrored into
19
- * document.cookie. The Set-Cookie headers still travel on the response, where
20
- * the network panel shows them.
13
+ * Session cookies are held in a jar here, because the browser will not hold
14
+ * them: a response a service worker synthesizes never reaches the cookie
15
+ * store, and MSW's own jar comma-joins the Set-Cookie headers before parsing
16
+ * them, losing every cookie after the first. So the answer's cookies go into
17
+ * the jar, the next request carries them back, and the ones a page's scripts
18
+ * may see are mirrored into document.cookie. The Set-Cookie headers still
19
+ * travel on the response, where the network panel shows them.
20
+ *
21
+ * A request's cookies are therefore the jar's and document.cookie's, never
22
+ * its Cookie header: MSW fills that from its own store, which captures the
23
+ * HttpOnly session cookie off those Set-Cookie headers and keeps it in
24
+ * localStorage across reloads. Reading it would send a second session after
25
+ * a user switch (every call answering sessionExpired), keep a cleared jar
26
+ * signed in, and put the raw token into request events.
21
27
  *
22
28
  * Lambder never depends on msw: the app installs it and passes the module
23
29
  * in. An injected network failure answers MSW's network error. A POST whose
24
30
  * body is not an API envelope is left to other handlers.
25
31
  *
26
32
  * Generic over the module so the handler keeps msw's own handler type, which
27
- * is what `setupWorker(...)` and `setupServer(...)` take. Returning `unknown`
28
- * made the documented wiring an error at the consumer.
33
+ * is what `setupWorker(...)` and `setupServer(...)` take; typed `unknown`,
34
+ * the documented wiring would be a type error at the consumer.
29
35
  */
30
36
  export const lambderMockMswHandler = (mockApp, options) => {
31
37
  const { msw, apiPath } = options;
@@ -38,13 +44,11 @@ export const lambderMockMswHandler = (mockApp, options) => {
38
44
  // cookies name.
39
45
  if (!options.cookieJar)
40
46
  mockApp.adoptCookieJar(jar);
41
- // The runtime's default, not a second one of this adapter's own: an app
42
- // that set defaultClientIp saw its address through the direct transport
43
- // and 127.0.0.1 through the service worker, so a per-IP rate limit counted
44
- // two clients where there was one and the two adapters disagreed about
45
- // what ctx.request.ip is.
46
- // Normalized the way every other adapter's is, so one address is one
47
- // counter under a `per: "ip"` limit however it was spelled.
47
+ // The runtime's default, not one of this adapter's own, so the direct
48
+ // transport and the service worker agree on ctx.request.ip and a per-IP
49
+ // rate limit counts one client as one. Normalized the way every other
50
+ // adapter's is, so one address is one counter under a `per: "ip"` limit
51
+ // however it was spelled.
48
52
  const clientIp = normalizeClientIp(options.clientIp ?? mockApp.defaultClientIp);
49
53
  const handler = msw.http.post(apiPath, async ({ request }) => {
50
54
  let post;
@@ -54,27 +58,34 @@ export const lambderMockMswHandler = (mockApp, options) => {
54
58
  catch {
55
59
  return undefined;
56
60
  }
57
- // Through the one header map every adapter builds, which is built on
58
- // Object.create(null): a header literally named __proto__ was dropped
59
- // here and landed as an own key on the server, and headers["toString"]
60
- // handed a guard an inherited function where every other adapter gives
61
- // undefined.
61
+ // Through the one header map every adapter builds, on
62
+ // Object.create(null): on a plain object, a header literally named
63
+ // __proto__ would be dropped here though the server keeps it as an own
64
+ // key, and headers["toString"] would hand a guard an inherited
65
+ // function where every other adapter gives undefined.
62
66
  const headers = lowercaseHeaderNames(Object.fromEntries(request.headers));
67
+ // A POST of another type is no API call on the server either: it
68
+ // goes on to MSW's other handlers and the network, as a non-envelope
69
+ // body does below, rather than working here and not in production.
70
+ if (!isApiCallContentType(headers))
71
+ return undefined;
72
+ // The cookies travel as `cookies` below, as the direct transport's do.
73
+ delete headers.cookie;
63
74
  const url = new URL(request.url);
64
75
  // Only the cookies whose scope covers this call, as a browser would
65
- // send: reading the whole jar sent one host's session to another as
66
- // soon as a jar was shared across hosts, and read cookies the request
67
- // path was never in scope for. The host is the runtime's own, the path
68
- // the one this call is going to. The jar's copies come first: where a
69
- // name is in both, the jar holds what this runtime last set and the
70
- // document's copy is the mirror of it, so the jar is the one to
71
- // believe.
76
+ // send: the whole jar would send one host's session to another once a
77
+ // jar is shared across hosts, and cookies the request path is not in
78
+ // scope for. The host is the runtime's own, the path the one this call
79
+ // is going to. The jar's copies come first: where a name is in both,
80
+ // the jar holds what this runtime last set and the document's copy
81
+ // mirrors it, so the jar is the one to believe.
72
82
  const cookieScope = { host: mockApp.cookieHost, path: url.pathname };
73
83
  const cookies = cookieValuesByName(jar.cookiePairs(cookieScope));
74
84
  // Pair by pair, so a name the document holds at two scopes keeps both
75
85
  // values and the session controller can weigh them, as it does on
76
86
  // the server.
77
- for (const [name, values] of Object.entries(cookieValuesByName((request.headers.get("cookie") ?? "").split(";")))) {
87
+ const pageCookies = typeof document === "undefined" ? "" : document.cookie;
88
+ for (const [name, values] of Object.entries(cookieValuesByName(pageCookies.split(";")))) {
78
89
  for (const value of values) {
79
90
  if (!cookies[name]?.includes(value))
80
91
  (cookies[name] ??= []).push(value);
@@ -105,12 +116,12 @@ export const lambderMockMswHandler = (mockApp, options) => {
105
116
  const setCookies = getAnswerHeader(answer.headers, "Set-Cookie") ?? [];
106
117
  jar.storeSetCookies(setCookies, cookieScope);
107
118
  // The cookies a page's own scripts may see are mirrored into
108
- // document.cookie, so it reads the same in mocked development as it
109
- // does against the real backend. Not decoration: the browser caller
110
- // reads the CSRF token from there and posts it on the envelope, so
111
- // without this every session call fails its CSRF check. Through the
112
- // runtime, which is where the one mirror implementation lives and
113
- // where what was planted is remembered for reset().
119
+ // document.cookie, so it reads the same in mocked development as
120
+ // against the real backend. Not decoration: the browser caller reads
121
+ // the CSRF token from there and posts it on the envelope, so without
122
+ // this every session call fails its CSRF check. Done by the runtime,
123
+ // which owns the one mirror implementation and remembers what was
124
+ // planted for reset().
114
125
  mockApp.mirrorCookiesIntoDocument(setCookies);
115
126
  const responseHeaders = new Headers();
116
127
  for (const [key, values] of Object.entries(answer.headers)) {
@@ -0,0 +1,26 @@
1
+ import type { LambderMemoryUploadBucket } from "../stores/LambderMemoryUploadBucket.js";
2
+ import type { LambderMswModule } from "./lambderMockMswHandler.js";
3
+ /**
4
+ * The MSW handler that makes a LambderMemoryUploadBucket the storage a mock
5
+ * app's browser uploads to: every request under the bucket's baseUrl (a
6
+ * LambderUploadRunner's post, a download link's GET) is answered by the
7
+ * bucket, the way S3 would answer it. Register it beside the API handler:
8
+ *
9
+ * ```ts
10
+ * const documents = new LambderMemoryUploadBucket();
11
+ * setupWorker(
12
+ * lambderMockMswHandler(mockApp, { apiPath: "/api", msw }),
13
+ * lambderMockUploadMswHandler(documents, { msw }),
14
+ * );
15
+ * ```
16
+ *
17
+ * The mock's ticket and confirm handlers then call `documents` as the
18
+ * server's call the real bucket, so the runner's whole conversation runs, the
19
+ * checks storage makes on a post included.
20
+ *
21
+ * Lambder never depends on msw: the app installs it and passes the module
22
+ * in. Generic over the module so the handler keeps msw's own handler type.
23
+ */
24
+ export declare const lambderMockUploadMswHandler: <M extends LambderMswModule>(bucket: LambderMemoryUploadBucket, options: {
25
+ msw: M;
26
+ }) => ReturnType<M["http"]["all"]>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The MSW handler that makes a LambderMemoryUploadBucket the storage a mock
3
+ * app's browser uploads to: every request under the bucket's baseUrl (a
4
+ * LambderUploadRunner's post, a download link's GET) is answered by the
5
+ * bucket, the way S3 would answer it. Register it beside the API handler:
6
+ *
7
+ * ```ts
8
+ * const documents = new LambderMemoryUploadBucket();
9
+ * setupWorker(
10
+ * lambderMockMswHandler(mockApp, { apiPath: "/api", msw }),
11
+ * lambderMockUploadMswHandler(documents, { msw }),
12
+ * );
13
+ * ```
14
+ *
15
+ * The mock's ticket and confirm handlers then call `documents` as the
16
+ * server's call the real bucket, so the runner's whole conversation runs, the
17
+ * checks storage makes on a post included.
18
+ *
19
+ * Lambder never depends on msw: the app installs it and passes the module
20
+ * in. Generic over the module so the handler keeps msw's own handler type.
21
+ */
22
+ export const lambderMockUploadMswHandler = (bucket, options) => {
23
+ const { msw } = options;
24
+ if (!msw?.http?.all) {
25
+ throw new Error('lambderMockUploadMswHandler requires the msw module: lambderMockUploadMswHandler(bucket, { msw: await import("msw") }). Install it with: npm install msw --save-dev');
26
+ }
27
+ return msw.http.all(`${bucket.baseUrl}*`, async ({ request }) => (await bucket.handleStorageRequest(request)) ?? undefined);
28
+ };
package/dist/mock.d.ts CHANGED
@@ -8,12 +8,15 @@
8
8
  */
9
9
  export { LambderMockApp, initLambderMock } from "./mock/LambderMockApp.js";
10
10
  export { LambderMockTransportError } from "./mock/LambderMockFailureInjector.js";
11
- export type { LambderMockAppOptions, LambderMockSessionsOptions, LambderMockIdempotencyOptions, LambderMockTransport, LambderMockTransportOptions } from "./mock/LambderMockCreateOptions.js";
11
+ export type { LambderMockAppOptions, LambderMockSessionsOptions, LambderMockIdempotencyOptions, LambderMockInvalidInputAnswer, LambderMockTransport, LambderMockTransportOptions } from "./mock/LambderMockCreateOptions.js";
12
12
  export type { LambderMockCallContext, LambderMockSessionCallContext, LambderMockContext, LambderMockGuards, LambderMockHandler, LambderMockEntry, LambderMockEntryOptions, LambderMockEntryInput, LambderMockSlice, LambderMockRestEntry, LambderMockRegistryCheck, LambderMockMissingNames, LambderMockStrayNames, LambderMockDuplicateNames, LambderMockPublicNames, LambderMockSessionNames, LambderMockLatency, LambderMockFailure, LambderMockFailureReason, LambderMockOutcome, LambderMockCallEvent, LambderMockRequestEvent, LambderMockResponseEvent, LambderMockCallRecord, LambderMockListener, LambderMockRateLimitPolicies, LambderMockInputOf, LambderMockOutputOf, LambderMockOverride, } from "./mock/LambderMockTypes.js";
13
13
  export { lambderMockConsoleLogger } from "./mock/lambderMockConsoleLogger.js";
14
14
  export type { LambderMockConsoleLoggerOptions } from "./mock/lambderMockConsoleLogger.js";
15
15
  export { lambderMockMswHandler } from "./mock/lambderMockMswHandler.js";
16
16
  export type { LambderMswModule, LambderMockMswTarget } from "./mock/lambderMockMswHandler.js";
17
+ export { LambderMemoryUploadBucket } from "./stores/LambderMemoryUploadBucket.js";
18
+ export type { LambderMemoryUploadBucketOptions, LambderMemoryUploadObject } from "./stores/LambderMemoryUploadBucket.js";
19
+ export { lambderMockUploadMswHandler } from "./mock/lambderMockUploadMswHandler.js";
17
20
  export { lambderMockInvokeTransport } from "./mock/lambderMockInvokeTransport.js";
18
21
  export type { LambderMockInvokeEvent, LambderMockInvokeResult } from "./mock/lambderMockInvokeTransport.js";
19
22
  export { LambderCookieJar } from "./shared/transport/LambderCookieJar.js";
package/dist/mock.js CHANGED
@@ -9,12 +9,15 @@
9
9
  export { LambderMockApp, initLambderMock } from "./mock/LambderMockApp.js";
10
10
  // The four collaborators behind LambderMockApp (the entry registry, the call
11
11
  // recorder, the failure injector, the browser cookies) are deliberately not
12
- // exported: the runtime is reached through the app, and its surface did not
13
- // change when they moved out of it. Only the error a transport rejects with is
14
- // public, as before.
12
+ // exported: the runtime is reached through the app. Only the error a
13
+ // transport rejects with is public.
15
14
  export { LambderMockTransportError } from "./mock/LambderMockFailureInjector.js";
16
15
  export { lambderMockConsoleLogger } from "./mock/lambderMockConsoleLogger.js";
17
16
  export { lambderMockMswHandler } from "./mock/lambderMockMswHandler.js";
17
+ // The storage a mock app's uploads go to: a memory bucket the mock's ticket and
18
+ // confirm handlers call, and the MSW handler that answers its storage requests.
19
+ export { LambderMemoryUploadBucket } from "./stores/LambderMemoryUploadBucket.js";
20
+ export { lambderMockUploadMswHandler } from "./mock/lambderMockUploadMswHandler.js";
18
21
  export { lambderMockInvokeTransport } from "./mock/lambderMockInvokeTransport.js";
19
22
  // What a mock setup reaches for beside the app: the stores it runs on, the
20
23
  // jar its transport carries, and the refusal a handler says no with.
@@ -5,10 +5,10 @@ import type LambderSessionManager from "./LambderSessionManager.js";
5
5
  import type { LambderCreatedSession } from "./LambderSessionManager.js";
6
6
  /**
7
7
  * The part of a call this controller touches: the session it reads and
8
- * writes, and the headers it puts Set-Cookie on. Declaring it here is what
9
- * keeps the session layer under the API core rather than beside it: the
10
- * pipeline and both adapters pass their own full call context, which is
11
- * structurally this plus the fields the controller never reads.
8
+ * writes, and the headers it puts Set-Cookie on. Declared here so the session
9
+ * layer sits under the API core rather than beside it: the pipeline and both
10
+ * adapters pass their full call context, which is structurally this plus
11
+ * fields the controller never reads.
12
12
  */
13
13
  export type LambderSessionCallSurface<TSessionData = any> = {
14
14
  session: LambderSessionRecord<TSessionData> | null;
@@ -20,10 +20,9 @@ export type LambderSessionCallSurface<TSessionData = any> = {
20
20
  * one deployment serves several apex domains (return undefined for a
21
21
  * host-only cookie). Changing `domain` or `path` on a live deployment is a
22
22
  * migration: browsers keep the cookie under the old scope beside the new
23
- * one, and both arrive on every request. fetchSession tolerates that by
24
- * scanning every copy for the one live session and evicting the stale
25
- * host-only twin; a copy at a parent domain this host cannot name outlives
26
- * its own Expires.
23
+ * one, and both arrive on every request. fetchSession scans every copy for
24
+ * the one live session and evicts the stale host-only twin; a copy at a
25
+ * parent domain this host cannot name lives until its own Expires.
27
26
  */
28
27
  export type LambderSessionCookieOptions = Pick<LambderCookieOptions, "domain" | "path" | "sameSite" | "secure">;
29
28
  /**
@@ -41,10 +40,9 @@ export type LambderSessionControllerOptions<TSessionData> = {
41
40
  manager: LambderSessionManager<TSessionData>;
42
41
  /**
43
42
  * Name of the session cookie. Required rather than defaulted here: the
44
- * defaults live in shared/wire/LambderSessionCookieNames.ts and are applied
45
- * once, where the app's session options are read, so a second copy of
46
- * them in this constructor would be a second place for them to drift and
47
- * would let a controller read a cookie name the app never writes.
43
+ * defaults (shared/wire/LambderSessionCookieNames.ts) are applied once,
44
+ * where the app's session options are read. A second copy here could
45
+ * drift and have a controller read a cookie name the app never writes.
48
46
  */
49
47
  tokenCookieKey: string;
50
48
  /** Name of the CSRF cookie, required on the same terms as tokenCookieKey. */
@@ -55,40 +53,46 @@ export type LambderSessionControllerOptions<TSessionData> = {
55
53
  request: LambderSessionRequestInfo;
56
54
  };
57
55
  /**
58
- * No session for this request: the cookies named none, or the single session
59
- * they named did not pair with the posted CSRF token.
56
+ * No session for this request: the cookies named none, the single session
57
+ * they named did not pair with the posted CSRF token, they cannot be
58
+ * resolved to one session (LambderSessionAmbiguousError, the one case with a
59
+ * type of its own), or the session was ended while the request held it (a
60
+ * logout or a password change elsewhere, or the dataRefresh callback).
60
61
  *
61
- * Typed rather than a bare Error because fetchSessionIfExists has to tell
62
- * "there is no session here" apart from "something broke". Everything else,
63
- * a TypeError from a custom store, a bug in an app's dataRefresh callback,
64
- * propagates and becomes a crash: answering sessionExpired for a defect makes
65
- * the client clear its cookies and turns somebody's bug into a logout.
62
+ * Typed so fetchSessionIfExists can tell "no session here" from "something
63
+ * broke", and so can every place that answers a request which needed a
64
+ * session and has none (the API pipeline, a route or a hook on the server):
65
+ * each tests for this class, and the ambiguous case with it. Everything else
66
+ * (a TypeError from a custom store, a bug in a dataRefresh callback)
67
+ * propagates as a crash: answering sessionExpired for a defect makes the
68
+ * client clear its cookies and turns a bug into a logout.
66
69
  */
67
70
  export declare class LambderSessionNotFoundError extends Error {
68
71
  constructor(message?: string);
69
72
  }
70
73
  /**
71
74
  * The request's session cookies cannot be resolved to one session, so none of
72
- * them is used and every scope this host can write is cleared. Also a "no
73
- * session" answer to the caller, and deliberately a different type: this one
74
- * carries the clearing Set-Cookie headers that heal the state, and it is the
75
- * one worth finding in a log.
75
+ * them is used and every scope this host can write is cleared. A request with
76
+ * no usable session, so it is a LambderSessionNotFoundError and is answered
77
+ * as one wherever that is (a 401 or the session-expired route answer, the
78
+ * sessionExpired envelope on an API call). The subclass keeps it apart for
79
+ * whoever wants to tell: this case carries the clearing Set-Cookie headers
80
+ * that heal the state, and it is the one worth finding in a log.
76
81
  */
77
- export declare class LambderSessionAmbiguousError extends Error {
82
+ export declare class LambderSessionAmbiguousError extends LambderSessionNotFoundError {
78
83
  constructor(message?: string);
79
84
  }
80
85
  /**
81
86
  * A `__Host-` cookie is the browser's own answer to a sibling subdomain
82
87
  * planting a session cookie at a parent domain: it refuses one that carries a
83
88
  * Domain, so no other host can write it. `__Secure-` is the weaker sibling,
84
- * accepted only on a Secure cookie. Both protections fail silently, though: a
85
- * browser handed a prefixed name with an attribute the prefix forbids simply
86
- * discards the cookie, and the app looks like it has no sessions at all
87
- * rather than like it is misconfigured. So the combinations are rejected at
88
- * creation instead.
89
+ * accepted only on a Secure cookie. Both fail silently: a browser discards a
90
+ * prefixed cookie with an attribute the prefix forbids, and the app looks
91
+ * like it has no sessions rather than like it is misconfigured. So the
92
+ * combinations are rejected at creation.
89
93
  *
90
94
  * Session policy, so it lives beside the controller that writes the cookies
91
- * rather than in the pipeline that happens to call it.
95
+ * rather than in the pipeline that calls it.
92
96
  */
93
97
  export declare const assertSessionCookiePrefixes: (sessions: {
94
98
  tokenCookieKey: string;
@@ -97,11 +101,11 @@ export declare const assertSessionCookiePrefixes: (sessions: {
97
101
  }) => void;
98
102
  /**
99
103
  * Sessions as one request sees them: reads the session the request's
100
- * cookies name onto the context, and writes the cookies a created,
101
- * rotated or ended session needs into the context's response headers.
102
- * Server handlers reach it through lambder.getSessionController(ctx); mock
103
- * handlers through ctx.sessions. It works on the call context and the
104
- * request info alone, so it is one class for both.
104
+ * cookies name onto the context, and writes the cookies a created, rotated
105
+ * or ended session needs into the context's response headers. Server and
106
+ * mock handlers reach it as ctx.sessionController (the server's also through
107
+ * lambder.getSessionController(ctx)); it needs only the call context and
108
+ * request info, so one class serves both.
105
109
  */
106
110
  export default class LambderSessionController<TSessionData = any> {
107
111
  readonly manager: LambderSessionManager<TSessionData>;
@@ -114,48 +118,44 @@ export default class LambderSessionController<TSessionData = any> {
114
118
  /** The configured scope with the domain resolved for this request, or the host-only scope. */
115
119
  private cookieScope;
116
120
  /**
117
- * Both cookies at one expiry, with the raw secrets. They exist only on the
118
- * LambderCreatedSession result, in these cookies and in the request that
119
- * carried them back; the record stores hashes. `csrfToken` is null where
120
- * the raw CSRF value is not known to this request, in which case only the
121
- * session cookie is written: writing a CSRF cookie whose value does not
122
- * pair with the session would break the very session it is refreshing.
121
+ * Both cookies at one expiry, with the raw secrets, which exist only on
122
+ * the LambderCreatedSession result, in these cookies and in requests that
123
+ * carry them back; the record stores hashes. `csrfToken` is null when this
124
+ * request does not know the raw CSRF value, and then only the session
125
+ * cookie is written: a CSRF cookie that does not pair with the session
126
+ * would break the session it is refreshing.
123
127
  */
124
128
  private writeSessionCookies;
125
129
  private setSessionCookies;
126
130
  /**
127
- * The deleting pair for one scope. Written once because a deletion only
128
- * reaches a cookie carrying the same Domain and Path, so the pair is
129
- * emitted per scope and the two callers differ in nothing but which
130
- * scopes they walk.
131
+ * The deleting pair for one scope. A deletion only reaches a cookie with
132
+ * the same Domain and Path, so the pair is emitted per scope; the two
133
+ * callers differ only in which scopes they walk.
131
134
  */
132
135
  private addClearCookiePair;
133
136
  private clearSessionCookies;
134
137
  /**
135
138
  * Every Domain this host is allowed to write the session cookies at: the
136
139
  * host-only scope, the configured one, and each parent domain of the
137
- * request host. A deletion matches only a cookie carrying the same
138
- * Domain, so evicting a copy the app itself never set needs all of them.
139
- * A browser ignores a Domain it will not accept, which is why a suffix
140
- * the registry owns can be offered without checking a public-suffix list.
140
+ * request host. A deletion matches only a cookie with the same Domain, so
141
+ * evicting a copy the app never set needs all of them. A browser ignores
142
+ * a Domain it will not accept, so a registry-owned suffix can be offered
143
+ * without checking a public-suffix list.
141
144
  */
142
145
  private cookieClearDomains;
143
146
  /**
144
- * Clears the session cookies at every scope this host can reach, rather
145
- * than at the one the app configured. Used when a request carries more
146
- * than one live session: the copy that has to go may sit at a parent
147
- * domain a sibling host planted it at, and clearing the configured scope
148
- * alone would evict this visitor's own cookie and leave the planted one
149
- * as the only survivor, which completes the takeover instead of stopping
150
- * it.
147
+ * Clears the session cookies at every scope this host can reach, not just
148
+ * the configured one. Used when a request carries more than one live
149
+ * session: the copy that has to go may sit at a parent domain where a
150
+ * sibling host planted it, and clearing only the configured scope would
151
+ * evict the visitor's own cookie and leave the planted one as the sole
152
+ * survivor, completing the takeover instead of stopping it.
151
153
  */
152
154
  private clearSessionCookiesEverywhere;
153
155
  /**
154
156
  * Refuses a request whose session cookies cannot be resolved to one
155
- * session, clearing every scope this host can write. Clearing only the
156
- * configured scope would be worse than picking one: a deletion matches
157
- * only a cookie carrying the same Domain, so it would evict the visitor's
158
- * own copy and leave a planted one as the sole survivor.
157
+ * session, clearing every scope this host can write (see
158
+ * clearSessionCookiesEverywhere for why not just the configured one).
159
159
  *
160
160
  * Path is the one dimension this cannot sweep: the request info carries
161
161
  * no path, and a deletion matches only a cookie at the same Path, so a
@@ -168,12 +168,11 @@ export default class LambderSessionController<TSessionData = any> {
168
168
  * Both session cookie names read in one pass: every well-formed value
169
169
  * under the token name, and every value under the CSRF name.
170
170
  *
171
- * The CSRF cookie is counted here rather than looked at only when a token
172
- * is checked against it, because it is plantable exactly like the session
173
- * cookie and the browser picks between copies without telling anyone: the
174
- * client reads its CSRF token with js-cookie's Cookies.get, which returns
175
- * the FIRST copy in document.cookie, and a browser orders a longer Path
176
- * first. So a sibling host that plants one CSRF cookie at a parent domain
171
+ * The CSRF cookie is counted, not just checked against a token, because
172
+ * it is plantable like the session cookie and the browser picks between
173
+ * copies silently: the client reads it with js-cookie's Cookies.get, which
174
+ * returns the FIRST copy in document.cookie, and browsers order a longer
175
+ * Path first. A sibling host that plants a CSRF cookie at a parent domain
177
176
  * with a deeper Path decides which token every call posts, and the count
178
177
  * is the only thing that shows it.
179
178
  */
@@ -182,45 +181,65 @@ export default class LambderSessionController<TSessionData = any> {
182
181
  private areRequestSessionTokensValid;
183
182
  createSession(sessionKey: string, data?: TSessionData, ttlInSeconds?: number): Promise<LambderSessionRecord<TSessionData>>;
184
183
  /**
185
- * createSession, handing back the raw tokens beside the session: what a
186
- * test or a mock runtime needs to plant the cookies somewhere else (a
187
- * cookie jar) than this call's response.
184
+ * createSession, handing back the raw tokens beside the session, for a
185
+ * test or mock runtime that plants the cookies somewhere other than this
186
+ * call's response (a cookie jar).
188
187
  */
189
188
  issueSession(sessionKey: string, data?: TSessionData, ttlInSeconds?: number): Promise<LambderCreatedSession<TSessionData>>;
190
189
  regenerateSession(): Promise<LambderSessionRecord<TSessionData>>;
191
190
  /**
192
- * regenerateSession, handing back the raw tokens beside the session, the
193
- * way issueSession does for a new one. Rotating the session mints a new
194
- * CSRF token, and a client that holds its token rather than reading
195
- * document.cookie (a native app, an invoke caller) needs the new one to
196
- * keep calling.
191
+ * regenerateSession, handing back the raw tokens beside the session as
192
+ * issueSession does. Rotation mints a new CSRF token, and a client that
193
+ * holds its token rather than reading document.cookie (a native app, an
194
+ * invoke caller) needs the new one to keep calling.
197
195
  */
198
196
  reissueSession(): Promise<LambderCreatedSession<TSessionData>>;
199
197
  fetchSession(): Promise<LambderSessionRecord<TSessionData>>;
200
198
  /**
201
199
  * Re-issues both cookies at this session's expiry: after a sliding write
202
- * moved it, and beside the host-only eviction above, which would
203
- * otherwise delete a cookie without replacing it.
200
+ * moved it, and beside the host-only eviction, which would otherwise
201
+ * delete a cookie without replacing it.
204
202
  *
205
- * The raw CSRF value is the posted one on an API call, which the pairing
206
- * check above has just matched against this session. A route posts none,
207
- * so the single arriving CSRF cookie stands in, and only once it is known
208
- * to pair: re-issuing an unpaired value would overwrite this visitor's
209
- * real CSRF cookie with a planted one, at the app's own scope, which is
210
- * the takeover the scan exists to prevent. Where neither is available the
211
- * session cookie slides alone, which is the half that decides whether the
212
- * session survives.
203
+ * On an API call the raw CSRF value is the posted one, which the pairing
204
+ * check just matched. A route posts none, so the single arriving CSRF
205
+ * cookie stands in, but only once it is known to pair: re-issuing an
206
+ * unpaired value would overwrite the visitor's real CSRF cookie with a
207
+ * planted one at the app's own scope, the takeover the scan exists to
208
+ * prevent. Where neither is available the session cookie slides alone;
209
+ * it is the half that decides whether the session survives.
213
210
  */
214
211
  private slideSessionCookies;
212
+ /**
213
+ * "No session" for a request whose session cookie names none, or whose
214
+ * session ended while it held it: the context holds none.
215
+ *
216
+ * The cookies are left alone. A deletion matches a cookie by name, not by
217
+ * value, so clearing here would also delete a session another response
218
+ * has just set: a poll sent with the old cookie, answering after a login,
219
+ * a rotation or a password change, would sign the person straight out of
220
+ * the new session. It also keeps the client's own check working, which
221
+ * clears the CSRF cookie only while it still holds the token the call
222
+ * sent. A dead cookie costs a store read per request until it expires.
223
+ */
224
+ private endWithNoSession;
215
225
  fetchSessionIfExists(): Promise<LambderSessionRecord<TSessionData> | null>;
226
+ /**
227
+ * Writes new data onto the current session. Throws
228
+ * LambderSessionNotFoundError when the session was ended while this
229
+ * request held it: the write does not bring it back, and an API call
230
+ * answers sessionExpired.
231
+ */
216
232
  updateSessionData(newData: TSessionData): Promise<LambderSessionRecord<TSessionData>>;
217
233
  /**
218
- * Force-runs the dataRefresh callback now (see the session option of create) and
219
- * persists the result onto the current session. Returns the updated
220
- * session, or null when the callback ended it: the record is deleted and
221
- * the session cookies are cleared.
234
+ * Force-runs the dataRefresh callback now (see the session option of
235
+ * create) and persists the result onto the current session. Throws
236
+ * LambderSessionNotFoundError when the session is over, because the
237
+ * callback ended it (the record is deleted) or because it was ended while
238
+ * this request held it: the same "no session" a read gives for either,
239
+ * with the cookies left alone (see endWithNoSession), and what an API
240
+ * call answers as sessionExpired.
222
241
  */
223
- refreshSessionData(): Promise<LambderSessionRecord<TSessionData> | null>;
242
+ refreshSessionData(): Promise<LambderSessionRecord<TSessionData>>;
224
243
  /**
225
244
  * Deletes every session of the given sessionKey (e.g. a user id): "log
226
245
  * this subject out everywhere". Unlike endSessionAll it needs no fetched