lambder 11.1.1 → 13.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 +217 -0
- package/README.md +25 -15
- package/dist/api/LambderApiAnswer.d.ts +7 -0
- package/dist/api/LambderApiDeclarations.d.ts +194 -0
- package/dist/api/LambderApiDeclarations.js +52 -0
- package/dist/api/LambderApiDefinition.d.ts +1 -1
- package/dist/api/LambderApiEnvelope.js +4 -1
- package/dist/api/LambderApiGuards.d.ts +21 -22
- package/dist/api/LambderApiGuards.js +1 -1
- package/dist/api/LambderApiRateLimits.d.ts +19 -19
- package/dist/api/LambderApiRateLimits.js +1 -1
- package/dist/api/LambderApiRefusals.d.ts +22 -0
- package/dist/api/LambderApiRefusals.js +13 -0
- package/dist/api/LambderApiRequest.d.ts +15 -6
- package/dist/api/LambderApiRequest.js +8 -9
- package/dist/build/generateApiFiles.d.ts +60 -0
- package/dist/build/generateApiFiles.js +85 -0
- package/dist/build/generatedTables.d.ts +2 -1
- package/dist/build/generatedTables.js +1 -1
- package/dist/build.d.ts +4 -1
- package/dist/build.js +3 -1
- package/dist/client/LambderCaller.d.ts +36 -23
- package/dist/client/LambderCaller.js +88 -67
- package/dist/client/lambderFetchTransport.js +2 -1
- package/dist/client.d.ts +3 -1
- package/dist/client.js +2 -0
- package/dist/core/Lambder.d.ts +232 -92
- package/dist/core/Lambder.js +400 -103
- package/dist/core/LambderCallSummary.d.ts +43 -0
- package/dist/core/LambderCallSummary.js +10 -0
- package/dist/core/LambderContext.d.ts +15 -2
- package/dist/core/LambderContext.js +32 -9
- package/dist/core/LambderCreateOptions.d.ts +78 -64
- package/dist/core/LambderCreateOptions.js +39 -21
- package/dist/core/LambderInvocationScope.d.ts +25 -0
- package/dist/core/LambderInvocationScope.js +21 -0
- package/dist/core/LambderResponse.d.ts +11 -0
- package/dist/core/LambderResponse.js +12 -0
- package/dist/core/LambderResponseBuilder.js +5 -1
- package/dist/index.d.ts +13 -7
- package/dist/index.js +3 -1
- package/dist/invoke/LambderInvokeCaller.d.ts +48 -31
- package/dist/invoke/LambderInvokeCaller.js +110 -94
- package/dist/invoke/LambderLambdaEvent.d.ts +2 -1
- package/dist/invoke/LambderLambdaEvent.js +8 -3
- package/dist/invoke/lambderHandlerTransport.js +2 -1
- package/dist/mock/LambderMockApp.d.ts +39 -33
- package/dist/mock/LambderMockApp.js +66 -55
- package/dist/mock/LambderMockCreateOptions.d.ts +8 -10
- package/dist/mock/LambderMockTypes.d.ts +44 -7
- package/dist/mock/lambderMockInvokeTransport.d.ts +9 -1
- package/dist/mock/lambderMockInvokeTransport.js +15 -7
- package/dist/mock/lambderMockMswHandler.js +8 -4
- package/dist/mock.d.ts +2 -2
- package/dist/session/LambderSessionManager.d.ts +46 -3
- package/dist/session/LambderSessionManager.js +62 -11
- package/dist/shared/LambderI18n.js +49 -4
- package/dist/shared/contracts/LambderRateLimiter.d.ts +2 -2
- package/dist/shared/contracts/LambderRateLimiter.js +2 -2
- package/dist/shared/transport/LambderApiTransport.d.ts +3 -2
- package/dist/shared/transport/LambderApiTransport.js +2 -3
- package/dist/shared/transport/lambderCookieJarTransport.js +2 -1
- package/dist/shared/util/LambderInvocationScope.d.ts +10 -0
- package/dist/shared/util/LambderInvocationScope.js +5 -0
- package/dist/shared/util/LambderNamedMaps.d.ts +22 -0
- package/dist/shared/util/LambderNamedMaps.js +19 -0
- package/dist/shared/util/LambderTypeUtilities.d.ts +1 -1
- package/dist/shared/wire/LambderApiContract.d.ts +4 -18
- package/dist/shared/wire/LambderApiContract.js +1 -1
- package/dist/shared/wire/LambderApiGroupCalls.d.ts +31 -0
- package/dist/shared/wire/LambderApiGroupCalls.js +68 -0
- package/dist/shared/wire/LambderApiNames.d.ts +55 -0
- package/dist/shared/wire/LambderApiNames.js +81 -0
- package/dist/shared/wire/LambderCallOutcome.d.ts +27 -0
- package/dist/shared/wire/LambderCallOutcome.js +47 -0
- package/dist/shared/wire/LambderInvokeApiId.d.ts +10 -0
- package/dist/shared/wire/LambderInvokeApiId.js +10 -0
- package/dist/shared/wire/LambderUploadSchemas.js +2 -1
- package/dist/stores/LambderDdbRateLimiter.d.ts +24 -16
- package/dist/stores/LambderDdbRateLimiter.js +64 -45
- package/dist/stores/LambderMemoryRateLimiter.d.ts +9 -4
- package/dist/stores/LambderMemoryRateLimiter.js +20 -15
- package/dist/testing/LambderTestApp.d.ts +18 -5
- package/dist/testing/LambderTestApp.js +21 -5
- package/dist/testing/LambderTestVisitor.d.ts +16 -8
- package/dist/testing/LambderTestVisitor.js +33 -25
- package/package.json +1 -1
package/dist/core/Lambder.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { LambderFiles } from "./LambderFiles.js";
|
|
|
12
12
|
import { type LambderPipelineBackends, type LambderPipelineBackendSwap } from "../api/LambderApiPipeline.js";
|
|
13
13
|
import type { LambderFileSource } from "../shared/contracts/LambderFileSource.js";
|
|
14
14
|
import { LAMBDER_BACKEND_SWAP, LAMBDER_CRASH_WATCH } from "../shared/util/LambderTestingDoors.js";
|
|
15
|
-
import { type LambderWireRefusalsOf, type LambderHandlerRefusalsOf, type LambderRefusalNamesIn, type LambderRefusalsOption, type
|
|
15
|
+
import { type LambderWireRefusalsOf, type LambderHandlerRefusalsOf, type LambderRefusalNamesIn, type LambderRefusalsOption, type LambderRefusalVocabularyOption, type LambderRefusalVocabularyOptionChecks, type LambderMergedRefusalVocabulary } from "../api/LambderApiRefusals.js";
|
|
16
16
|
import { type LambderDeclaredRefuse } from "../shared/wire/LambderApiRefusal.js";
|
|
17
17
|
import { type LambderApiSignatureEntry } from "../api/LambderApiSignature.js";
|
|
18
18
|
import { type LambderApiSignatureMap } from "../shared/wire/LambderApiSignatureMap.js";
|
|
@@ -21,13 +21,17 @@ import type { LambderApiIdempotencyOption } from "../shared/wire/LambderApiOptio
|
|
|
21
21
|
import type { LambderApiGuard, LambderGuardMetaMap, LambderGuardsOption, LambderGuardDataOf, LambderGuardInputsOf, LambderGuardRefusalNamesOf } from "../api/LambderApiGuards.js";
|
|
22
22
|
import type { LambderApiRateLimitPolicyConfig, LambderRateLimitOption } from "../api/LambderApiRateLimits.js";
|
|
23
23
|
import type { LambderApiIdempotencyConfig } from "../api/LambderApiIdempotency.js";
|
|
24
|
-
import type { LambderContractEntry, LambderJsonOf
|
|
24
|
+
import type { LambderContractEntry, LambderJsonOf } from "../shared/wire/LambderApiContract.js";
|
|
25
|
+
import { type LambderActionNamesCheck, type LambderApiDeclaration, type LambderApiDeclarations, type LambderApiGroup, type LambderApiModeOf, type LambderAppTypes, type LambderContractOfGroups, type LambderGroupNameCheck, type LambderGroupPartsCheck, type LambderMergedParts, type LambderLazyApiGroup, type LambderPlainAppTypes, type LambderPublicSessionPolicyCheck, type LambderRegisteredGroupsCheck, type LambderRegistrableApiGroup, type LambderSessionModeCheck } from "../api/LambderApiDeclarations.js";
|
|
25
26
|
import { type LambderHttpEvent, type LambderRenderContext, type LambderSessionRenderContext } from "./LambderContext.js";
|
|
26
27
|
import type { LambderReadonlyDeep, MaybePromise } from "../shared/util/LambderTypeUtilities.js";
|
|
28
|
+
import { type LambderCallSummary } from "./LambderCallSummary.js";
|
|
27
29
|
import { type LambderMergedNamedMaps, type LambderNamedMapsOption, type LambderRouteHandler, type LambderInputValidationHandler, type LambderFallbackHandler, type LambderGlobalErrorHandler, type LambderAfterRenderHook, type LambderBeforeRenderHook, type LambderFallbackHook, type LambderActionTools, type LambderCreateOptions, type LambderGivenOption, type LambderHandler, type LambderNestedOptionChecks, type LambderObjectOutputCheck, type LambderPayloadSliceCheck, type LambderRequirableGuardsField, type LambderSessionEnabledInstance, type LambderSessionRouteHandler } from "./LambderCreateOptions.js";
|
|
28
30
|
/** Everything `lambder/testing` may put under a built instance: the pipeline's stores, and the source its files are read from. */
|
|
29
31
|
export type LambderInstanceBackends = LambderPipelineBackends & {
|
|
30
32
|
fileSource?: LambderFileSource;
|
|
33
|
+
/** Where call summaries go instead of the app's own callSummary; null writes none. */
|
|
34
|
+
callSummary?: ((summary: LambderCallSummary) => void) | null;
|
|
31
35
|
};
|
|
32
36
|
/** What the instance had a place for; see LambderPipelineBackendSwap. `files` is false on an instance created without the files option. */
|
|
33
37
|
export type LambderInstanceBackendSwap = LambderPipelineBackendSwap & {
|
|
@@ -39,36 +43,41 @@ export type LambderInstanceBackendSwap = LambderPipelineBackendSwap & {
|
|
|
39
43
|
* because its parameter is the class, and an options module that names the
|
|
40
44
|
* class cannot be read without it.
|
|
41
45
|
*/
|
|
42
|
-
export type LambderCreatedHook = (lambderInstance: Lambder<any, any
|
|
46
|
+
export type LambderCreatedHook = (lambderInstance: Lambder<any, any>) => void | Promise<void>;
|
|
43
47
|
/** The codes one API may refuse with, typed: its own refusals option's and its declared guards', as the vocabulary holds them. */
|
|
44
48
|
type LambderApiRefusalCodes<TVocabulary, TGuards, TRefusalsOpt, TGuardsOpt> = (LambderRefusalNamesIn<TRefusalsOpt> | LambderGuardRefusalNamesOf<TGuards, TGuardsOpt>) & keyof TVocabulary & string;
|
|
49
|
+
/**
|
|
50
|
+
* What an endpoint's handler is handed: the session context when one of its
|
|
51
|
+
* guards needs a session (so ctx.session is typed present), the plain one
|
|
52
|
+
* otherwise, with the payload, the guards' data and a refuse() typed to the
|
|
53
|
+
* codes the endpoint may refuse with.
|
|
54
|
+
*/
|
|
55
|
+
type LambderApiHandlerContext<TApp extends LambderAppTypes, TPayload, TGuardsOpt, TRefusalsOpt> = (LambderApiModeOf<TApp["guards"], TGuardsOpt> extends "session" ? LambderSessionRenderContext<TPayload, TApp["session"], Record<string, string>, LambderGuardDataOf<TApp["guards"], TGuardsOpt>, TApp["policies"]> : LambderRenderContext<TPayload, Record<string, string>, LambderGuardDataOf<TApp["guards"], TGuardsOpt>, TApp["session"], TApp["policies"]>) & {
|
|
56
|
+
refuse: LambderDeclaredRefuse<LambderHandlerRefusalsOf<TApp["refusals"], LambderApiRefusalCodes<TApp["refusals"], TApp["guards"], TRefusalsOpt, TGuardsOpt>>, TApp["refusalCodesRequired"]>;
|
|
57
|
+
};
|
|
45
58
|
/**
|
|
46
59
|
* Main Lambder class for building type-safe serverless APIs. Create
|
|
47
60
|
* instances with initLambder<SessionData>().create({...}) (see below): the
|
|
48
61
|
* whole configuration, including the typed policy layer, is given at
|
|
49
|
-
* construction
|
|
62
|
+
* construction. Endpoints are declared as values on the instance
|
|
63
|
+
* (defineApi, defineApiGroup) and registered in one registerApiGroups()
|
|
64
|
+
* call; routes, hooks and actions chain.
|
|
50
65
|
*
|
|
51
|
-
* @typeParam
|
|
52
|
-
* @typeParam _TContract - @internal
|
|
53
|
-
* @typeParam _TRateLimitPolicies - @internal Inferred from create()'s rateLimits.policies (do not pass manually)
|
|
54
|
-
* @typeParam _TGuards - @internal Guard metadata map inferred from create()'s guards (do not pass manually)
|
|
55
|
-
* @typeParam _TIdempotencyEnabled - @internal True when create() received idempotency (do not pass manually)
|
|
56
|
-
* @typeParam _TSessionGuardsRequired - @internal True when create() received requireSessionApiGuards (do not pass manually)
|
|
57
|
-
* @typeParam _TPublicGuardsRequired - @internal True when create() received requirePublicApiGuards (do not pass manually)
|
|
58
|
-
* @typeParam _TSessionsEnabled - @internal True when create() received the session option (do not pass manually). Defaults to true, unlike its siblings, so a plugin annotating its parameter as the bare Lambder<SessionData> can still register session APIs. create() knows the option and supplies the false; `new Lambder(...)` relies on the registration-time throw alone.
|
|
59
|
-
* @typeParam _TRefusals - @internal The refusal vocabulary declareRefusals() gave the init (do not pass manually)
|
|
60
|
-
* @typeParam _TRefusalCodesRequired - @internal True when declareRefusals() received requireCodes (do not pass manually)
|
|
66
|
+
* @typeParam TApp - @internal What create() configured, as LambderAppTypes: the session data, policies, guards, idempotency, the guard requirement, sessions and the refusal vocabulary (do not pass manually)
|
|
67
|
+
* @typeParam _TContract - @internal The contract of the groups registered so far (do not pass manually)
|
|
61
68
|
*
|
|
62
69
|
* @example
|
|
63
70
|
* ```typescript
|
|
64
71
|
* interface SessionData { userId: string; role: string; }
|
|
65
72
|
*
|
|
66
|
-
* const
|
|
67
|
-
*
|
|
68
|
-
*
|
|
73
|
+
* const app = initLambder<SessionData>().create({ apiPath: '/api', session, guards });
|
|
74
|
+
* const userApis = app.defineApiGroup("users", {
|
|
75
|
+
* get: app.defineApi({ input: z.object({...}), output: z.object({...}), guards: "signedIn" }, handler),
|
|
76
|
+
* });
|
|
77
|
+
* const lambder = app.registerApiGroups(userApis);
|
|
69
78
|
* ```
|
|
70
79
|
*/
|
|
71
|
-
export default class Lambder<
|
|
80
|
+
export default class Lambder<TApp extends LambderAppTypes = LambderPlainAppTypes, _TContract extends Record<string, any> = {}> {
|
|
72
81
|
apiPath: string;
|
|
73
82
|
/** Stamped on every API answer's envelope as apiVersion. Informational: a client's staleness is judged per endpoint by its signature, see apiSignatures(). */
|
|
74
83
|
apiVersion: null | string;
|
|
@@ -78,24 +87,35 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
78
87
|
* Type property for extracting the API contract: every registered API's
|
|
79
88
|
* input, output, mode and declared options, as a client calls it.
|
|
80
89
|
*
|
|
81
|
-
* A small app's client imports it as it is.
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* this property off the exported instance and writes the contract out as
|
|
85
|
-
* plain types for such a client to import instead.
|
|
90
|
+
* A small app's client imports it as it is. A large app's client reads
|
|
91
|
+
* the plain types writeApiContract (lambder/build) prints from this
|
|
92
|
+
* property instead, which cost it nothing to resolve.
|
|
86
93
|
*
|
|
87
94
|
* @example
|
|
88
95
|
* ```typescript
|
|
89
|
-
* export const lambder =
|
|
96
|
+
* export const lambder = lambderApp.registerApiGroups(userApis, orderApis);
|
|
90
97
|
* export type ApiContractType = typeof lambder.ApiContract;
|
|
91
98
|
* ```
|
|
92
99
|
*/
|
|
93
100
|
readonly ApiContract: _TContract;
|
|
101
|
+
/**
|
|
102
|
+
* Type property for what create() configured (LambderAppTypes): the
|
|
103
|
+
* session data, policies, guards and the rest, for code that takes any
|
|
104
|
+
* instance and needs one of them (lambderTestApp reads the session data
|
|
105
|
+
* type here). Like ApiContract, it has no value.
|
|
106
|
+
*/
|
|
107
|
+
readonly AppTypes: TApp;
|
|
94
108
|
private actionList;
|
|
95
109
|
/** The API core: the pipeline every API call runs through, shared in shape with the mock runtime. */
|
|
96
110
|
private readonly pipeline;
|
|
97
|
-
/** Every registered API by name:
|
|
111
|
+
/** Every registered API by name: what dispatch, apiSignatures() and apiOptionEntries() read. */
|
|
98
112
|
private readonly apiDefinitions;
|
|
113
|
+
/** What answers each registered API: its output schema, compression setting and handler. */
|
|
114
|
+
private readonly apiHandlers;
|
|
115
|
+
/** Every group name registered, lazy or not: the duplicate-group check. */
|
|
116
|
+
private readonly apiGroupNames;
|
|
117
|
+
/** The lazy groups not loaded yet, each with its load in progress, if one is. */
|
|
118
|
+
private readonly lazyApiGroups;
|
|
99
119
|
/** The guards given at creation, merged into one map, kept for apiSignatures(): a guard's schema is part of the signature of every endpoint declaring it. */
|
|
100
120
|
private readonly guards;
|
|
101
121
|
/** The rate-limit policies given at creation, kept for apiOptionEntries(), which records each one less its key handler. */
|
|
@@ -117,7 +137,8 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
117
137
|
private eventActionList;
|
|
118
138
|
private corsConfig;
|
|
119
139
|
private finalizeOptions;
|
|
120
|
-
|
|
140
|
+
/** Whether every endpoint has to declare guards (create()'s requireApiGuards). */
|
|
141
|
+
private readonly requireApiGuards;
|
|
121
142
|
/** Whether every refusal an API answers with has to name a code (declareRefusals's requireCodes). */
|
|
122
143
|
private readonly requireRefusalCodes;
|
|
123
144
|
/** Told what a request threw, beside whatever answers it; null outside a test. See LAMBDER_CRASH_WATCH. */
|
|
@@ -128,8 +149,10 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
128
149
|
private readonly contextTools;
|
|
129
150
|
private readonly trustedClientIpHeaders;
|
|
130
151
|
private readonly trustedHostHeaders;
|
|
131
|
-
private
|
|
132
|
-
|
|
152
|
+
private readonly originProof;
|
|
153
|
+
/** Where each API call's summary goes (the callSummary option); null writes none. Replaceable through the backend swap alone. */
|
|
154
|
+
private callSummaryWriter;
|
|
155
|
+
constructor(given?: LambderCreateOptions<TApp["session"]>);
|
|
133
156
|
setRouteFallbackHandler(routeFallbackHandler: LambderFallbackHandler): this;
|
|
134
157
|
setApiFallbackHandler(apiFallbackHandler: LambderFallbackHandler): this;
|
|
135
158
|
setApiInputValidationErrorHandler(apiInputValidationErrorHandler: LambderInputValidationHandler): this;
|
|
@@ -163,45 +186,33 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
163
186
|
* res.templateFile (markers optional) with no-cache.
|
|
164
187
|
*/
|
|
165
188
|
serveIndexHtml(handler?: LambderFallbackHandler, options?: LambderIndexHtmlOptions): this;
|
|
166
|
-
addRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: (ctx: LambderRenderContext<any, LambderPathParamsOf<TPath>, {},
|
|
189
|
+
addRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: (ctx: LambderRenderContext<any, LambderPathParamsOf<TPath>, {}, TApp["session"], TApp["policies"]>, resolver: LambderResolver) => MaybePromise<LambderResponse>): this;
|
|
167
190
|
addRoute(condition: RegExp | LambderRouteConditionFn | LambderRouteMatcher, actionFn: LambderRouteHandler): this;
|
|
168
|
-
addSessionRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: ((ctx: LambderSessionRenderContext<any,
|
|
169
|
-
addSessionRoute(condition: RegExp | LambderRouteConditionFn | LambderRouteMatcher, actionFn: LambderSessionRouteHandler<
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
* body is large enough to gain, false never, true always. false suits an answer of base64 bytes: once
|
|
187
|
-
* compressed it leaves the function base64-encoded again, so it is no smaller under Lambda's response
|
|
188
|
-
* cap or to a lambda caller, and a browser gets it only about a quarter smaller for the time spent at
|
|
189
|
-
* both ends. A transport setting of this server's, not part of the API's contract.
|
|
190
|
-
*/
|
|
191
|
-
compress?: boolean | "auto";
|
|
192
|
-
} & LambderRequirableGuardsField<_TPublicGuardsRequired, TGuardsOpt> & LambderObjectOutputCheck<TOutput> & LambderPayloadSliceCheck<_TGuards, _TRateLimitPolicies, TGuardsOpt, TRateOpt, z.input<TInput>>,
|
|
193
|
-
/** Answers the call by returning its output (parsed through `output` before it is sent), or refuses it with ctx.refuse() or refuse(). */
|
|
194
|
-
handler: (ctx: LambderRenderContext<z.infer<TInput>, Record<string, string>, LambderGuardDataOf<_TGuards, TGuardsOpt>, TSessionData, _TRateLimitPolicies> & {
|
|
195
|
-
refuse: LambderDeclaredRefuse<LambderHandlerRefusalsOf<_TRefusals, LambderApiRefusalCodes<_TRefusals, _TGuards, TRefusalsOpt, TGuardsOpt>>, _TRefusalCodesRequired>;
|
|
196
|
-
}) => MaybePromise<TAnswer>): Lambder<TSessionData, LambderMergeContract<_TContract, TName, LambderContractEntry<z.input<TInput>, LambderJsonOf<z.output<TOutput>>, "public", LambderGuardInputsOf<_TGuards, TGuardsOpt>, TGuardsOpt, TRateOpt, TIdempotencyOpt, LambderWireRefusalsOf<_TRefusals, LambderApiRefusalCodes<_TRefusals, _TGuards, TRefusalsOpt, TGuardsOpt>>>>, _TRateLimitPolicies, _TGuards, _TIdempotencyEnabled, _TSessionGuardsRequired, _TPublicGuardsRequired, _TSessionsEnabled, _TRefusals, _TRefusalCodesRequired>;
|
|
197
|
-
addSessionApi<TName extends string, TInput extends z.ZodType, TOutput extends z.ZodType, const TAnswer extends LambderReadonlyDeep<z.input<TOutput>>, const TRateOpt extends LambderRateLimitOption<_TRateLimitPolicies, true> = never, const TGuardsOpt extends LambderGuardsOption<_TGuards, true> = never, const TIdempotencyOpt extends LambderApiIdempotencyOption = never, const TRefusalsOpt extends LambderRefusalsOption<_TRefusals> = never>(name: TName, schema: {
|
|
191
|
+
addSessionRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: ((ctx: LambderSessionRenderContext<any, TApp["session"], LambderPathParamsOf<TPath>, {}, TApp["policies"]>, resolver: LambderResolver) => MaybePromise<LambderResponse>) & LambderSessionEnabledInstance<TApp["sessions"]>): this;
|
|
192
|
+
addSessionRoute(condition: RegExp | LambderRouteConditionFn | LambderRouteMatcher, actionFn: LambderSessionRouteHandler<TApp["session"]> & LambderSessionEnabledInstance<TApp["sessions"]>): this;
|
|
193
|
+
/**
|
|
194
|
+
* Declares one endpoint, typed on this instance's types: its input and
|
|
195
|
+
* output schemas, its guards, rate limits, idempotency and refusals, and
|
|
196
|
+
* its handler. Nothing is registered until the declaration is put in a
|
|
197
|
+
* group (defineApiGroup) and the group is registered (registerApiGroups).
|
|
198
|
+
*
|
|
199
|
+
* The guards say who may call it, and so its mode: an endpoint whose
|
|
200
|
+
* guards include one that needs a session (`session: true`) is a session
|
|
201
|
+
* endpoint, its session read before the guards run and a call without
|
|
202
|
+
* one answered sessionExpired, and its handler's ctx.session is typed
|
|
203
|
+
* present. Any other endpoint is public.
|
|
204
|
+
*
|
|
205
|
+
* An arrow property rather than a method, so an app can hand it out
|
|
206
|
+
* detached: `export const { defineApi, defineApiGroup } = lambderApp;`.
|
|
207
|
+
*/
|
|
208
|
+
readonly defineApi: <TInput extends z.ZodType, TOutput extends z.ZodType, const TAnswer extends LambderReadonlyDeep<z.input<TOutput>>, const TRateOpt extends LambderRateLimitOption<TApp["policies"]> = never, const TGuardsOpt extends LambderGuardsOption<TApp["guards"]> = never, const TIdempotencyOpt extends LambderApiIdempotencyOption = never, const TRefusalsOpt extends LambderRefusalsOption<TApp["refusals"]> = never>(options: {
|
|
198
209
|
input: TInput;
|
|
199
210
|
output: TOutput;
|
|
200
211
|
} & {
|
|
201
|
-
/** Named rate limits, checked in declared order within their phase (per ip before the session read, per session before the guards, a custom key after the guards and input validation): a name, a list of names, or a { name: true | override } map (windows overridable on perApi budgets, refusal on any). The first exceeded one refuses (429 envelope + Retry-After); attempts count on every counter checked before it. */
|
|
212
|
+
/** Named rate limits, checked in declared order within their phase (per ip before the session read, per session before the guards, a custom key after the guards and input validation): a name, a list of names, or a { name: true | override } map (windows overridable on perApi budgets, refusal on any). The first exceeded one refuses (429 envelope + Retry-After); attempts count on every counter checked before it. A per-session policy needs one of the endpoint's guards to need a session. */
|
|
202
213
|
rateLimit?: TRateOpt;
|
|
203
214
|
/** Replay-protect this API per client idempotencyKey. Requires the idempotency option at creation. */
|
|
204
|
-
idempotency?:
|
|
215
|
+
idempotency?: TApp["idempotency"] extends true ? TIdempotencyOpt : never;
|
|
205
216
|
/**
|
|
206
217
|
* The refusal codes this API may refuse with, from the vocabulary given at creation: one code or a
|
|
207
218
|
* non-empty list. Its guards' codes join them. The handler raises one with `ctx.refuse(content, { code, data })`,
|
|
@@ -216,19 +227,96 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
216
227
|
* both ends. A transport setting of this server's, not part of the API's contract.
|
|
217
228
|
*/
|
|
218
229
|
compress?: boolean | "auto";
|
|
219
|
-
} & LambderRequirableGuardsField<
|
|
230
|
+
} & LambderRequirableGuardsField<TApp["guardsRequired"], TGuardsOpt> & LambderObjectOutputCheck<TOutput> & LambderPayloadSliceCheck<TApp["guards"], TApp["policies"], TGuardsOpt, TRateOpt, z.input<TInput>> & LambderPublicSessionPolicyCheck<LambderApiModeOf<TApp["guards"], TGuardsOpt>, TApp["policies"], TRateOpt> & LambderSessionModeCheck<LambderApiModeOf<TApp["guards"], TGuardsOpt>, TApp["sessions"]>,
|
|
220
231
|
/** Answers the call by returning its output (parsed through `output` before it is sent), or refuses it with ctx.refuse() or refuse(). */
|
|
221
|
-
handler: (ctx:
|
|
222
|
-
|
|
223
|
-
|
|
232
|
+
handler: (ctx: LambderApiHandlerContext<TApp, z.infer<TInput>, TGuardsOpt, TRefusalsOpt>) => MaybePromise<TAnswer>) => LambderApiDeclaration<LambderContractEntry<z.input<TInput>, LambderJsonOf<z.output<TOutput>>, LambderApiModeOf<TApp["guards"], TGuardsOpt>, LambderGuardInputsOf<TApp["guards"], TGuardsOpt>, TGuardsOpt, TRateOpt, TIdempotencyOpt, LambderWireRefusalsOf<TApp["refusals"], LambderApiRefusalCodes<TApp["refusals"], TApp["guards"], TRefusalsOpt, TGuardsOpt>>>>;
|
|
233
|
+
/**
|
|
234
|
+
* Gathers endpoints into a named group: each is registered as
|
|
235
|
+
* `name.action` and called at `{apiPath}/{name}/{action}`, and every
|
|
236
|
+
* Lambder caller reaches it as `caller.name.action(input)`. A group's
|
|
237
|
+
* name and its actions are identifiers, and a group may not take a name
|
|
238
|
+
* a caller already answers for (see LAMBDER_RESERVED_GROUP_NAMES).
|
|
239
|
+
*
|
|
240
|
+
* A group declared across files takes each file's part:
|
|
241
|
+
* `defineApiGroup("orders", orderReadApis, orderWriteApis)`. An action
|
|
242
|
+
* two parts declare is refused, at compile time and at startup, rather
|
|
243
|
+
* than one silently replacing the other as an object spread would.
|
|
244
|
+
*/
|
|
245
|
+
readonly defineApiGroup: <const TName extends string, const TParts extends readonly [LambderApiDeclarations, ...LambderApiDeclarations[]]>(name: TName & LambderGroupNameCheck<TName>, ...parts: TParts & LambderGroupPartsCheck<TParts> & { [TIndex in keyof TParts]: LambderActionNamesCheck<TParts[TIndex]>; }) => LambderApiGroup<TName, LambderMergedParts<TParts>>;
|
|
224
246
|
/**
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
247
|
+
* A group loaded on the first call to one of its endpoints:
|
|
248
|
+
* `lazyApiGroup("orders", () => import("./orders.js").then((m) => m.orderApis))`.
|
|
249
|
+
* A cold start then parses none of it, nor anything only it imports,
|
|
250
|
+
* until a request calls it; the contract is the loaded group's, read off
|
|
251
|
+
* its type. The group loaded must carry the same name, which the type
|
|
252
|
+
* checks and loading checks again. `loadApiGroups()` loads every group,
|
|
253
|
+
* for a build step or a boot check that has to see them all.
|
|
254
|
+
*/
|
|
255
|
+
readonly lazyApiGroup: <const TName extends string, TGroup extends LambderApiGroup<TName, any>>(name: TName & LambderGroupNameCheck<TName>, load: () => Promise<TGroup>) => LambderLazyApiGroup<TName, NoInfer<TGroup>>;
|
|
256
|
+
/**
|
|
257
|
+
* Registers groups of endpoints, as one contract: `typeof
|
|
258
|
+
* lambder.ApiContract` then maps every `group.action` to its entry, one
|
|
259
|
+
* flat object type the api-contract generator prints as it is. Register
|
|
260
|
+
* every group in one call where you can: the contract of one call is one
|
|
261
|
+
* mapped type, and a second call intersects it with the first.
|
|
262
|
+
*
|
|
263
|
+
* The call's groups take their place in the first-match chain here, as
|
|
264
|
+
* a route does: a route or action registered before them sees their calls
|
|
265
|
+
* first, one registered after them never does. The beforeRender hooks run
|
|
266
|
+
* before a lazy group loads, so a hook that answers a request spares it
|
|
267
|
+
* the import; one that throws a refusal or charges a per-API budget loads
|
|
268
|
+
* it (see registeredDefinitionOf).
|
|
269
|
+
*
|
|
270
|
+
* Refused at compile time: a group typed `any`, or a lazy one loading a
|
|
271
|
+
* group typed `any`, or a group whose endpoints are (its endpoints would
|
|
272
|
+
* be `any` to every client), and a group name given twice. Refused at
|
|
273
|
+
* registration, which is at startup for a group and at its first call for
|
|
274
|
+
* a lazy one: everything registration refuses of one endpoint (an unknown
|
|
275
|
+
* guard or policy, a missing guard where requireApiGuards is on, a
|
|
276
|
+
* refusal code outside the vocabulary).
|
|
230
277
|
*/
|
|
231
|
-
|
|
278
|
+
registerApiGroups<const TGroups extends readonly LambderRegistrableApiGroup[]>(this: LambderRegisteredGroupsCheck<TGroups, Lambder<TApp, _TContract>>, ...groups: TGroups): Lambder<TApp, _TContract & LambderContractOfGroups<TGroups>>;
|
|
279
|
+
/**
|
|
280
|
+
* Loads every lazy group not loaded yet, registering its endpoints: what
|
|
281
|
+
* a build step digesting the signatures, a generator writing the options
|
|
282
|
+
* or a boot check has to do before it sees every endpoint. A group whose
|
|
283
|
+
* registration fails rejects here, which is the point of calling it.
|
|
284
|
+
*/
|
|
285
|
+
loadApiGroups(): Promise<void>;
|
|
286
|
+
/**
|
|
287
|
+
* An API call to a registered group, its hooks run: its group loaded
|
|
288
|
+
* first when it is a lazy one no call has reached yet, then its endpoint
|
|
289
|
+
* run. An action the group does not have is answered as any unmatched API
|
|
290
|
+
* call is, fallback hooks first.
|
|
291
|
+
*/
|
|
292
|
+
private dispatchApiCall;
|
|
293
|
+
/**
|
|
294
|
+
* The definition of the endpoint a call names, its group loaded first
|
|
295
|
+
* when it is a lazy one no call has reached yet; undefined for a name no
|
|
296
|
+
* registered group declares. Everything that reads an endpoint's
|
|
297
|
+
* declarations for a call asks here (its dispatch, a refusal a hook
|
|
298
|
+
* throws on the way to it, a per-API budget a hook charges), so a lazy
|
|
299
|
+
* group answers each of them as an eager one does.
|
|
300
|
+
*/
|
|
301
|
+
private registeredDefinitionOf;
|
|
302
|
+
/** The endpoints of one group, each checked as `group.action`; nothing is registered until they are committed. */
|
|
303
|
+
private prepareApiGroup;
|
|
304
|
+
/**
|
|
305
|
+
* A lazy group, loaded once: its import, checked to be the group it was
|
|
306
|
+
* registered as, then registered. Concurrent first calls share one load;
|
|
307
|
+
* a failed load is forgotten, so the next call tries again rather than
|
|
308
|
+
* answering every later call with the first failure.
|
|
309
|
+
*/
|
|
310
|
+
private loadLazyApiGroup;
|
|
311
|
+
/**
|
|
312
|
+
* What registering an endpoint takes: the checks that can refuse it and
|
|
313
|
+
* its mode read off its guards, into the definition apiSignatures()
|
|
314
|
+
* digests, beside its handler. Nothing is recorded here (commitApi does
|
|
315
|
+
* that), so a refusal anywhere in a registration leaves nothing behind.
|
|
316
|
+
*/
|
|
317
|
+
private prepareApi;
|
|
318
|
+
/** Records a checked endpoint: its definition, its refusals option as written, and what answers it. */
|
|
319
|
+
private commitApi;
|
|
232
320
|
addHook(hookEvent: 'created', hookFn: LambderCreatedHook, priority?: number): this;
|
|
233
321
|
addHook(hookEvent: 'beforeRender', hookFn: LambderBeforeRenderHook, priority?: number): this;
|
|
234
322
|
addHook(hookEvent: 'afterRender', hookFn: LambderAfterRenderHook, priority?: number): this;
|
|
@@ -251,7 +339,13 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
251
339
|
*/
|
|
252
340
|
addAction<TEvent>(filter: (event: unknown, ctx: LambderRenderContext | null) => event is TEvent, actionFn: (event: TEvent, tools: LambderActionTools) => MaybePromise<unknown>): this;
|
|
253
341
|
addAction(filter: (event: unknown, ctx: LambderRenderContext | null) => boolean, actionFn: (event: unknown, tools: LambderActionTools) => MaybePromise<unknown>): this;
|
|
254
|
-
|
|
342
|
+
/**
|
|
343
|
+
* Hands the instance to a function that registers on it (routes, hooks,
|
|
344
|
+
* actions) and continues the chain with what it returns. Endpoints are
|
|
345
|
+
* not registered this way: they are values, registered by
|
|
346
|
+
* registerApiGroups(), so a plugin adds nothing to the contract.
|
|
347
|
+
*/
|
|
348
|
+
use(plugin: (lambder: this) => unknown): this;
|
|
255
349
|
/**
|
|
256
350
|
* A session controller for a context: what creates, rotates, refreshes
|
|
257
351
|
* and ends sessions. An API call presents its posted CSRF token; a route
|
|
@@ -259,9 +353,9 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
259
353
|
* carries one as `ctx.sessionController`; this is for a context it did
|
|
260
354
|
* not render, such as one createContext() built from an event on its own.
|
|
261
355
|
*/
|
|
262
|
-
getSessionController(ctx: LambderRenderContext | LambderSessionRenderContext<any,
|
|
356
|
+
getSessionController(ctx: LambderRenderContext | LambderSessionRenderContext<any, TApp["session"]>): LambderSessionController<TApp["session"]>;
|
|
263
357
|
/** The session manager, for code that works on sessions outside a request (maintenance, tests). */
|
|
264
|
-
getSessionManager(): LambderSessionManager<
|
|
358
|
+
getSessionManager(): LambderSessionManager<TApp["session"]>;
|
|
265
359
|
/**
|
|
266
360
|
* The backend swap `lambder/testing` performs: the stores given go under
|
|
267
361
|
* this instance in place, so every handler and guard that closed over it
|
|
@@ -316,7 +410,7 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
316
410
|
* same object. Every table is sorted by name, so the module diffs by
|
|
317
411
|
* endpoint and never moves when registrations are reordered.
|
|
318
412
|
*/
|
|
319
|
-
apiOptionEntries(): LambderApiOptionEntries
|
|
413
|
+
apiOptionEntries(): Promise<LambderApiOptionEntries>;
|
|
320
414
|
getResponseBuilder(ctx?: LambderRenderContext): LambderResponseBuilder;
|
|
321
415
|
private getResolver;
|
|
322
416
|
getHandler(): LambderHandler;
|
|
@@ -341,6 +435,12 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
341
435
|
*/
|
|
342
436
|
private runBeforeRenderHooks;
|
|
343
437
|
private handleNoMatchedAction;
|
|
438
|
+
/**
|
|
439
|
+
* What answers a request nothing matched, its beforeRender hooks run:
|
|
440
|
+
* the fallback hooks, then the API fallback for an API call, and
|
|
441
|
+
* otherwise the public files, the shell and the route fallback in turn.
|
|
442
|
+
*/
|
|
443
|
+
private answerUnmatched;
|
|
344
444
|
/**
|
|
345
445
|
* True for the OPTIONS request the CORS layer answers by itself. Asked
|
|
346
446
|
* twice: once to build the 204, once at the end of render() to pick which
|
|
@@ -351,7 +451,15 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
351
451
|
*/
|
|
352
452
|
private isCorsPreflight;
|
|
353
453
|
private resolveRequest;
|
|
454
|
+
/**
|
|
455
|
+
* One HTTP invocation, from the event to the finalized response, under
|
|
456
|
+
* an invocation record of its own (see LambderInvocationScope): what an
|
|
457
|
+
* API call's summary line is written from once the response is final.
|
|
458
|
+
*/
|
|
354
459
|
render(event: LambderHttpEvent, lambdaContext: Context): Promise<LambderHttpResponse>;
|
|
460
|
+
private renderRequest;
|
|
461
|
+
/** What createContext reads this instance's requests with. */
|
|
462
|
+
private contextOptions;
|
|
355
463
|
/**
|
|
356
464
|
* A thrown value that is an answer rather than a crash, as the response;
|
|
357
465
|
* anything else is rethrown to the crash path.
|
|
@@ -376,6 +484,12 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
376
484
|
* failed too.
|
|
377
485
|
*/
|
|
378
486
|
private answerCrash;
|
|
487
|
+
/**
|
|
488
|
+
* The summary line of an API call, once its response is final: nothing
|
|
489
|
+
* for an invocation that served no API call. A writer that throws costs
|
|
490
|
+
* the call its line and nothing else.
|
|
491
|
+
*/
|
|
492
|
+
private writeCallSummary;
|
|
379
493
|
/**
|
|
380
494
|
* An answer to a crash, carrying what the call wrote and its CORS headers.
|
|
381
495
|
* As on the success path, headers belong to the call: a call that wrote a
|
|
@@ -406,6 +520,7 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
406
520
|
* so Lambda's retries and dead-letter queues still see the failure.
|
|
407
521
|
*/
|
|
408
522
|
renderEvent(event: unknown, lambdaContext: Context): Promise<unknown>;
|
|
523
|
+
private renderEventAction;
|
|
409
524
|
/**
|
|
410
525
|
* The answer for a rejected input: the app's
|
|
411
526
|
* setApiInputValidationErrorHandler when set, otherwise the standard 422
|
|
@@ -446,7 +561,8 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
446
561
|
/**
|
|
447
562
|
* A thrown LambderApiRefusal (from a hook, say) as the structured API
|
|
448
563
|
* envelope: the core's one mapping, after the same check the pipeline
|
|
449
|
-
* applies, against the endpoint the call names
|
|
564
|
+
* applies, against the endpoint the call names, its lazy group loaded if
|
|
565
|
+
* the refusal came before the call reached it. A name no API is
|
|
450
566
|
* registered under declares no code, so only an uncoded or a framework
|
|
451
567
|
* refusal goes out for it.
|
|
452
568
|
*/
|
|
@@ -456,11 +572,12 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
456
572
|
* The canonical way to create an instance: fix the session data type first,
|
|
457
573
|
* then create with the full configuration in one declaration. The policy,
|
|
458
574
|
* guard and idempotency types are inferred from the options, so the instance
|
|
459
|
-
* is born fully typed and
|
|
460
|
-
*
|
|
575
|
+
* is born fully typed, and the endpoints declared with its defineApi are
|
|
576
|
+
* typed against it. There are no ordering rules, and nothing can be
|
|
577
|
+
* half-configured.
|
|
461
578
|
*
|
|
462
579
|
* ```typescript
|
|
463
|
-
* // app.ts (imports no api modules, so modules can import
|
|
580
|
+
* // app.ts (imports no api modules, so modules can import from it)
|
|
464
581
|
* export const lambderApp = initLambder<SessionData>().create({
|
|
465
582
|
* apiPath: "/api",
|
|
466
583
|
* session: { store: new LambderDdbSessionStore({ tableName: "app-session", region: "us-east-1" }), sessionSalt: "..." },
|
|
@@ -468,13 +585,15 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
|
|
|
468
585
|
* guards,
|
|
469
586
|
* idempotency: { store },
|
|
470
587
|
* });
|
|
471
|
-
* export
|
|
588
|
+
* export const { defineApi, defineApiGroup, lazyApiGroup } = lambderApp;
|
|
472
589
|
*
|
|
473
590
|
* // orders.ts
|
|
474
|
-
* export const
|
|
591
|
+
* export const orderApis = defineApiGroup("orders", {
|
|
592
|
+
* place: defineApi({ input, output, guards: "signedIn" }, async (ctx) => ...),
|
|
593
|
+
* });
|
|
475
594
|
*
|
|
476
595
|
* // index.ts: registration only
|
|
477
|
-
* const lambder = lambderApp.
|
|
596
|
+
* const lambder = lambderApp.registerApiGroups(orderApis).addHook(...);
|
|
478
597
|
* export const handler = lambder.getHandler();
|
|
479
598
|
* ```
|
|
480
599
|
*
|
|
@@ -498,7 +617,10 @@ export declare const initLambder: <TSessionData = any>() => {
|
|
|
498
617
|
* Declares the app's refusal vocabulary: every code once, with the schema
|
|
499
618
|
* of its data (`{ data: schema }`) or none (`{}`), the status every
|
|
500
619
|
* refusal with it leaves with (`status`, 200 by default) and whether it
|
|
501
|
-
* sets the notAuthorized flag (`notAuthorized: true`).
|
|
620
|
+
* sets the notAuthorized flag (`notAuthorized: true`). One map of codes,
|
|
621
|
+
* or a list of them, as guards and rate-limit policies are declared, so
|
|
622
|
+
* each part of an app declares its own codes; a code two maps declare is
|
|
623
|
+
* refused, at compile time and at the call. Returns the init
|
|
502
624
|
* bound to it: its guard() types ctx.refuse to a guard's refusals and
|
|
503
625
|
* refuses a guard naming a code outside the vocabulary, its refuse is
|
|
504
626
|
* typed to the whole vocabulary, and its create() hands the vocabulary to
|
|
@@ -506,7 +628,7 @@ export declare const initLambder: <TSessionData = any>() => {
|
|
|
506
628
|
* handler, a guard or a helper is a crash rather than an answer, so every
|
|
507
629
|
* "no" a client reads names a code.
|
|
508
630
|
*/
|
|
509
|
-
declareRefusals<const TRefusals extends
|
|
631
|
+
declareRefusals<const TRefusals extends LambderRefusalVocabularyOption, const TRequireCodes extends boolean = false>(refusals: TRefusals & LambderRefusalVocabularyOptionChecks<TRefusals>, options?: {
|
|
510
632
|
requireCodes?: TRequireCodes;
|
|
511
633
|
}): {
|
|
512
634
|
/**
|
|
@@ -517,11 +639,20 @@ export declare const initLambder: <TSessionData = any>() => {
|
|
|
517
639
|
* refuse(). Inside an API handler ctx.refuse is narrower, that
|
|
518
640
|
* endpoint's codes alone.
|
|
519
641
|
*/
|
|
520
|
-
refuse: LambderDeclaredRefuse<LambderHandlerRefusalsOf<TRefusals
|
|
521
|
-
create<const TOptions extends LambderInitCreateOptions<TSessionData>>(options: TOptions & Record<Exclude<keyof TOptions, "session" | "guards" | "idempotency" | "apiVersion" | "cors" | "apiPath" | "apiSignatures" | "trustedClientIpHeaders" | "trustedHostHeaders" | "files" | "etag" | "rateLimits" | "minApiVersion" | "compression" | "maxResponseBytes" | "maxRequestPayloadBytes" | "
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
642
|
+
refuse: LambderDeclaredRefuse<LambderHandlerRefusalsOf<LambderMergedRefusalVocabulary<TRefusals>, keyof LambderMergedRefusalVocabulary<TRefusals> & string>, TRequireCodes>;
|
|
643
|
+
create<const TOptions extends LambderInitCreateOptions<TSessionData>>(options: TOptions & Record<Exclude<keyof TOptions, "session" | "guards" | "idempotency" | "apiVersion" | "cors" | "apiPath" | "apiSignatures" | "trustedClientIpHeaders" | "trustedHostHeaders" | "originProof" | "files" | "etag" | "rateLimits" | "minApiVersion" | "compression" | "maxResponseBytes" | "maxRequestPayloadBytes" | "callSummary" | "requireApiGuards" | "crashes">, never> & LambderNestedOptionChecks<TSessionData, TOptions, LambderMergedRefusalVocabulary<TRefusals>>): Lambder<{
|
|
644
|
+
session: TSessionData;
|
|
645
|
+
policies: TOptions["rateLimits"] extends {
|
|
646
|
+
policies: infer TPolicies;
|
|
647
|
+
} ? LambderMergedNamedMaps<TPolicies> extends infer TMerged extends Record<string, LambderApiRateLimitPolicyConfig> ? TMerged : {} : {};
|
|
648
|
+
guards: TOptions["guards"] extends LambderNamedMapsOption<Record<string, LambderApiGuard<any, any, any>>> ? LambderGuardMetaMap<LambderMergedNamedMaps<TOptions["guards"]>> : {};
|
|
649
|
+
idempotency: TOptions["idempotency"] extends LambderApiIdempotencyConfig ? true : false;
|
|
650
|
+
guardsRequired: [LambderGivenOption<TOptions, "requireApiGuards">] extends [false | undefined] ? false : true;
|
|
651
|
+
sessions: [LambderGivenOption<TOptions, "session">] extends [undefined] ? false : true;
|
|
652
|
+
refusals: LambderMergedRefusalVocabulary<TRefusals>;
|
|
653
|
+
refusalCodesRequired: TRequireCodes;
|
|
654
|
+
}, {}>;
|
|
655
|
+
guard: import("../api/LambderApiGuards.js").LambderGuardBuilder<LambderRenderContext<any, Record<string, string>, {}, TSessionData>, LambderSessionRenderContext<any, TSessionData>, LambderMergedRefusalVocabulary<TRefusals>, TRequireCodes>;
|
|
525
656
|
rateLimitKey: import("../api/LambderApiRateLimits.js").LambderRateLimitKeyBuilder<LambderRenderContext<any, Record<string, string>, {}, TSessionData>>;
|
|
526
657
|
};
|
|
527
658
|
/**
|
|
@@ -544,9 +675,18 @@ export declare const initLambder: <TSessionData = any>() => {
|
|
|
544
675
|
code?: undefined;
|
|
545
676
|
data?: undefined;
|
|
546
677
|
}) | undefined) => never;
|
|
547
|
-
create<const TOptions extends LambderInitCreateOptions<TSessionData>>(options: TOptions & Record<Exclude<keyof TOptions, "session" | "guards" | "idempotency" | "apiVersion" | "cors" | "apiPath" | "apiSignatures" | "trustedClientIpHeaders" | "trustedHostHeaders" | "files" | "etag" | "rateLimits" | "minApiVersion" | "compression" | "maxResponseBytes" | "maxRequestPayloadBytes" | "
|
|
548
|
-
|
|
549
|
-
|
|
678
|
+
create<const TOptions extends LambderInitCreateOptions<TSessionData>>(options: TOptions & Record<Exclude<keyof TOptions, "session" | "guards" | "idempotency" | "apiVersion" | "cors" | "apiPath" | "apiSignatures" | "trustedClientIpHeaders" | "trustedHostHeaders" | "originProof" | "files" | "etag" | "rateLimits" | "minApiVersion" | "compression" | "maxResponseBytes" | "maxRequestPayloadBytes" | "callSummary" | "requireApiGuards" | "crashes">, never> & LambderNestedOptionChecks<TSessionData, TOptions, {}>): Lambder<{
|
|
679
|
+
session: TSessionData;
|
|
680
|
+
policies: TOptions["rateLimits"] extends {
|
|
681
|
+
policies: infer TPolicies;
|
|
682
|
+
} ? LambderMergedNamedMaps<TPolicies> extends infer TMerged extends Record<string, LambderApiRateLimitPolicyConfig> ? TMerged : {} : {};
|
|
683
|
+
guards: TOptions["guards"] extends LambderNamedMapsOption<Record<string, LambderApiGuard<any, any, any>>> ? LambderGuardMetaMap<LambderMergedNamedMaps<TOptions["guards"]>> : {};
|
|
684
|
+
idempotency: TOptions["idempotency"] extends LambderApiIdempotencyConfig ? true : false;
|
|
685
|
+
guardsRequired: [LambderGivenOption<TOptions, "requireApiGuards">] extends [false | undefined] ? false : true;
|
|
686
|
+
sessions: [LambderGivenOption<TOptions, "session">] extends [undefined] ? false : true;
|
|
687
|
+
refusals: {};
|
|
688
|
+
refusalCodesRequired: false;
|
|
689
|
+
}, {}>;
|
|
550
690
|
guard: import("../api/LambderApiGuards.js").LambderGuardBuilder<LambderRenderContext<any, Record<string, string>, {}, TSessionData>, LambderSessionRenderContext<any, TSessionData>, {}, false>;
|
|
551
691
|
rateLimitKey: import("../api/LambderApiRateLimits.js").LambderRateLimitKeyBuilder<LambderRenderContext<any, Record<string, string>, {}, TSessionData>>;
|
|
552
692
|
};
|