lambder 6.0.1 → 7.0.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 +2316 -0
- package/README.md +60 -33
- package/dist/api/LambderApiAnswer.d.ts +40 -0
- package/dist/api/LambderApiAnswer.js +19 -0
- package/dist/api/LambderApiCallContext.d.ts +38 -0
- package/dist/api/LambderApiCallContext.js +13 -0
- package/dist/api/LambderApiDefinition.d.ts +18 -0
- package/dist/api/LambderApiDefinition.js +1 -0
- package/dist/api/LambderApiEnvelope.d.ts +67 -0
- package/dist/api/LambderApiEnvelope.js +180 -0
- package/dist/api/LambderApiGuards.d.ts +302 -0
- package/dist/api/LambderApiGuards.js +134 -0
- package/dist/api/LambderApiIdempotency.d.ts +122 -0
- package/dist/api/LambderApiIdempotency.js +330 -0
- package/dist/api/LambderApiPipeline.d.ts +134 -0
- package/dist/api/LambderApiPipeline.js +221 -0
- package/dist/api/LambderApiPolicyEngine.d.ts +36 -0
- package/dist/api/LambderApiPolicyEngine.js +77 -0
- package/dist/api/LambderApiRateLimits.d.ts +206 -0
- package/dist/api/LambderApiRateLimits.js +239 -0
- package/dist/api/LambderApiRequest.d.ts +101 -0
- package/dist/api/LambderApiRequest.js +129 -0
- package/dist/api/LambderApiValidationRefusal.d.ts +32 -0
- package/dist/api/LambderApiValidationRefusal.js +40 -0
- package/dist/client/LambderCaller.d.ts +62 -55
- package/dist/client/LambderCaller.js +147 -90
- package/dist/client/lambderFetchTransport.d.ts +9 -0
- package/dist/client/lambderFetchTransport.js +71 -0
- package/dist/client.d.ts +20 -10
- package/dist/client.js +11 -5
- package/dist/core/Lambder.d.ts +117 -253
- package/dist/core/Lambder.js +374 -341
- package/dist/core/LambderContext.d.ts +54 -44
- package/dist/core/LambderContext.js +41 -110
- package/dist/core/LambderCreateOptions.d.ts +285 -0
- package/dist/core/LambderCreateOptions.js +44 -0
- package/dist/core/LambderFiles.d.ts +1 -45
- package/dist/core/LambderFiles.js +18 -38
- package/dist/core/LambderIndexHtml.d.ts +37 -0
- package/dist/core/LambderIndexHtml.js +87 -0
- package/dist/core/LambderPolicyBuilders.d.ts +17 -0
- package/dist/core/LambderPolicyBuilders.js +16 -0
- package/dist/core/LambderPublicFiles.d.ts +5 -2
- package/dist/core/LambderPublicFiles.js +7 -2
- package/dist/core/LambderResolver.d.ts +8 -6
- package/dist/core/LambderResponse.d.ts +29 -11
- package/dist/core/LambderResponse.js +96 -49
- package/dist/core/LambderResponseBuilder.d.ts +18 -14
- package/dist/core/LambderResponseBuilder.js +19 -25
- package/dist/core/LambderRouting.d.ts +18 -7
- package/dist/core/LambderRouting.js +17 -7
- package/dist/core/LambderTemplatingEngine.d.ts +0 -62
- package/dist/core/LambderTemplatingEngine.js +7 -3
- package/dist/index.d.ts +85 -32
- package/dist/index.js +44 -16
- package/dist/invoke/LambderInvokeCaller.d.ts +46 -139
- package/dist/invoke/LambderInvokeCaller.js +140 -335
- package/dist/invoke/LambderInvokeOutcome.d.ts +165 -0
- package/dist/invoke/LambderInvokeOutcome.js +129 -0
- package/dist/invoke/LambderLambdaEvent.d.ts +81 -0
- package/dist/invoke/LambderLambdaEvent.js +187 -0
- package/dist/invoke/lambderHandlerTransport.d.ts +36 -0
- package/dist/invoke/lambderHandlerTransport.js +89 -0
- package/dist/mock/LambderMockApp.d.ts +352 -0
- package/dist/mock/LambderMockApp.js +815 -0
- package/dist/mock/LambderMockBrowserCookies.d.ts +55 -0
- package/dist/mock/LambderMockBrowserCookies.js +76 -0
- package/dist/mock/LambderMockCallRecorder.d.ts +85 -0
- package/dist/mock/LambderMockCallRecorder.js +183 -0
- package/dist/mock/LambderMockCreateOptions.d.ts +161 -0
- package/dist/mock/LambderMockCreateOptions.js +9 -0
- package/dist/mock/LambderMockEntryRegistry.d.ts +52 -0
- package/dist/mock/LambderMockEntryRegistry.js +126 -0
- package/dist/mock/LambderMockFailureInjector.d.ts +60 -0
- package/dist/mock/LambderMockFailureInjector.js +138 -0
- package/dist/mock/LambderMockTypes.d.ts +421 -0
- package/dist/mock/LambderMockTypes.js +8 -0
- package/dist/mock/lambderMockConsoleLogger.d.ts +16 -0
- package/dist/mock/lambderMockConsoleLogger.js +35 -0
- package/dist/mock/lambderMockInvokeTransport.d.ts +50 -0
- package/dist/mock/lambderMockInvokeTransport.js +52 -0
- package/dist/mock/lambderMockMswHandler.d.ts +99 -0
- package/dist/mock/lambderMockMswHandler.js +126 -0
- package/dist/mock.d.ts +34 -0
- package/dist/mock.js +27 -0
- package/dist/session/LambderSessionController.d.ts +199 -30
- package/dist/session/LambderSessionController.js +396 -82
- package/dist/session/LambderSessionCrypto.d.ts +66 -0
- package/dist/session/LambderSessionCrypto.js +101 -0
- package/dist/session/LambderSessionManager.d.ts +118 -80
- package/dist/session/LambderSessionManager.js +212 -184
- package/dist/shared/LambderI18n.d.ts +6 -6
- package/dist/shared/LambderI18n.js +1 -1
- package/dist/shared/contracts/LambderFileSource.d.ts +33 -0
- package/dist/shared/contracts/LambderFileSource.js +19 -0
- package/dist/shared/contracts/LambderIdempotencyStore.d.ts +66 -0
- package/dist/shared/contracts/LambderIdempotencyStore.js +12 -0
- package/dist/shared/contracts/LambderRateLimiter.d.ts +71 -0
- package/dist/shared/contracts/LambderRateLimiter.js +24 -0
- package/dist/shared/contracts/LambderSessionStore.d.ts +72 -0
- package/dist/shared/contracts/LambderSessionStore.js +13 -0
- package/dist/shared/transport/LambderApiTransport.d.ts +139 -0
- package/dist/shared/transport/LambderApiTransport.js +65 -0
- package/dist/shared/transport/LambderCookieJar.d.ts +121 -0
- package/dist/shared/transport/LambderCookieJar.js +246 -0
- package/dist/shared/transport/lambderCookieJarTransport.d.ts +30 -0
- package/dist/shared/transport/lambderCookieJarTransport.js +60 -0
- package/dist/shared/util/LambderBase64.d.ts +10 -0
- package/dist/shared/util/LambderBase64.js +27 -0
- package/dist/shared/util/LambderCallAbort.d.ts +62 -0
- package/dist/shared/util/LambderCallAbort.js +80 -0
- package/dist/shared/util/LambderClientIp.d.ts +32 -0
- package/dist/shared/util/LambderClientIp.js +56 -0
- package/dist/shared/util/LambderExpiringMap.d.ts +119 -0
- package/dist/shared/util/LambderExpiringMap.js +217 -0
- package/dist/shared/util/LambderKeyFields.d.ts +32 -0
- package/dist/shared/util/LambderKeyFields.js +34 -0
- package/dist/shared/util/LambderNodeModules.d.ts +9 -0
- package/dist/shared/util/LambderNodeModules.js +39 -0
- package/dist/shared/util/LambderOptionChecks.d.ts +17 -0
- package/dist/shared/util/LambderOptionChecks.js +33 -0
- package/dist/shared/util/LambderResponseBrand.d.ts +20 -0
- package/dist/shared/util/LambderResponseBrand.js +18 -0
- package/dist/shared/util/LambderTextDigest.d.ts +17 -0
- package/dist/shared/util/LambderTextDigest.js +34 -0
- package/dist/shared/util/LambderTypeUtilities.d.ts +33 -0
- package/dist/shared/util/LambderTypeUtilities.js +8 -0
- package/dist/shared/wire/LambderAnswerHeaders.d.ts +60 -0
- package/dist/shared/wire/LambderAnswerHeaders.js +94 -0
- package/dist/shared/wire/LambderApiContract.d.ts +129 -0
- package/dist/shared/wire/LambderApiOptionValues.d.ts +39 -0
- package/dist/shared/wire/LambderApiOptionValues.js +11 -0
- package/dist/shared/wire/LambderApiOutcome.d.ts +128 -0
- package/dist/shared/{LambderApiOutcome.js → wire/LambderApiOutcome.js} +16 -9
- package/dist/shared/{LambderApiError.d.ts → wire/LambderApiRefusal.d.ts} +48 -26
- package/dist/shared/{LambderApiError.js → wire/LambderApiRefusal.js} +13 -11
- package/dist/shared/wire/LambderCallOptions.d.ts +171 -0
- package/dist/shared/wire/LambderCallOptions.js +17 -0
- package/dist/shared/{LambderCompressionCodec.d.ts → wire/LambderCompressionCodec.d.ts} +10 -6
- package/dist/shared/{LambderCompressionCodec.js → wire/LambderCompressionCodec.js} +67 -23
- package/dist/shared/{LambderCompressionOption.d.ts → wire/LambderCompressionOption.d.ts} +1 -1
- package/dist/shared/{LambderCompressionOption.js → wire/LambderCompressionOption.js} +3 -4
- package/dist/shared/{LambderCrashDetail.d.ts → wire/LambderCrashDetail.d.ts} +10 -0
- package/dist/shared/{LambderCrashDetail.js → wire/LambderCrashDetail.js} +30 -0
- package/dist/shared/wire/LambderHttpStatus.d.ts +12 -0
- package/dist/shared/wire/LambderHttpStatus.js +1 -0
- package/dist/shared/{LambderRequestPayload.d.ts → wire/LambderRequestPayload.d.ts} +25 -17
- package/dist/shared/{LambderRequestPayload.js → wire/LambderRequestPayload.js} +29 -52
- package/dist/shared/wire/LambderSessionCookieNames.d.ts +9 -0
- package/dist/shared/wire/LambderSessionCookieNames.js +9 -0
- package/dist/stores/LambderDdbCache.d.ts +12 -9
- package/dist/stores/LambderDdbCache.js +56 -47
- package/dist/stores/{LambderDdbIdempotency.d.ts → LambderDdbIdempotencyStore.d.ts} +41 -31
- package/dist/stores/LambderDdbIdempotencyStore.js +319 -0
- package/dist/stores/LambderDdbRateLimiter.d.ts +30 -49
- package/dist/stores/LambderDdbRateLimiter.js +47 -45
- package/dist/stores/LambderDdbSdk.d.ts +83 -6
- package/dist/stores/LambderDdbSdk.js +83 -2
- package/dist/stores/LambderDdbSessionStore.d.ts +65 -0
- package/dist/stores/LambderDdbSessionStore.js +161 -0
- package/dist/stores/LambderHttpFileSource.d.ts +1 -1
- package/dist/stores/LambderHttpFileSource.js +10 -1
- package/dist/stores/LambderLocalFileSource.d.ts +15 -0
- package/dist/stores/LambderLocalFileSource.js +28 -0
- package/dist/stores/LambderMemoryIdempotencyStore.d.ts +63 -0
- package/dist/stores/LambderMemoryIdempotencyStore.js +113 -0
- package/dist/stores/LambderMemoryRateLimiter.d.ts +34 -0
- package/dist/stores/LambderMemoryRateLimiter.js +64 -0
- package/dist/stores/LambderMemorySessionStore.d.ts +48 -0
- package/dist/stores/LambderMemorySessionStore.js +74 -0
- package/dist/stores/LambderS3FileSource.d.ts +1 -1
- package/dist/stores/LambderS3FileSource.js +1 -1
- package/package.json +26 -24
- package/dist/client/LambderMSW.d.ts +0 -69
- package/dist/client/LambderMSW.js +0 -121
- package/dist/policies/LambderApiGuards.d.ts +0 -256
- package/dist/policies/LambderApiGuards.js +0 -94
- package/dist/policies/LambderApiIdempotency.d.ts +0 -58
- package/dist/policies/LambderApiIdempotency.js +0 -219
- package/dist/policies/LambderApiPolicies.d.ts +0 -42
- package/dist/policies/LambderApiPolicies.js +0 -52
- package/dist/policies/LambderApiRateLimits.d.ts +0 -132
- package/dist/policies/LambderApiRateLimits.js +0 -119
- package/dist/shared/LambderApiContract.d.ts +0 -57
- package/dist/shared/LambderApiOutcome.d.ts +0 -69
- package/dist/shared/LambderCallOptions.d.ts +0 -71
- package/dist/shared/LambderCallOptions.js +0 -16
- package/dist/shared/node-polyfills.d.ts +0 -4
- package/dist/shared/node-polyfills.js +0 -58
- package/dist/stores/LambderDdbIdempotency.js +0 -229
- package/dist/testing.d.ts +0 -9
- package/dist/testing.js +0 -8
- /package/dist/shared/{LambderApiContract.js → wire/LambderApiContract.js} +0 -0
- /package/dist/{core → shared/wire}/LambderCookie.d.ts +0 -0
- /package/dist/{core → shared/wire}/LambderCookie.js +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The idempotency vocabulary every part of Lambder shares: what a stored
|
|
3
|
+
* answer looks like, what claiming a scope reports, and the four methods the
|
|
4
|
+
* idempotency engine asks of a store.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from the engine for the same reason LambderRateLimiter is:
|
|
7
|
+
* a store implements this and nothing else, and importing it from the engine
|
|
8
|
+
* would pull the engine (and through it the refusal machinery) into every
|
|
9
|
+
* store's import graph. Pure and dependency-free, so the mock runtime and the
|
|
10
|
+
* browser entry can resolve it.
|
|
11
|
+
*/
|
|
12
|
+
/** A stored answer: what a completed record replays. */
|
|
13
|
+
export type LambderIdempotencyDoneRecord = {
|
|
14
|
+
statusCode: number;
|
|
15
|
+
/** Response headers stored with the record (normalized multi-value map). */
|
|
16
|
+
headers: Record<string, string[]>;
|
|
17
|
+
body: string;
|
|
18
|
+
};
|
|
19
|
+
export type LambderIdempotencyBeginResult = {
|
|
20
|
+
state: "new";
|
|
21
|
+
ownerToken: string;
|
|
22
|
+
} | {
|
|
23
|
+
state: "pending";
|
|
24
|
+
} | ({
|
|
25
|
+
state: "done";
|
|
26
|
+
} & LambderIdempotencyDoneRecord);
|
|
27
|
+
/**
|
|
28
|
+
* What the idempotency engine asks of a store: one record per scope, claimed
|
|
29
|
+
* atomically, settled by the claim's owner. LambderDdbIdempotencyStore and
|
|
30
|
+
* LambderMemoryIdempotencyStore implement it; an app may bring its own.
|
|
31
|
+
*
|
|
32
|
+
* The rules an implementation has to keep are the ones tests/store-conformance
|
|
33
|
+
* asserts against every implementation, and the three that are easy to get
|
|
34
|
+
* wrong are worth naming here.
|
|
35
|
+
*
|
|
36
|
+
* A read hands back a COPY of the record, never the stored object, because a
|
|
37
|
+
* caller applies its own headers onto what it gets back.
|
|
38
|
+
*
|
|
39
|
+
* A write takes a copy too: complete() must not keep the caller's record or
|
|
40
|
+
* its headers map, because that object goes on being used after the call
|
|
41
|
+
* returns (the pipeline writes the call's own headers into it on the way
|
|
42
|
+
* out). A store that retained it would let one request's Set-Cookie become
|
|
43
|
+
* part of the stored answer and replay to everybody else. A store that goes
|
|
44
|
+
* over the wire gets this for free, since serializing IS the copy; one that
|
|
45
|
+
* keeps the record in the process has to make it.
|
|
46
|
+
*
|
|
47
|
+
* Size decides before ownership does, so an answer too big to store reports
|
|
48
|
+
* "too-large" even when the claim has meanwhile been lost. The engine
|
|
49
|
+
* releases the claim either way, so the order only shows in which reason it
|
|
50
|
+
* is told, but an implementation that inverted it would disagree with every
|
|
51
|
+
* other one.
|
|
52
|
+
*/
|
|
53
|
+
export interface LambderIdempotencyStore {
|
|
54
|
+
/** The stored answer when a completed, unexpired record exists, null otherwise (absent, pending, or expired). */
|
|
55
|
+
peek(scopeKey: string): Promise<LambderIdempotencyDoneRecord | null>;
|
|
56
|
+
/** Claims the scope: "new" with the ownerToken to settle with, "pending" when another request owns it, "done" with the answer to replay. */
|
|
57
|
+
begin(scopeKey: string, options: {
|
|
58
|
+
pendingTtlSeconds: number;
|
|
59
|
+
}): Promise<LambderIdempotencyBeginResult>;
|
|
60
|
+
/** Stores the answer over the claim: "stored", "too-large" (nothing written; release the claim), or "lost" (the claim expired and a retry took the scope). */
|
|
61
|
+
complete(scopeKey: string, ownerToken: string, record: LambderIdempotencyDoneRecord & {
|
|
62
|
+
ttlSeconds: number;
|
|
63
|
+
}): Promise<"stored" | "too-large" | "lost">;
|
|
64
|
+
/** Releases the claim without storing; a lost claim makes this a silent no-op. */
|
|
65
|
+
abandon(scopeKey: string, ownerToken: string): Promise<void>;
|
|
66
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The idempotency vocabulary every part of Lambder shares: what a stored
|
|
3
|
+
* answer looks like, what claiming a scope reports, and the four methods the
|
|
4
|
+
* idempotency engine asks of a store.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from the engine for the same reason LambderRateLimiter is:
|
|
7
|
+
* a store implements this and nothing else, and importing it from the engine
|
|
8
|
+
* would pull the engine (and through it the refusal machinery) into every
|
|
9
|
+
* store's import graph. Pure and dependency-free, so the mock runtime and the
|
|
10
|
+
* browser entry can resolve it.
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rate-limit vocabulary every part of Lambder shares: the fixed windows a
|
|
3
|
+
* policy may cap, the policy shape, what an exceeded check reports, and the
|
|
4
|
+
* one method the rate-limit engine asks of a limiter.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from the DynamoDB limiter on purpose. The engine needs only this
|
|
7
|
+
* table, and importing it from the store would pull the DynamoDB SDK loader
|
|
8
|
+
* into the engine's import graph, which is what kept the policy layer from
|
|
9
|
+
* running anywhere but inside a Lambda. Pure and dependency-free, so the
|
|
10
|
+
* mock runtime and the browser entry can resolve it.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The fixed windows a policy may cap, smallest first (the evaluation order),
|
|
14
|
+
* with their length. The policy type derives from this table, so the two can
|
|
15
|
+
* never drift.
|
|
16
|
+
*/
|
|
17
|
+
export declare const RATE_LIMIT_WINDOWS: readonly [{
|
|
18
|
+
readonly key: "perMin";
|
|
19
|
+
readonly seconds: 60;
|
|
20
|
+
}, {
|
|
21
|
+
readonly key: "per10Min";
|
|
22
|
+
readonly seconds: number;
|
|
23
|
+
}, {
|
|
24
|
+
readonly key: "perHour";
|
|
25
|
+
readonly seconds: number;
|
|
26
|
+
}, {
|
|
27
|
+
readonly key: "perDay";
|
|
28
|
+
readonly seconds: number;
|
|
29
|
+
}, {
|
|
30
|
+
readonly key: "perWeek";
|
|
31
|
+
readonly seconds: number;
|
|
32
|
+
}, {
|
|
33
|
+
readonly key: "perMonth";
|
|
34
|
+
readonly seconds: number;
|
|
35
|
+
}];
|
|
36
|
+
export type LambderRateLimitWindow = (typeof RATE_LIMIT_WINDOWS)[number]["key"];
|
|
37
|
+
/** Per-window caps. A window that is absent or 0 is not enforced. */
|
|
38
|
+
export type LambderRateLimitPolicy = Partial<Record<LambderRateLimitWindow, number>>;
|
|
39
|
+
/**
|
|
40
|
+
* The window that refused: which one, its limit, and the epoch second at
|
|
41
|
+
* which that fixed window resets (Retry-After derives from it).
|
|
42
|
+
*/
|
|
43
|
+
export type LambderRateLimitExceeded = {
|
|
44
|
+
window: LambderRateLimitWindow;
|
|
45
|
+
limit: number;
|
|
46
|
+
resetAt: number;
|
|
47
|
+
};
|
|
48
|
+
/** `false` when allowed, otherwise the window whose limit was hit. */
|
|
49
|
+
export type LambderRateLimitResult = false | LambderRateLimitExceeded;
|
|
50
|
+
/**
|
|
51
|
+
* What the rate-limit engine asks of a limiter: count one attempt against
|
|
52
|
+
* every window the policy caps and say whether any of them is over. The
|
|
53
|
+
* DynamoDB limiter and the in-memory one implement it; an app may bring its
|
|
54
|
+
* own (Redis, a database) by implementing this one method.
|
|
55
|
+
*
|
|
56
|
+
* The engine validates a policy before it ever reaches here, so every capped
|
|
57
|
+
* window arrives as a non-negative whole number and a limiter never has to
|
|
58
|
+
* invent an answer for a nonsense one. A caller reaching isRateLimited
|
|
59
|
+
* directly owes the same precondition: the two shipped implementations
|
|
60
|
+
* disagree on a negative cap (one refuses the first attempt, the other allows
|
|
61
|
+
* it) because neither was ever meant to be asked.
|
|
62
|
+
*
|
|
63
|
+
* The tracker key is bounded there too: the variable half of it (a custom
|
|
64
|
+
* key handler's return, a session key) is replaced by its own sha256 past
|
|
65
|
+
* 1024 UTF-8 bytes, so an implementation with a key limit of its own never
|
|
66
|
+
* meets a key it has to refuse. That matters because a limiter's refusal is a
|
|
67
|
+
* throw, and a throw is what failOpen swallows into no limit at all.
|
|
68
|
+
*/
|
|
69
|
+
export interface LambderRateLimiter {
|
|
70
|
+
isRateLimited(trackerKey: string, policy: LambderRateLimitPolicy): Promise<LambderRateLimitResult>;
|
|
71
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rate-limit vocabulary every part of Lambder shares: the fixed windows a
|
|
3
|
+
* policy may cap, the policy shape, what an exceeded check reports, and the
|
|
4
|
+
* one method the rate-limit engine asks of a limiter.
|
|
5
|
+
*
|
|
6
|
+
* Kept apart from the DynamoDB limiter on purpose. The engine needs only this
|
|
7
|
+
* table, and importing it from the store would pull the DynamoDB SDK loader
|
|
8
|
+
* into the engine's import graph, which is what kept the policy layer from
|
|
9
|
+
* running anywhere but inside a Lambda. Pure and dependency-free, so the
|
|
10
|
+
* mock runtime and the browser entry can resolve it.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The fixed windows a policy may cap, smallest first (the evaluation order),
|
|
14
|
+
* with their length. The policy type derives from this table, so the two can
|
|
15
|
+
* never drift.
|
|
16
|
+
*/
|
|
17
|
+
export const RATE_LIMIT_WINDOWS = [
|
|
18
|
+
{ key: "perMin", seconds: 60 },
|
|
19
|
+
{ key: "per10Min", seconds: 10 * 60 },
|
|
20
|
+
{ key: "perHour", seconds: 60 * 60 },
|
|
21
|
+
{ key: "perDay", seconds: 24 * 60 * 60 },
|
|
22
|
+
{ key: "perWeek", seconds: 7 * 24 * 60 * 60 },
|
|
23
|
+
{ key: "perMonth", seconds: 30 * 24 * 60 * 60 },
|
|
24
|
+
];
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session is at rest, and what the session manager asks of the place
|
|
3
|
+
* it rests in.
|
|
4
|
+
*
|
|
5
|
+
* The manager owns the model (token format, hashing, expiry, sliding
|
|
6
|
+
* writes, dataRefresh, regeneration); a store owns nothing but the five
|
|
7
|
+
* operations below, keyed by the two hashes. LambderDdbSessionStore is the
|
|
8
|
+
* DynamoDB implementation and LambderMemorySessionStore the in-memory one;
|
|
9
|
+
* an app may bring its own (Redis, a database) by implementing this
|
|
10
|
+
* interface. Records written by one store read back through another with
|
|
11
|
+
* the same shape, because the shape is the manager's, not the store's.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* A session record. The two hashes are the record's identity: the partition
|
|
15
|
+
* is a salted hash of the app's sessionKey (a user id, say) and the sort key
|
|
16
|
+
* is a hash of the bearer secret the client holds. The raw secrets are never
|
|
17
|
+
* stored, so a read of the store yields no usable credentials.
|
|
18
|
+
*/
|
|
19
|
+
export type LambderSessionRecord<SessionData = unknown> = {
|
|
20
|
+
/** Salted sha256 of the sessionKey: the partition every session of one subject shares. */
|
|
21
|
+
sessionKeyHash: string;
|
|
22
|
+
/** sha256 of the sort-key secret the client's session cookie carries. */
|
|
23
|
+
secretHash: string;
|
|
24
|
+
/** sha256 of the raw CSRF token the client's csrf cookie carries. */
|
|
25
|
+
csrfTokenHash: string;
|
|
26
|
+
/** The app's own key for the subject (a user id), as given to createSession. */
|
|
27
|
+
sessionKey: string;
|
|
28
|
+
data: SessionData;
|
|
29
|
+
/** Epoch seconds. */
|
|
30
|
+
createdAt: number;
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
lastAccessedAt: number;
|
|
33
|
+
ttlInSeconds: number;
|
|
34
|
+
/**
|
|
35
|
+
* When `data` must be renewed via the dataRefresh callback (epoch seconds).
|
|
36
|
+
* Only present when dataRefresh is configured; independent of the
|
|
37
|
+
* session's own expiresAt.
|
|
38
|
+
*/
|
|
39
|
+
dataExpiresAt?: number;
|
|
40
|
+
};
|
|
41
|
+
export interface LambderSessionStore<SessionData = unknown> {
|
|
42
|
+
/**
|
|
43
|
+
* Whether records live only for as long as this process does. The session
|
|
44
|
+
* manager reads it to refuse a non-cryptographic LambderSessionCrypto
|
|
45
|
+
* over a store that outlives the process: hashing that is not hashing is
|
|
46
|
+
* survivable in memory for a development run and never survivable at
|
|
47
|
+
* rest, where the records would be usable credentials.
|
|
48
|
+
*/
|
|
49
|
+
readonly isMemoryOnly: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* The record under the two hashes, or null. A failing read throws; the
|
|
52
|
+
* manager wraps it as a LambderSessionReadError.
|
|
53
|
+
*
|
|
54
|
+
* A store MAY hand back a record that is past its expiresAt: a DynamoDB
|
|
55
|
+
* TTL deletes within days rather than at the second, and an implementation
|
|
56
|
+
* over a plain table has nothing that sweeps at all. Expiry is the
|
|
57
|
+
* manager's to enforce, and it does, on every read. A store that drops
|
|
58
|
+
* expired records itself is doing housekeeping, not policy.
|
|
59
|
+
*/
|
|
60
|
+
get(sessionKeyHash: string, secretHash: string): Promise<LambderSessionRecord<SessionData> | null>;
|
|
61
|
+
/** Writes the record, replacing any under the same hashes. */
|
|
62
|
+
put(record: LambderSessionRecord<SessionData>): Promise<void>;
|
|
63
|
+
delete(sessionKeyHash: string, secretHash: string): Promise<void>;
|
|
64
|
+
/** Every secretHash stored under the partition: the sessions of one subject. */
|
|
65
|
+
listSecretHashes(sessionKeyHash: string): Promise<string[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Stamps dataExpiresAt on one record, only if it still exists: neither
|
|
68
|
+
* resurrects a session deleted in between nor overwrites a concurrent
|
|
69
|
+
* write. A record that no longer exists is skipped silently.
|
|
70
|
+
*/
|
|
71
|
+
markDataExpired(sessionKeyHash: string, secretHash: string, at: number): Promise<void>;
|
|
72
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a session is at rest, and what the session manager asks of the place
|
|
3
|
+
* it rests in.
|
|
4
|
+
*
|
|
5
|
+
* The manager owns the model (token format, hashing, expiry, sliding
|
|
6
|
+
* writes, dataRefresh, regeneration); a store owns nothing but the five
|
|
7
|
+
* operations below, keyed by the two hashes. LambderDdbSessionStore is the
|
|
8
|
+
* DynamoDB implementation and LambderMemorySessionStore the in-memory one;
|
|
9
|
+
* an app may bring its own (Redis, a database) by implementing this
|
|
10
|
+
* interface. Records written by one store read back through another with
|
|
11
|
+
* the same shape, because the shape is the manager's, not the store's.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { LambderApiHttpAnswer } from "../wire/LambderApiOutcome.js";
|
|
2
|
+
import type { LambderCompressedGzipPayload, LambderCompressedBrotliPayload } from "../wire/LambderRequestPayload.js";
|
|
3
|
+
/**
|
|
4
|
+
* What LambderCaller hands its transport: the envelope fields of one call
|
|
5
|
+
* plus what a transport may need beside them. Cookies and the client IP are
|
|
6
|
+
* for transports that build the request themselves (in-process, mock); the
|
|
7
|
+
* browser's fetch attaches its own cookies and ignores both.
|
|
8
|
+
*/
|
|
9
|
+
export type LambderApiTransportRequest = {
|
|
10
|
+
apiPath: string;
|
|
11
|
+
apiName: string;
|
|
12
|
+
version?: string;
|
|
13
|
+
/** The CSRF token the caller read from its cookie; "" when it holds none. */
|
|
14
|
+
token: string;
|
|
15
|
+
/**
|
|
16
|
+
* The cookie name the caller reads that token from. A transport that
|
|
17
|
+
* fills the token in itself (the cookie-jar decorator, where there is no
|
|
18
|
+
* document to read) needs the same name, and taking it from the caller is
|
|
19
|
+
* what keeps the two from being configured apart.
|
|
20
|
+
*/
|
|
21
|
+
csrfCookieKey?: string;
|
|
22
|
+
siteHost: string;
|
|
23
|
+
/** The payload, when it goes plainly. */
|
|
24
|
+
payload?: unknown;
|
|
25
|
+
/** The compressed pair, when it goes compressed instead of `payload`. */
|
|
26
|
+
compressed?: LambderCompressedGzipPayload | LambderCompressedBrotliPayload;
|
|
27
|
+
guardInputs?: Record<string, unknown>;
|
|
28
|
+
idempotencyKey?: string;
|
|
29
|
+
headers?: Record<string, string>;
|
|
30
|
+
/** Cookie header pairs, `name=value`. */
|
|
31
|
+
cookies?: string[];
|
|
32
|
+
clientIp?: string;
|
|
33
|
+
signal?: AbortSignal;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Why a transport could not deliver a call. `network` is the default reading
|
|
37
|
+
* of a rejection: nothing came back. `protocol` says the call reached the
|
|
38
|
+
* callee and no answer came of it, either because what came back was not one
|
|
39
|
+
* or because the callee threw instead of answering, which is a server or
|
|
40
|
+
* wiring fault and should not be reported to a developer as flaky
|
|
41
|
+
* connectivity. `timeout` belongs to the caller, which knows whether its own
|
|
42
|
+
* abort fired.
|
|
43
|
+
*/
|
|
44
|
+
export type LambderTransportFailureReason = "network" | "protocol";
|
|
45
|
+
/**
|
|
46
|
+
* A transport saying why it failed, instead of leaving the caller to assume.
|
|
47
|
+
* Thrown by a transport; the caller reads `reason` and keeps `cause`, so the
|
|
48
|
+
* thing that actually went wrong survives the trip.
|
|
49
|
+
*/
|
|
50
|
+
export declare class LambderTransportFailure extends Error {
|
|
51
|
+
readonly isLambderTransportFailure: true;
|
|
52
|
+
readonly reason: LambderTransportFailureReason;
|
|
53
|
+
constructor(reason: LambderTransportFailureReason, message: string, options?: {
|
|
54
|
+
cause?: unknown;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/** Brand-based type guard, so a duplicate install of the package still matches. */
|
|
58
|
+
export declare const isLambderTransportFailure: (err: unknown) => err is LambderTransportFailure;
|
|
59
|
+
/**
|
|
60
|
+
* Delivers one call and hands back the answer in the accessor form
|
|
61
|
+
* resolveApiOutcome() reads. What a transport owes its caller, since nothing
|
|
62
|
+
* but this contract stands between a call and a wrong outcome:
|
|
63
|
+
*
|
|
64
|
+
* - **Any HTTP status is an answer.** A 4xx or 5xx resolves, status and body
|
|
65
|
+
* included, because resolveApiOutcome() is the one place that reads what a
|
|
66
|
+
* status means. A transport that rejects on a status throws away the
|
|
67
|
+
* envelope a refusal, a validation failure or a crash arrived in.
|
|
68
|
+
* - **A rejection is a transport failure.** The caller reports it as
|
|
69
|
+
* `network` unless the transport threw a LambderTransportFailure naming
|
|
70
|
+
* another reason, or `timeout` when the caller's own abort fired. That is
|
|
71
|
+
* the channel for the real cause too: a LambderTransportFailure keeps it as
|
|
72
|
+
* `cause`, where the caller's `outcome.error` carries it.
|
|
73
|
+
* - **`request.signal` must be honoured**, by rejecting as soon as it aborts.
|
|
74
|
+
* It is the only thing that makes the caller's `timeoutMs` and its per-call
|
|
75
|
+
* `signal` mean anything: a transport that ignores it leaves a call waiting
|
|
76
|
+
* for as long as the callee takes, whatever the caller asked for. Work
|
|
77
|
+
* already begun need not be cancellable (an in-process handler is not); the
|
|
78
|
+
* obligation is to stop waiting, not to stop the callee.
|
|
79
|
+
* - **Timeouts and retries belong to the caller.** A transport starts no
|
|
80
|
+
* clock of its own and retries nothing, so one call is one delivery
|
|
81
|
+
* attempt and an idempotency key means what it says.
|
|
82
|
+
*
|
|
83
|
+
* Four transports ship: fetch (lambderFetchTransport, the browser default),
|
|
84
|
+
* an in-process Lambder handler (lambderHandlerTransport, for tests), the
|
|
85
|
+
* mock runtime (LambderMockApp.transport), and a cookie-jar decorator over
|
|
86
|
+
* any of them (lambderCookieJarTransport).
|
|
87
|
+
*/
|
|
88
|
+
export type LambderApiTransport = (request: LambderApiTransportRequest) => Promise<LambderApiHttpAnswer>;
|
|
89
|
+
/**
|
|
90
|
+
* The fields of the request envelope, in the order they go on the wire: the
|
|
91
|
+
* one statement of what a call sends, for every sender there is.
|
|
92
|
+
*
|
|
93
|
+
* Two senders write it. A transport hands the payload over as a value
|
|
94
|
+
* (buildTransportEnvelope, below); LambderInvokeCaller has already serialized
|
|
95
|
+
* its payload to decide whether to compress it, and splices that JSON onto the
|
|
96
|
+
* end rather than parsing and stringifying it a second time
|
|
97
|
+
* (buildEnvelopeJson, in invoke/LambderLambdaEvent.ts). The splice sits on top
|
|
98
|
+
* of this function precisely so that a new envelope field cannot be added to
|
|
99
|
+
* one sender and missed by the other, which nothing on the wire would catch.
|
|
100
|
+
*/
|
|
101
|
+
export declare const buildEnvelopeFields: (fields: {
|
|
102
|
+
apiName: string;
|
|
103
|
+
version?: string;
|
|
104
|
+
/** The CSRF token, as the envelope names it. */
|
|
105
|
+
token: string;
|
|
106
|
+
siteHost: string;
|
|
107
|
+
/**
|
|
108
|
+
* The plain payload's slot: `{ payload }` from a sender holding the value,
|
|
109
|
+
* and nothing from one that splices its own JSON in afterwards. A
|
|
110
|
+
* compressed payload replaces it.
|
|
111
|
+
*/
|
|
112
|
+
payloadSlot?: {
|
|
113
|
+
payload: unknown;
|
|
114
|
+
};
|
|
115
|
+
compressed?: LambderCompressedGzipPayload | LambderCompressedBrotliPayload | null;
|
|
116
|
+
guardInputs?: Record<string, unknown>;
|
|
117
|
+
idempotencyKey?: string;
|
|
118
|
+
}) => Record<string, unknown>;
|
|
119
|
+
/**
|
|
120
|
+
* The body envelope every transport posts, as a plain object: the same
|
|
121
|
+
* fields whichever transport carries them, so the server and the mock
|
|
122
|
+
* runtime read one shape.
|
|
123
|
+
*/
|
|
124
|
+
export declare const buildTransportEnvelope: (request: LambderApiTransportRequest) => Record<string, unknown>;
|
|
125
|
+
/**
|
|
126
|
+
* Where a call is actually going, read off its apiPath: an absolute one names
|
|
127
|
+
* the host and the scheme the request reaches, a relative one only its path.
|
|
128
|
+
* Both the cookie-jar decorator (a cookie's scope is the host and path of the
|
|
129
|
+
* request, not of the page) and the in-process handler transport (whose event
|
|
130
|
+
* needs a path, not a URL, or no route matches) split it this way.
|
|
131
|
+
*/
|
|
132
|
+
type LambderApiPathTarget = {
|
|
133
|
+
host?: string;
|
|
134
|
+
path: string;
|
|
135
|
+
/** Whether the target speaks https; undefined when the apiPath names no scheme. */
|
|
136
|
+
secure?: boolean;
|
|
137
|
+
};
|
|
138
|
+
export declare const resolveApiPathTarget: (apiPath: string) => LambderApiPathTarget;
|
|
139
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A transport saying why it failed, instead of leaving the caller to assume.
|
|
3
|
+
* Thrown by a transport; the caller reads `reason` and keeps `cause`, so the
|
|
4
|
+
* thing that actually went wrong survives the trip.
|
|
5
|
+
*/
|
|
6
|
+
export class LambderTransportFailure extends Error {
|
|
7
|
+
isLambderTransportFailure = true;
|
|
8
|
+
reason;
|
|
9
|
+
constructor(reason, message, options = {}) {
|
|
10
|
+
super(message, options.cause !== undefined ? { cause: options.cause } : undefined);
|
|
11
|
+
this.name = "LambderTransportFailure";
|
|
12
|
+
this.reason = reason;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/** Brand-based type guard, so a duplicate install of the package still matches. */
|
|
16
|
+
export const isLambderTransportFailure = (err) => err instanceof Error && err.isLambderTransportFailure === true;
|
|
17
|
+
/**
|
|
18
|
+
* The fields of the request envelope, in the order they go on the wire: the
|
|
19
|
+
* one statement of what a call sends, for every sender there is.
|
|
20
|
+
*
|
|
21
|
+
* Two senders write it. A transport hands the payload over as a value
|
|
22
|
+
* (buildTransportEnvelope, below); LambderInvokeCaller has already serialized
|
|
23
|
+
* its payload to decide whether to compress it, and splices that JSON onto the
|
|
24
|
+
* end rather than parsing and stringifying it a second time
|
|
25
|
+
* (buildEnvelopeJson, in invoke/LambderLambdaEvent.ts). The splice sits on top
|
|
26
|
+
* of this function precisely so that a new envelope field cannot be added to
|
|
27
|
+
* one sender and missed by the other, which nothing on the wire would catch.
|
|
28
|
+
*/
|
|
29
|
+
export const buildEnvelopeFields = (fields) => ({
|
|
30
|
+
apiName: fields.apiName,
|
|
31
|
+
version: fields.version,
|
|
32
|
+
token: fields.token,
|
|
33
|
+
siteHost: fields.siteHost,
|
|
34
|
+
...(fields.compressed ?? fields.payloadSlot ?? {}),
|
|
35
|
+
...(fields.guardInputs !== undefined ? { guardInputs: fields.guardInputs } : {}),
|
|
36
|
+
...(fields.idempotencyKey !== undefined ? { idempotencyKey: fields.idempotencyKey } : {}),
|
|
37
|
+
});
|
|
38
|
+
/**
|
|
39
|
+
* The body envelope every transport posts, as a plain object: the same
|
|
40
|
+
* fields whichever transport carries them, so the server and the mock
|
|
41
|
+
* runtime read one shape.
|
|
42
|
+
*/
|
|
43
|
+
export const buildTransportEnvelope = (request) => buildEnvelopeFields({
|
|
44
|
+
apiName: request.apiName,
|
|
45
|
+
version: request.version,
|
|
46
|
+
token: request.token,
|
|
47
|
+
siteHost: request.siteHost,
|
|
48
|
+
payloadSlot: { payload: request.payload },
|
|
49
|
+
compressed: request.compressed,
|
|
50
|
+
guardInputs: request.guardInputs,
|
|
51
|
+
idempotencyKey: request.idempotencyKey,
|
|
52
|
+
});
|
|
53
|
+
export const resolveApiPathTarget = (apiPath) => {
|
|
54
|
+
// Only an absolute URL carries a host. Parsing "/api" would need a base,
|
|
55
|
+
// and inventing one invents a host to go with it.
|
|
56
|
+
if (!/^https?:\/\//i.test(apiPath))
|
|
57
|
+
return { path: apiPath };
|
|
58
|
+
try {
|
|
59
|
+
const url = new URL(apiPath);
|
|
60
|
+
return { host: url.hostname, path: url.pathname, secure: url.protocol === "https:" };
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return { path: apiPath };
|
|
64
|
+
}
|
|
65
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The cookie jar a transport carries (LambderCookieJar), and the Set-Cookie
|
|
3
|
+
* parsing behind it. tough-cookie is reached from this module and no other, so
|
|
4
|
+
* a bundle that never carries a jar drops it.
|
|
5
|
+
*/
|
|
6
|
+
/** A cookie as the jar holds it. Epoch milliseconds for `expires`, and `host` set only for a host-only cookie. */
|
|
7
|
+
export type LambderStoredCookie = {
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
/** The Domain attribute, without its leading dot; undefined for a host-only cookie. */
|
|
11
|
+
domain: string | undefined;
|
|
12
|
+
/** The host that set it, when it carried no Domain. Absent when the jar never learned a host. */
|
|
13
|
+
host?: string;
|
|
14
|
+
path: string;
|
|
15
|
+
/** Epoch milliseconds; undefined for a browser-session cookie. */
|
|
16
|
+
expires: number | undefined;
|
|
17
|
+
httpOnly: boolean;
|
|
18
|
+
/** Withheld from a target known to be plain http; a target of unknown scheme (in-process, mock) still carries it. */
|
|
19
|
+
secure: boolean;
|
|
20
|
+
};
|
|
21
|
+
/** Where a call is going, as far as a cookie's scope is concerned. An absent field is one the caller could not know, and matches anything. */
|
|
22
|
+
type LambderCookieTarget = {
|
|
23
|
+
host?: string;
|
|
24
|
+
path?: string;
|
|
25
|
+
/** False only for a target known to speak plain http, which neither accepts a Secure cookie nor sends one. */
|
|
26
|
+
secure?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* One Set-Cookie header value, read the way a browser reads it. `requestPath`
|
|
30
|
+
* is the path the answer came from, which decides the default Path. Returns
|
|
31
|
+
* null for a header no browser would keep.
|
|
32
|
+
*/
|
|
33
|
+
export declare const parseSetCookie: (header: string, now: number, requestPath?: string) => LambderStoredCookie | null;
|
|
34
|
+
/**
|
|
35
|
+
* A browser's cookie storage, for transports that have no browser: the
|
|
36
|
+
* in-process handler transport in a Node test, and the mock runtime's direct
|
|
37
|
+
* transport. It stores what an answer's Set-Cookie headers set, honours their
|
|
38
|
+
* expiry and deletion, and hands back the Cookie pairs the next request should
|
|
39
|
+
* carry. One jar is one browser; two jars are two.
|
|
40
|
+
*
|
|
41
|
+
* The rules themselves are tough-cookie's, which is the reference
|
|
42
|
+
* implementation of RFC 6265 and carries the public suffix list: domain and
|
|
43
|
+
* path matching, default-path, Max-Age against Expires, Secure, HttpOnly, and
|
|
44
|
+
* the __Host-/__Secure- prefixes. That list is the part worth importing rather
|
|
45
|
+
* than writing. A hand-rolled check can tell that `Domain=com` is a registry
|
|
46
|
+
* suffix by counting labels, and cannot tell that `co.uk` is one, so a
|
|
47
|
+
* hand-rolled jar either trusts `Domain=co.uk` or bans every two-label domain.
|
|
48
|
+
*
|
|
49
|
+
* What stays Lambder's is the shape of the questions a transport asks: whole
|
|
50
|
+
* Set-Cookie header lists in (storeSetCookies), `name=value` pairs out
|
|
51
|
+
* (cookiePairs), and a target given as a host and path rather than a URL,
|
|
52
|
+
* since a transport that never speaks HTTP has no URL to give. A field the
|
|
53
|
+
* caller omits is one it could not know, and an unknown field matches
|
|
54
|
+
* anything: a jar pointed at a single host is the ordinary case, and refusing
|
|
55
|
+
* to answer it until it can name that host would make the common setup the
|
|
56
|
+
* awkward one.
|
|
57
|
+
*
|
|
58
|
+
* SameSite is stored but never consulted. It answers "did another site
|
|
59
|
+
* initiate this", and a transport call has no initiating site: every call here
|
|
60
|
+
* is same-site by construction.
|
|
61
|
+
*/
|
|
62
|
+
export declare class LambderCookieJar {
|
|
63
|
+
private readonly jar;
|
|
64
|
+
private readonly now;
|
|
65
|
+
private readonly host;
|
|
66
|
+
/** `host` is the host this jar is the browser of: the sender of every answer and the target of every request that names none. */
|
|
67
|
+
constructor(options?: {
|
|
68
|
+
now?: () => number;
|
|
69
|
+
host?: string;
|
|
70
|
+
});
|
|
71
|
+
/** The host a call is about, or the stand-in when neither the call nor the jar names one. */
|
|
72
|
+
private hostFor;
|
|
73
|
+
/**
|
|
74
|
+
* Applies Set-Cookie header values as a browser would: stores, replaces,
|
|
75
|
+
* and deletes on an expiry in the past. `request` says where the answer
|
|
76
|
+
* came from. Its `host` is the sending host, which every Domain is checked
|
|
77
|
+
* against, and its `path` is the default Path of a cookie that names none.
|
|
78
|
+
*
|
|
79
|
+
* A Domain the sender is not under does not narrow a cookie, it voids it
|
|
80
|
+
* (RFC 6265 section 5.3 step 6), and so does a Domain that is a public
|
|
81
|
+
* suffix. Both are how evil.example.com would otherwise plant a cookie
|
|
82
|
+
* that bank.example.com is handed on the next call.
|
|
83
|
+
*/
|
|
84
|
+
storeSetCookies(headers: readonly string[], request?: LambderCookieTarget): void;
|
|
85
|
+
/** Every live cookie. */
|
|
86
|
+
list(): LambderStoredCookie[];
|
|
87
|
+
/**
|
|
88
|
+
* The Cookie header pairs the next request carries, as `name=value`, in
|
|
89
|
+
* the order RFC 6265 section 5.4 puts them in: the longest Path first,
|
|
90
|
+
* and among equal paths the one set first. Servers that read only the
|
|
91
|
+
* first value of a repeated name depend on that order, and so does any
|
|
92
|
+
* test reasoning about which of two same-named cookies wins.
|
|
93
|
+
*
|
|
94
|
+
* Only the cookies whose scope covers the target travel. A field the
|
|
95
|
+
* target leaves out is one the caller could not know, and matches
|
|
96
|
+
* anything: a caller that cannot name its own host still gets the cookies
|
|
97
|
+
* of the one host its jar talks to.
|
|
98
|
+
*/
|
|
99
|
+
cookiePairs(target?: LambderCookieTarget): string[];
|
|
100
|
+
/**
|
|
101
|
+
* One cookie's value as a page's script would read it: HttpOnly cookies
|
|
102
|
+
* are invisible unless asked for, which is how the transport fills in the
|
|
103
|
+
* CSRF token the caller would have read from document.cookie.
|
|
104
|
+
*/
|
|
105
|
+
get(name: string, options?: {
|
|
106
|
+
includeHttpOnly?: boolean;
|
|
107
|
+
} & LambderCookieTarget): string | undefined;
|
|
108
|
+
/**
|
|
109
|
+
* The live cookies whose scope reaches this target, in RFC 6265 send
|
|
110
|
+
* order. Delegated to tough-cookie whenever the target names a host,
|
|
111
|
+
* which is the case worth getting exactly right; an unnamed host falls
|
|
112
|
+
* back to every cookie the jar holds, filtered by the rules that do not
|
|
113
|
+
* need one and ordered by the same rule.
|
|
114
|
+
*/
|
|
115
|
+
private matchingCookies;
|
|
116
|
+
/** Number of live cookies. */
|
|
117
|
+
get size(): number;
|
|
118
|
+
/** Forgets every cookie: the browser's storage cleared. */
|
|
119
|
+
clear(): void;
|
|
120
|
+
}
|
|
121
|
+
export {};
|