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.
- package/CHANGELOG.md +1047 -3
- package/README.md +46 -21
- package/dist/api/LambderApiAnswer.d.ts +18 -22
- package/dist/api/LambderApiAnswer.js +6 -7
- package/dist/api/LambderApiCallContext.d.ts +21 -8
- package/dist/api/LambderApiCallContext.js +22 -4
- package/dist/api/LambderApiDefinition.d.ts +4 -3
- package/dist/api/LambderApiEnvelope.d.ts +14 -9
- package/dist/api/LambderApiEnvelope.js +33 -34
- package/dist/api/LambderApiGuards.d.ts +78 -51
- package/dist/api/LambderApiGuards.js +34 -36
- package/dist/api/LambderApiIdempotency.d.ts +68 -62
- package/dist/api/LambderApiIdempotency.js +214 -151
- package/dist/api/LambderApiOutputValidationError.d.ts +32 -0
- package/dist/api/LambderApiOutputValidationError.js +50 -0
- package/dist/api/LambderApiPipeline.d.ts +47 -38
- package/dist/api/LambderApiPipeline.js +122 -63
- package/dist/api/LambderApiRateLimits.d.ts +201 -54
- package/dist/api/LambderApiRateLimits.js +185 -108
- package/dist/api/LambderApiRequest.d.ts +27 -21
- package/dist/api/LambderApiRequest.js +26 -19
- package/dist/api/LambderApiSignature.d.ts +12 -15
- package/dist/api/LambderApiSignature.js +28 -51
- package/dist/api/LambderApiValidationRefusal.d.ts +9 -9
- package/dist/api/LambderApiValidationRefusal.js +10 -10
- package/dist/build/ContractTypePrinter.d.ts +85 -0
- package/dist/build/ContractTypePrinter.js +402 -0
- package/dist/build/freshProcessVerifier.d.ts +13 -0
- package/dist/build/freshProcessVerifier.js +19 -0
- package/dist/build/moduleLocation.d.ts +11 -0
- package/dist/build/moduleLocation.js +6 -0
- package/dist/build/writeApiContract.d.ts +78 -0
- package/dist/build/writeApiContract.js +302 -0
- package/dist/build/writeApiSignatures.d.ts +114 -0
- package/dist/build/writeApiSignatures.js +217 -0
- package/dist/build/writeFileAtomically.d.ts +8 -0
- package/dist/build/writeFileAtomically.js +22 -0
- package/dist/build.d.ts +14 -0
- package/dist/build.js +11 -0
- package/dist/client/LambderCaller.d.ts +13 -44
- package/dist/client/LambderCaller.js +77 -84
- package/dist/client/LambderReloadLoopBreaker.d.ts +56 -26
- package/dist/client/LambderReloadLoopBreaker.js +90 -46
- package/dist/client/LambderUploadRunner.d.ts +96 -0
- package/dist/client/LambderUploadRunner.js +234 -0
- package/dist/client/lambderFetchTransport.d.ts +4 -1
- package/dist/client/lambderFetchTransport.js +52 -28
- package/dist/client.d.ts +9 -3
- package/dist/client.js +6 -1
- package/dist/core/Lambder.d.ts +143 -79
- package/dist/core/Lambder.js +350 -231
- package/dist/core/LambderContext.d.ts +82 -15
- package/dist/core/LambderContext.js +107 -20
- package/dist/core/LambderCors.d.ts +21 -3
- package/dist/core/LambderCors.js +35 -16
- package/dist/core/LambderCrashHandling.d.ts +40 -0
- package/dist/core/LambderCrashHandling.js +97 -0
- package/dist/core/LambderCreateOptions.d.ts +151 -75
- package/dist/core/LambderCreateOptions.js +16 -23
- package/dist/core/LambderFiles.d.ts +21 -7
- package/dist/core/LambderFiles.js +62 -34
- package/dist/core/LambderIndexHtml.js +12 -11
- package/dist/core/LambderPolicyBuilders.d.ts +17 -5
- package/dist/core/LambderPolicyBuilders.js +17 -5
- package/dist/core/LambderPublicFiles.d.ts +11 -5
- package/dist/core/LambderPublicFiles.js +32 -4
- package/dist/core/LambderRequestPath.d.ts +43 -0
- package/dist/core/LambderRequestPath.js +63 -0
- package/dist/core/LambderResponse.d.ts +26 -5
- package/dist/core/LambderResponse.js +157 -70
- package/dist/core/LambderResponseBuilder.d.ts +49 -4
- package/dist/core/LambderResponseBuilder.js +64 -3
- package/dist/core/LambderRouting.d.ts +2 -3
- package/dist/core/LambderRouting.js +22 -7
- package/dist/core/LambderTemplatingEngine.js +211 -32
- package/dist/index.d.ts +25 -8
- package/dist/index.js +13 -4
- package/dist/invoke/LambderInvokeCaller.d.ts +37 -42
- package/dist/invoke/LambderInvokeCaller.js +76 -66
- package/dist/invoke/LambderInvokeOutcome.d.ts +27 -26
- package/dist/invoke/LambderInvokeOutcome.js +9 -22
- package/dist/invoke/LambderLambdaEvent.d.ts +29 -9
- package/dist/invoke/LambderLambdaEvent.js +40 -22
- package/dist/invoke/lambderHandlerTransport.d.ts +9 -10
- package/dist/invoke/lambderHandlerTransport.js +15 -18
- package/dist/mock/LambderMockApp.d.ts +67 -83
- package/dist/mock/LambderMockApp.js +167 -153
- package/dist/mock/LambderMockBrowserCookies.d.ts +24 -28
- package/dist/mock/LambderMockBrowserCookies.js +24 -28
- package/dist/mock/LambderMockCallRecorder.d.ts +15 -22
- package/dist/mock/LambderMockCallRecorder.js +19 -28
- package/dist/mock/LambderMockCreateOptions.d.ts +42 -24
- package/dist/mock/LambderMockEntryRegistry.d.ts +11 -12
- package/dist/mock/LambderMockEntryRegistry.js +24 -29
- package/dist/mock/LambderMockFailureInjector.d.ts +3 -6
- package/dist/mock/LambderMockFailureInjector.js +3 -6
- package/dist/mock/LambderMockTypes.d.ts +78 -108
- package/dist/mock/lambderMockInvokeTransport.d.ts +11 -13
- package/dist/mock/lambderMockInvokeTransport.js +11 -10
- package/dist/mock/lambderMockMswHandler.d.ts +43 -33
- package/dist/mock/lambderMockMswHandler.js +50 -39
- package/dist/mock/lambderMockUploadMswHandler.d.ts +26 -0
- package/dist/mock/lambderMockUploadMswHandler.js +28 -0
- package/dist/mock.d.ts +4 -1
- package/dist/mock.js +6 -3
- package/dist/session/LambderSessionController.d.ts +108 -89
- package/dist/session/LambderSessionController.js +187 -168
- package/dist/session/LambderSessionCrypto.d.ts +16 -7
- package/dist/session/LambderSessionCrypto.js +26 -12
- package/dist/session/LambderSessionManager.d.ts +124 -46
- package/dist/session/LambderSessionManager.js +262 -137
- package/dist/shared/LambderHtml.d.ts +42 -3
- package/dist/shared/LambderHtml.js +127 -7
- package/dist/shared/LambderHtmlPositions.d.ts +173 -0
- package/dist/shared/LambderHtmlPositions.js +652 -0
- package/dist/shared/LambderI18n.d.ts +10 -11
- package/dist/shared/LambderI18n.js +33 -21
- package/dist/shared/contracts/LambderCache.d.ts +66 -0
- package/dist/shared/contracts/LambderCache.js +11 -0
- package/dist/shared/contracts/LambderFileSource.d.ts +6 -6
- package/dist/shared/contracts/LambderFileSource.js +5 -8
- package/dist/shared/contracts/LambderIdempotencyStore.d.ts +51 -22
- package/dist/shared/contracts/LambderIdempotencyStore.js +4 -5
- package/dist/shared/contracts/LambderRateLimiter.d.ts +27 -15
- package/dist/shared/contracts/LambderRateLimiter.js +4 -5
- package/dist/shared/contracts/LambderSessionStore.d.ts +65 -26
- package/dist/shared/contracts/LambderSessionStore.js +5 -6
- package/dist/shared/contracts/LambderUploadBucket.d.ts +154 -0
- package/dist/shared/contracts/LambderUploadBucket.js +74 -0
- package/dist/shared/transport/LambderApiTransport.d.ts +27 -27
- package/dist/shared/transport/LambderApiTransport.js +7 -7
- package/dist/shared/transport/LambderCookieJar.d.ts +28 -35
- package/dist/shared/transport/LambderCookieJar.js +54 -66
- package/dist/shared/transport/lambderCookieJarTransport.d.ts +11 -13
- package/dist/shared/transport/lambderCookieJarTransport.js +24 -23
- package/dist/shared/util/LambderCallAbort.d.ts +5 -5
- package/dist/shared/util/LambderCallAbort.js +5 -5
- package/dist/shared/util/LambderClientIp.d.ts +27 -11
- package/dist/shared/util/LambderClientIp.js +96 -13
- package/dist/shared/util/LambderContentDisposition.d.ts +10 -0
- package/dist/shared/util/LambderContentDisposition.js +13 -0
- package/dist/shared/util/LambderExpiringMap.d.ts +35 -49
- package/dist/shared/util/LambderExpiringMap.js +41 -57
- package/dist/shared/util/LambderNodeModules.js +6 -7
- package/dist/shared/util/LambderOptionChecks.d.ts +4 -4
- package/dist/shared/util/LambderOptionChecks.js +4 -4
- package/dist/shared/util/LambderResponseBrand.d.ts +5 -5
- package/dist/shared/util/LambderResponseBrand.js +5 -5
- package/dist/shared/util/LambderTextDigest.d.ts +7 -5
- package/dist/shared/util/LambderTextDigest.js +11 -5
- package/dist/shared/util/LambderTypeUtilities.d.ts +7 -8
- package/dist/shared/util/LambderTypeUtilities.js +3 -3
- package/dist/shared/util/boundKeyField.d.ts +20 -0
- package/dist/shared/util/boundKeyField.js +34 -0
- package/dist/shared/util/canonicalJson.d.ts +11 -0
- package/dist/shared/util/canonicalJson.js +28 -0
- package/dist/shared/util/joinKeyFields.d.ts +20 -0
- package/dist/shared/util/joinKeyFields.js +22 -0
- package/dist/shared/wire/LambderAnswerHeaders.d.ts +12 -16
- package/dist/shared/wire/LambderAnswerHeaders.js +12 -16
- package/dist/shared/wire/LambderApiContract.d.ts +98 -53
- package/dist/shared/wire/LambderApiOutcome.d.ts +43 -31
- package/dist/shared/wire/LambderApiOutcome.js +48 -23
- package/dist/shared/wire/LambderApiRefusal.d.ts +45 -27
- package/dist/shared/wire/LambderApiRefusal.js +42 -7
- package/dist/shared/wire/LambderApiSignature.d.ts +18 -22
- package/dist/shared/wire/LambderApiSignature.js +16 -19
- package/dist/shared/wire/LambderCallOptions.d.ts +38 -47
- package/dist/shared/wire/LambderCallOptions.js +9 -11
- package/dist/shared/wire/LambderCompressionCodec.d.ts +29 -34
- package/dist/shared/wire/LambderCompressionCodec.js +31 -36
- package/dist/shared/wire/LambderCompressionOption.d.ts +9 -9
- package/dist/shared/wire/LambderCompressionOption.js +9 -9
- package/dist/shared/wire/LambderCrashDetail.d.ts +12 -15
- package/dist/shared/wire/LambderCrashDetail.js +12 -15
- package/dist/shared/wire/LambderDefaultApiPath.d.ts +6 -0
- package/dist/shared/wire/LambderDefaultApiPath.js +6 -0
- package/dist/shared/wire/LambderHttpStatus.d.ts +6 -7
- package/dist/shared/wire/LambderIdempotencyKeyScope.d.ts +89 -0
- package/dist/shared/wire/LambderIdempotencyKeyScope.js +146 -0
- package/dist/shared/wire/LambderInvokeApiId.d.ts +27 -0
- package/dist/shared/wire/LambderInvokeApiId.js +27 -0
- package/dist/shared/wire/LambderOutcomeAssertions.d.ts +6 -7
- package/dist/shared/wire/LambderOutcomeAssertions.js +6 -7
- package/dist/shared/wire/LambderRequestPayload.d.ts +18 -20
- package/dist/shared/wire/LambderRequestPayload.js +4 -6
- package/dist/shared/wire/LambderUploadObjectFields.d.ts +10 -0
- package/dist/shared/wire/LambderUploadObjectFields.js +24 -0
- package/dist/shared/wire/LambderUploadRefusal.d.ts +9 -0
- package/dist/shared/wire/LambderUploadRefusal.js +18 -0
- package/dist/shared/wire/LambderUploadSchemas.d.ts +12 -0
- package/dist/shared/wire/LambderUploadSchemas.js +30 -0
- package/dist/stores/LambderCacheFiller.d.ts +48 -0
- package/dist/stores/LambderCacheFiller.js +119 -0
- package/dist/stores/LambderCacheKeys.d.ts +26 -0
- package/dist/stores/LambderCacheKeys.js +54 -0
- package/dist/stores/LambderCacheValues.d.ts +45 -0
- package/dist/stores/LambderCacheValues.js +74 -0
- package/dist/stores/LambderDdbCache.d.ts +121 -56
- package/dist/stores/LambderDdbCache.js +528 -225
- package/dist/stores/LambderDdbIdempotencyStore.d.ts +33 -22
- package/dist/stores/LambderDdbIdempotencyStore.js +75 -50
- package/dist/stores/LambderDdbRateLimiter.d.ts +76 -20
- package/dist/stores/LambderDdbRateLimiter.js +151 -39
- package/dist/stores/LambderDdbSdk.d.ts +43 -31
- package/dist/stores/LambderDdbSdk.js +80 -38
- package/dist/stores/LambderDdbSessionStore.d.ts +27 -14
- package/dist/stores/LambderDdbSessionStore.js +119 -47
- package/dist/stores/LambderHttpFileSource.d.ts +15 -6
- package/dist/stores/LambderHttpFileSource.js +15 -13
- package/dist/stores/LambderMemoryCache.d.ts +49 -0
- package/dist/stores/LambderMemoryCache.js +113 -0
- package/dist/stores/LambderMemoryIdempotencyStore.d.ts +13 -12
- package/dist/stores/LambderMemoryIdempotencyStore.js +31 -30
- package/dist/stores/LambderMemoryRateLimiter.d.ts +8 -9
- package/dist/stores/LambderMemoryRateLimiter.js +14 -13
- package/dist/stores/LambderMemorySessionStore.d.ts +14 -11
- package/dist/stores/LambderMemorySessionStore.js +38 -19
- package/dist/stores/LambderMemoryUploadBucket.d.ts +99 -0
- package/dist/stores/LambderMemoryUploadBucket.js +219 -0
- package/dist/stores/LambderS3FileSource.d.ts +21 -6
- package/dist/stores/LambderS3FileSource.js +12 -7
- package/dist/stores/LambderS3UploadBucket.d.ts +73 -0
- package/dist/stores/LambderS3UploadBucket.js +144 -0
- package/dist/stores/LambderSdkInstallHint.d.ts +11 -0
- package/dist/stores/LambderSdkInstallHint.js +14 -0
- package/dist/testing/LambderTestApp.d.ts +23 -25
- package/dist/testing/LambderTestApp.js +22 -24
- package/dist/testing/LambderTestVisitor.d.ts +10 -12
- package/dist/testing/LambderTestVisitor.js +15 -15
- package/dist/testing.d.ts +3 -0
- package/dist/testing.js +2 -0
- package/package.json +26 -3
- package/dist/api/LambderApiPolicyEngine.d.ts +0 -47
- package/dist/api/LambderApiPolicyEngine.js +0 -85
- package/dist/shared/util/LambderKeyFields.d.ts +0 -32
- 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,
|
|
11
|
-
*
|
|
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
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
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
|
|
28
|
-
*
|
|
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
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
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,
|
|
58
|
-
// Object.create(null): a header literally named
|
|
59
|
-
//
|
|
60
|
-
//
|
|
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:
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
//
|
|
70
|
-
//
|
|
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
|
-
|
|
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
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
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
|
|
13
|
-
//
|
|
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.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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
|
|
24
|
-
*
|
|
25
|
-
*
|
|
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
|
|
45
|
-
*
|
|
46
|
-
*
|
|
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,
|
|
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
|
|
62
|
-
* "
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
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.
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
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
|
|
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
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
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
|
|
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
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
* request info
|
|
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
|
|
118
|
-
* LambderCreatedSession result, in these cookies and in
|
|
119
|
-
*
|
|
120
|
-
* the raw CSRF value
|
|
121
|
-
*
|
|
122
|
-
*
|
|
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.
|
|
128
|
-
*
|
|
129
|
-
*
|
|
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
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
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,
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
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
|
|
156
|
-
*
|
|
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
|
|
172
|
-
* is
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
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
|
|
186
|
-
* test or
|
|
187
|
-
*
|
|
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
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
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
|
|
203
|
-
*
|
|
200
|
+
* moved it, and beside the host-only eviction, which would otherwise
|
|
201
|
+
* delete a cookie without replacing it.
|
|
204
202
|
*
|
|
205
|
-
*
|
|
206
|
-
* check
|
|
207
|
-
*
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
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
|
|
219
|
-
* persists the result onto the current session.
|
|
220
|
-
*
|
|
221
|
-
* the
|
|
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
|
|
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
|