lambder 7.3.1 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/CHANGELOG.md +1047 -3
  2. package/README.md +46 -21
  3. package/dist/api/LambderApiAnswer.d.ts +18 -22
  4. package/dist/api/LambderApiAnswer.js +6 -7
  5. package/dist/api/LambderApiCallContext.d.ts +21 -8
  6. package/dist/api/LambderApiCallContext.js +22 -4
  7. package/dist/api/LambderApiDefinition.d.ts +4 -3
  8. package/dist/api/LambderApiEnvelope.d.ts +14 -9
  9. package/dist/api/LambderApiEnvelope.js +33 -34
  10. package/dist/api/LambderApiGuards.d.ts +78 -51
  11. package/dist/api/LambderApiGuards.js +34 -36
  12. package/dist/api/LambderApiIdempotency.d.ts +68 -62
  13. package/dist/api/LambderApiIdempotency.js +214 -151
  14. package/dist/api/LambderApiOutputValidationError.d.ts +32 -0
  15. package/dist/api/LambderApiOutputValidationError.js +50 -0
  16. package/dist/api/LambderApiPipeline.d.ts +47 -38
  17. package/dist/api/LambderApiPipeline.js +122 -63
  18. package/dist/api/LambderApiRateLimits.d.ts +201 -54
  19. package/dist/api/LambderApiRateLimits.js +185 -108
  20. package/dist/api/LambderApiRequest.d.ts +27 -21
  21. package/dist/api/LambderApiRequest.js +26 -19
  22. package/dist/api/LambderApiSignature.d.ts +12 -15
  23. package/dist/api/LambderApiSignature.js +28 -51
  24. package/dist/api/LambderApiValidationRefusal.d.ts +9 -9
  25. package/dist/api/LambderApiValidationRefusal.js +10 -10
  26. package/dist/build/ContractTypePrinter.d.ts +85 -0
  27. package/dist/build/ContractTypePrinter.js +402 -0
  28. package/dist/build/freshProcessVerifier.d.ts +13 -0
  29. package/dist/build/freshProcessVerifier.js +19 -0
  30. package/dist/build/moduleLocation.d.ts +11 -0
  31. package/dist/build/moduleLocation.js +6 -0
  32. package/dist/build/writeApiContract.d.ts +78 -0
  33. package/dist/build/writeApiContract.js +302 -0
  34. package/dist/build/writeApiSignatures.d.ts +114 -0
  35. package/dist/build/writeApiSignatures.js +217 -0
  36. package/dist/build/writeFileAtomically.d.ts +8 -0
  37. package/dist/build/writeFileAtomically.js +22 -0
  38. package/dist/build.d.ts +14 -0
  39. package/dist/build.js +11 -0
  40. package/dist/client/LambderCaller.d.ts +13 -44
  41. package/dist/client/LambderCaller.js +77 -84
  42. package/dist/client/LambderReloadLoopBreaker.d.ts +56 -26
  43. package/dist/client/LambderReloadLoopBreaker.js +90 -46
  44. package/dist/client/LambderUploadRunner.d.ts +96 -0
  45. package/dist/client/LambderUploadRunner.js +234 -0
  46. package/dist/client/lambderFetchTransport.d.ts +4 -1
  47. package/dist/client/lambderFetchTransport.js +52 -28
  48. package/dist/client.d.ts +9 -3
  49. package/dist/client.js +6 -1
  50. package/dist/core/Lambder.d.ts +143 -79
  51. package/dist/core/Lambder.js +350 -231
  52. package/dist/core/LambderContext.d.ts +82 -15
  53. package/dist/core/LambderContext.js +107 -20
  54. package/dist/core/LambderCors.d.ts +21 -3
  55. package/dist/core/LambderCors.js +35 -16
  56. package/dist/core/LambderCrashHandling.d.ts +40 -0
  57. package/dist/core/LambderCrashHandling.js +97 -0
  58. package/dist/core/LambderCreateOptions.d.ts +151 -75
  59. package/dist/core/LambderCreateOptions.js +16 -23
  60. package/dist/core/LambderFiles.d.ts +21 -7
  61. package/dist/core/LambderFiles.js +62 -34
  62. package/dist/core/LambderIndexHtml.js +12 -11
  63. package/dist/core/LambderPolicyBuilders.d.ts +17 -5
  64. package/dist/core/LambderPolicyBuilders.js +17 -5
  65. package/dist/core/LambderPublicFiles.d.ts +11 -5
  66. package/dist/core/LambderPublicFiles.js +32 -4
  67. package/dist/core/LambderRequestPath.d.ts +43 -0
  68. package/dist/core/LambderRequestPath.js +63 -0
  69. package/dist/core/LambderResponse.d.ts +26 -5
  70. package/dist/core/LambderResponse.js +157 -70
  71. package/dist/core/LambderResponseBuilder.d.ts +49 -4
  72. package/dist/core/LambderResponseBuilder.js +64 -3
  73. package/dist/core/LambderRouting.d.ts +2 -3
  74. package/dist/core/LambderRouting.js +22 -7
  75. package/dist/core/LambderTemplatingEngine.js +211 -32
  76. package/dist/index.d.ts +25 -8
  77. package/dist/index.js +13 -4
  78. package/dist/invoke/LambderInvokeCaller.d.ts +37 -42
  79. package/dist/invoke/LambderInvokeCaller.js +76 -66
  80. package/dist/invoke/LambderInvokeOutcome.d.ts +27 -26
  81. package/dist/invoke/LambderInvokeOutcome.js +9 -22
  82. package/dist/invoke/LambderLambdaEvent.d.ts +29 -9
  83. package/dist/invoke/LambderLambdaEvent.js +40 -22
  84. package/dist/invoke/lambderHandlerTransport.d.ts +9 -10
  85. package/dist/invoke/lambderHandlerTransport.js +15 -18
  86. package/dist/mock/LambderMockApp.d.ts +67 -83
  87. package/dist/mock/LambderMockApp.js +167 -153
  88. package/dist/mock/LambderMockBrowserCookies.d.ts +24 -28
  89. package/dist/mock/LambderMockBrowserCookies.js +24 -28
  90. package/dist/mock/LambderMockCallRecorder.d.ts +15 -22
  91. package/dist/mock/LambderMockCallRecorder.js +19 -28
  92. package/dist/mock/LambderMockCreateOptions.d.ts +42 -24
  93. package/dist/mock/LambderMockEntryRegistry.d.ts +11 -12
  94. package/dist/mock/LambderMockEntryRegistry.js +24 -29
  95. package/dist/mock/LambderMockFailureInjector.d.ts +3 -6
  96. package/dist/mock/LambderMockFailureInjector.js +3 -6
  97. package/dist/mock/LambderMockTypes.d.ts +78 -108
  98. package/dist/mock/lambderMockInvokeTransport.d.ts +11 -13
  99. package/dist/mock/lambderMockInvokeTransport.js +11 -10
  100. package/dist/mock/lambderMockMswHandler.d.ts +43 -33
  101. package/dist/mock/lambderMockMswHandler.js +50 -39
  102. package/dist/mock/lambderMockUploadMswHandler.d.ts +26 -0
  103. package/dist/mock/lambderMockUploadMswHandler.js +28 -0
  104. package/dist/mock.d.ts +4 -1
  105. package/dist/mock.js +6 -3
  106. package/dist/session/LambderSessionController.d.ts +108 -89
  107. package/dist/session/LambderSessionController.js +187 -168
  108. package/dist/session/LambderSessionCrypto.d.ts +16 -7
  109. package/dist/session/LambderSessionCrypto.js +26 -12
  110. package/dist/session/LambderSessionManager.d.ts +124 -46
  111. package/dist/session/LambderSessionManager.js +262 -137
  112. package/dist/shared/LambderHtml.d.ts +42 -3
  113. package/dist/shared/LambderHtml.js +127 -7
  114. package/dist/shared/LambderHtmlPositions.d.ts +173 -0
  115. package/dist/shared/LambderHtmlPositions.js +652 -0
  116. package/dist/shared/LambderI18n.d.ts +10 -11
  117. package/dist/shared/LambderI18n.js +33 -21
  118. package/dist/shared/contracts/LambderCache.d.ts +66 -0
  119. package/dist/shared/contracts/LambderCache.js +11 -0
  120. package/dist/shared/contracts/LambderFileSource.d.ts +6 -6
  121. package/dist/shared/contracts/LambderFileSource.js +5 -8
  122. package/dist/shared/contracts/LambderIdempotencyStore.d.ts +51 -22
  123. package/dist/shared/contracts/LambderIdempotencyStore.js +4 -5
  124. package/dist/shared/contracts/LambderRateLimiter.d.ts +27 -15
  125. package/dist/shared/contracts/LambderRateLimiter.js +4 -5
  126. package/dist/shared/contracts/LambderSessionStore.d.ts +65 -26
  127. package/dist/shared/contracts/LambderSessionStore.js +5 -6
  128. package/dist/shared/contracts/LambderUploadBucket.d.ts +154 -0
  129. package/dist/shared/contracts/LambderUploadBucket.js +74 -0
  130. package/dist/shared/transport/LambderApiTransport.d.ts +27 -27
  131. package/dist/shared/transport/LambderApiTransport.js +7 -7
  132. package/dist/shared/transport/LambderCookieJar.d.ts +28 -35
  133. package/dist/shared/transport/LambderCookieJar.js +54 -66
  134. package/dist/shared/transport/lambderCookieJarTransport.d.ts +11 -13
  135. package/dist/shared/transport/lambderCookieJarTransport.js +24 -23
  136. package/dist/shared/util/LambderCallAbort.d.ts +5 -5
  137. package/dist/shared/util/LambderCallAbort.js +5 -5
  138. package/dist/shared/util/LambderClientIp.d.ts +27 -11
  139. package/dist/shared/util/LambderClientIp.js +96 -13
  140. package/dist/shared/util/LambderContentDisposition.d.ts +10 -0
  141. package/dist/shared/util/LambderContentDisposition.js +13 -0
  142. package/dist/shared/util/LambderExpiringMap.d.ts +35 -49
  143. package/dist/shared/util/LambderExpiringMap.js +41 -57
  144. package/dist/shared/util/LambderNodeModules.js +6 -7
  145. package/dist/shared/util/LambderOptionChecks.d.ts +4 -4
  146. package/dist/shared/util/LambderOptionChecks.js +4 -4
  147. package/dist/shared/util/LambderResponseBrand.d.ts +5 -5
  148. package/dist/shared/util/LambderResponseBrand.js +5 -5
  149. package/dist/shared/util/LambderTextDigest.d.ts +7 -5
  150. package/dist/shared/util/LambderTextDigest.js +11 -5
  151. package/dist/shared/util/LambderTypeUtilities.d.ts +7 -8
  152. package/dist/shared/util/LambderTypeUtilities.js +3 -3
  153. package/dist/shared/util/boundKeyField.d.ts +20 -0
  154. package/dist/shared/util/boundKeyField.js +34 -0
  155. package/dist/shared/util/canonicalJson.d.ts +11 -0
  156. package/dist/shared/util/canonicalJson.js +28 -0
  157. package/dist/shared/util/joinKeyFields.d.ts +20 -0
  158. package/dist/shared/util/joinKeyFields.js +22 -0
  159. package/dist/shared/wire/LambderAnswerHeaders.d.ts +12 -16
  160. package/dist/shared/wire/LambderAnswerHeaders.js +12 -16
  161. package/dist/shared/wire/LambderApiContract.d.ts +98 -53
  162. package/dist/shared/wire/LambderApiOutcome.d.ts +43 -31
  163. package/dist/shared/wire/LambderApiOutcome.js +48 -23
  164. package/dist/shared/wire/LambderApiRefusal.d.ts +45 -27
  165. package/dist/shared/wire/LambderApiRefusal.js +42 -7
  166. package/dist/shared/wire/LambderApiSignature.d.ts +18 -22
  167. package/dist/shared/wire/LambderApiSignature.js +16 -19
  168. package/dist/shared/wire/LambderCallOptions.d.ts +38 -47
  169. package/dist/shared/wire/LambderCallOptions.js +9 -11
  170. package/dist/shared/wire/LambderCompressionCodec.d.ts +29 -34
  171. package/dist/shared/wire/LambderCompressionCodec.js +31 -36
  172. package/dist/shared/wire/LambderCompressionOption.d.ts +9 -9
  173. package/dist/shared/wire/LambderCompressionOption.js +9 -9
  174. package/dist/shared/wire/LambderCrashDetail.d.ts +12 -15
  175. package/dist/shared/wire/LambderCrashDetail.js +12 -15
  176. package/dist/shared/wire/LambderDefaultApiPath.d.ts +6 -0
  177. package/dist/shared/wire/LambderDefaultApiPath.js +6 -0
  178. package/dist/shared/wire/LambderHttpStatus.d.ts +6 -7
  179. package/dist/shared/wire/LambderIdempotencyKeyScope.d.ts +89 -0
  180. package/dist/shared/wire/LambderIdempotencyKeyScope.js +146 -0
  181. package/dist/shared/wire/LambderInvokeApiId.d.ts +27 -0
  182. package/dist/shared/wire/LambderInvokeApiId.js +27 -0
  183. package/dist/shared/wire/LambderOutcomeAssertions.d.ts +6 -7
  184. package/dist/shared/wire/LambderOutcomeAssertions.js +6 -7
  185. package/dist/shared/wire/LambderRequestPayload.d.ts +18 -20
  186. package/dist/shared/wire/LambderRequestPayload.js +4 -6
  187. package/dist/shared/wire/LambderUploadObjectFields.d.ts +10 -0
  188. package/dist/shared/wire/LambderUploadObjectFields.js +24 -0
  189. package/dist/shared/wire/LambderUploadRefusal.d.ts +9 -0
  190. package/dist/shared/wire/LambderUploadRefusal.js +18 -0
  191. package/dist/shared/wire/LambderUploadSchemas.d.ts +12 -0
  192. package/dist/shared/wire/LambderUploadSchemas.js +30 -0
  193. package/dist/stores/LambderCacheFiller.d.ts +48 -0
  194. package/dist/stores/LambderCacheFiller.js +119 -0
  195. package/dist/stores/LambderCacheKeys.d.ts +26 -0
  196. package/dist/stores/LambderCacheKeys.js +54 -0
  197. package/dist/stores/LambderCacheValues.d.ts +45 -0
  198. package/dist/stores/LambderCacheValues.js +74 -0
  199. package/dist/stores/LambderDdbCache.d.ts +121 -56
  200. package/dist/stores/LambderDdbCache.js +528 -225
  201. package/dist/stores/LambderDdbIdempotencyStore.d.ts +33 -22
  202. package/dist/stores/LambderDdbIdempotencyStore.js +75 -50
  203. package/dist/stores/LambderDdbRateLimiter.d.ts +76 -20
  204. package/dist/stores/LambderDdbRateLimiter.js +151 -39
  205. package/dist/stores/LambderDdbSdk.d.ts +43 -31
  206. package/dist/stores/LambderDdbSdk.js +80 -38
  207. package/dist/stores/LambderDdbSessionStore.d.ts +27 -14
  208. package/dist/stores/LambderDdbSessionStore.js +119 -47
  209. package/dist/stores/LambderHttpFileSource.d.ts +15 -6
  210. package/dist/stores/LambderHttpFileSource.js +15 -13
  211. package/dist/stores/LambderMemoryCache.d.ts +49 -0
  212. package/dist/stores/LambderMemoryCache.js +113 -0
  213. package/dist/stores/LambderMemoryIdempotencyStore.d.ts +13 -12
  214. package/dist/stores/LambderMemoryIdempotencyStore.js +31 -30
  215. package/dist/stores/LambderMemoryRateLimiter.d.ts +8 -9
  216. package/dist/stores/LambderMemoryRateLimiter.js +14 -13
  217. package/dist/stores/LambderMemorySessionStore.d.ts +14 -11
  218. package/dist/stores/LambderMemorySessionStore.js +38 -19
  219. package/dist/stores/LambderMemoryUploadBucket.d.ts +99 -0
  220. package/dist/stores/LambderMemoryUploadBucket.js +219 -0
  221. package/dist/stores/LambderS3FileSource.d.ts +21 -6
  222. package/dist/stores/LambderS3FileSource.js +12 -7
  223. package/dist/stores/LambderS3UploadBucket.d.ts +73 -0
  224. package/dist/stores/LambderS3UploadBucket.js +144 -0
  225. package/dist/stores/LambderSdkInstallHint.d.ts +11 -0
  226. package/dist/stores/LambderSdkInstallHint.js +14 -0
  227. package/dist/testing/LambderTestApp.d.ts +23 -25
  228. package/dist/testing/LambderTestApp.js +22 -24
  229. package/dist/testing/LambderTestVisitor.d.ts +10 -12
  230. package/dist/testing/LambderTestVisitor.js +15 -15
  231. package/dist/testing.d.ts +3 -0
  232. package/dist/testing.js +2 -0
  233. package/package.json +26 -3
  234. package/dist/api/LambderApiPolicyEngine.d.ts +0 -47
  235. package/dist/api/LambderApiPolicyEngine.js +0 -85
  236. package/dist/shared/util/LambderKeyFields.d.ts +0 -32
  237. package/dist/shared/util/LambderKeyFields.js +0 -34
package/dist/client.d.ts CHANGED
@@ -20,10 +20,12 @@ export type { LambderApiSignatureMap } from "./shared/wire/LambderApiSignature.j
20
20
  export { RELOAD_LOOP_WINDOW_MS } from "./client/LambderReloadLoopBreaker.js";
21
21
  export { compareDottedVersions, isDottedVersion } from "./shared/wire/LambderVersionOrder.js";
22
22
  export type { LambderApiAnswerOutcome, LambderApiSuccessOutcome, LambderApiCallFailure, LambderApiValidationFailure, LambderApiEnvelopeFailure, LambderApiHttpAnswer, } from "./shared/wire/LambderApiOutcome.js";
23
- export type { LambderApiOutcome, LambderApiFailureReason, LambderValidationError, LambderCallOptions, LambderCallerOptions, LambderGuardInputsProvider, LambderProvidedGuardInputs, LambderIdempotencyKeyScope, LambderLogListHandler, } from "./client/LambderCaller.js";
24
- export { LambderApiRefusal, isLambderApiRefusal, refuse, LAMBDER_REFUSAL_CODES } from "./shared/wire/LambderApiRefusal.js";
23
+ export type { LambderApiOutcome, LambderApiFailureReason, LambderValidationError, LambderCallOptions, LambderCallerOptions, LambderGuardInputsProvider, LambderProvidedGuardInputs, LambderLogListHandler, } from "./client/LambderCaller.js";
24
+ export { createIdempotencyKey, createIdempotencyKeyScope } from "./shared/wire/LambderIdempotencyKeyScope.js";
25
+ export type { LambderIdempotencyKeyScope } from "./shared/wire/LambderIdempotencyKeyScope.js";
26
+ export { LambderApiRefusal, isLambderApiRefusal, refuse, refusalMessageOf, LAMBDER_REFUSAL_CODES } from "./shared/wire/LambderApiRefusal.js";
25
27
  export type { LambderApiRefusalOptions, LambderRefusalMessage, LambderAppRefusalMessage, LambderRefusalCode, LambderRefuseOptions } from "./shared/wire/LambderApiRefusal.js";
26
- export type { LambderApiContractShape, LambderApiMode, LambderApiEnvelopeBody, LambderApiResponseConfig, LambderGuardNamesIn, LambderContractMode, LambderContractKeysWithMode, LambderContractGuardsOf, LambderContractGuardNames, LambderContractGuardInputsOf, LambderContractGuardInput, LambderContractGuardInputNames, LambderContractRateLimitOf, LambderContractRateLimitNames, LambderContractIdempotencyOf, } from "./shared/wire/LambderApiContract.js";
28
+ export type { LambderApiContractShape, LambderApiMode, LambderApiEnvelopeBody, LambderApiResponseConfig, LambderGuardNamesIn, LambderContractMode, LambderContractKeysWithMode, LambderContractKeysWithGuard, LambderJsonOf, LambderJsonOutputOf, LambderContractGuardsOf, LambderContractGuardNames, LambderContractGuardInputsOf, LambderContractGuardInput, LambderContractGuardInputNames, LambderContractRateLimitOf, LambderContractRateLimitNames, LambderContractIdempotencyOf, } from "./shared/wire/LambderApiContract.js";
27
29
  export { describeCrash, errorFromCrashDetail } from "./shared/wire/LambderCrashDetail.js";
28
30
  export type { LambderCrashDetail, LambderCrashCause } from "./shared/wire/LambderCrashDetail.js";
29
31
  export { compressPayloadGzip, isRequestCompressionAvailable, COMPRESSED_PAYLOAD_GZ_FIELD, COMPRESSED_PAYLOAD_BR_FIELD, COMPRESSED_PAYLOAD_BYTES_FIELD, DEFAULT_REQUEST_COMPRESSION_SETTINGS, } from "./shared/wire/LambderRequestPayload.js";
@@ -34,3 +36,7 @@ export { html, xml, raw, jsonScript, escapeHtml, renderHtmlValue, LambderSafeHtm
34
36
  export { createLambderI18n } from "./shared/LambderI18n.js";
35
37
  export type { LambderLanguageMeta, LambderI18nConfig, LambderI18nInstance, LambderI18nTranslator, LambderI18nExtractParams, LambderI18nDictionaryLoader, LambderI18nCodes, LambderI18nKeys, LambderI18nTranslatorFor, } from "./shared/LambderI18n.js";
36
38
  export type { LambderHttpStatusCode } from "./shared/wire/LambderHttpStatus.js";
39
+ export { LambderUploadRunner, LambderUploadError } from "./client/LambderUploadRunner.js";
40
+ export type { LambderUploadRunnerOptions, LambderUploadProgress, LambderUploadPhase, LambderUploadFailureReason } from "./client/LambderUploadRunner.js";
41
+ export { checkUploadRule } from "./shared/contracts/LambderUploadBucket.js";
42
+ export type { LambderUploadRule, LambderUploadFileFacts, LambderUploadTicket, LambderUploadRuleVerdict } from "./shared/contracts/LambderUploadBucket.js";
package/dist/client.js CHANGED
@@ -19,9 +19,10 @@ export { resolveApiOutcome } from "./shared/wire/LambderApiOutcome.js";
19
19
  export { apiNameKeyOf, lookupApiSignature, readApiSignature, API_SIGNATURE_HEX_LENGTH, extensibleEnum } from "./shared/wire/LambderApiSignature.js";
20
20
  export { RELOAD_LOOP_WINDOW_MS } from "./client/LambderReloadLoopBreaker.js";
21
21
  export { compareDottedVersions, isDottedVersion } from "./shared/wire/LambderVersionOrder.js";
22
+ export { createIdempotencyKey, createIdempotencyKeyScope } from "./shared/wire/LambderIdempotencyKeyScope.js";
22
23
  // Typed API refusals (isomorphic: shared code may throw them from anywhere;
23
24
  // in the browser they are plain Errors).
24
- export { LambderApiRefusal, isLambderApiRefusal, refuse, LAMBDER_REFUSAL_CODES } from "./shared/wire/LambderApiRefusal.js";
25
+ export { LambderApiRefusal, isLambderApiRefusal, refuse, refusalMessageOf, LAMBDER_REFUSAL_CODES } from "./shared/wire/LambderApiRefusal.js";
25
26
  // A crash described for a caller allowed to see it (the envelope's `crash` field; pure, no Node built-ins).
26
27
  export { describeCrash, errorFromCrashDetail } from "./shared/wire/LambderCrashDetail.js";
27
28
  // Request payload compression (browser-safe: gzip via CompressionStream, no Node built-ins).
@@ -32,3 +33,7 @@ export { resolveCompressionOption } from "./shared/wire/LambderCompressionOption
32
33
  export { html, xml, raw, jsonScript, escapeHtml, renderHtmlValue, LambderSafeHtml } from "./shared/LambderHtml.js";
33
34
  // Typed translations (standalone, isomorphic)
34
35
  export { createLambderI18n } from "./shared/LambderI18n.js";
36
+ // Direct uploads: the runner that takes a file from the browser straight to
37
+ // storage, and the vocabulary it shares with the server's bucket.
38
+ export { LambderUploadRunner, LambderUploadError } from "./client/LambderUploadRunner.js";
39
+ export { checkUploadRule } from "./shared/contracts/LambderUploadBucket.js";
@@ -18,16 +18,10 @@ import type { LambderApiIdempotencyOption } from "../shared/wire/LambderApiOptio
18
18
  import type { LambderApiGuard, LambderGuardMetaMap, LambderGuardsOption, LambderGuardDataOf, LambderGuardInputsOf } from "../api/LambderApiGuards.js";
19
19
  import type { LambderApiRateLimitPolicyConfig, LambderRateLimitOption } from "../api/LambderApiRateLimits.js";
20
20
  import type { LambderApiIdempotencyConfig } from "../api/LambderApiIdempotency.js";
21
- import type { LambderContractEntry, LambderMergeContract } from "../shared/wire/LambderApiContract.js";
21
+ import type { LambderContractEntry, LambderJsonOutputOf, LambderMergeContract } from "../shared/wire/LambderApiContract.js";
22
22
  import { type LambderHttpEvent, type LambderRenderContext, type LambderSessionRenderContext } from "./LambderContext.js";
23
23
  import type { MaybePromise } from "../shared/util/LambderTypeUtilities.js";
24
24
  import { 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 LambderNoExtraKeys, type LambderRequirableGuardsField, type LambderSessionEnabledInstance, type LambderSessionRouteHandler } from "./LambderCreateOptions.js";
25
- /**
26
- * The "created" hook: run once the instance exists, with the instance. It is
27
- * declared here rather than beside the other hooks in LambderCreateOptions
28
- * because its parameter is the class, and an options module that names the
29
- * class cannot be read without it.
30
- */
31
25
  /** Everything `lambder/testing` may put under a built instance: the pipeline's stores, and the source its files are read from. */
32
26
  export type LambderInstanceBackends = LambderPipelineBackends & {
33
27
  fileSource?: LambderFileSource;
@@ -36,6 +30,12 @@ export type LambderInstanceBackends = LambderPipelineBackends & {
36
30
  export type LambderInstanceBackendSwap = LambderPipelineBackendSwap & {
37
31
  files: boolean;
38
32
  };
33
+ /**
34
+ * The "created" hook: run once the instance exists, with the instance. It is
35
+ * declared here rather than beside the other hooks in LambderCreateOptions
36
+ * because its parameter is the class, and an options module that names the
37
+ * class cannot be read without it.
38
+ */
39
39
  export type LambderCreatedHook = (lambderInstance: Lambder<any, any, any, any, any, any, any, any>) => void | Promise<void>;
40
40
  /**
41
41
  * Main Lambder class for building type-safe serverless APIs. Create
@@ -50,7 +50,7 @@ export type LambderCreatedHook = (lambderInstance: Lambder<any, any, any, any, a
50
50
  * @typeParam _TIdempotencyEnabled - @internal True when create() received idempotency (do not pass manually)
51
51
  * @typeParam _TSessionGuardsRequired - @internal True when create() received requireSessionApiGuards (do not pass manually)
52
52
  * @typeParam _TPublicGuardsRequired - @internal True when create() received requirePublicApiGuards (do not pass manually)
53
- * @typeParam _TSessionsEnabled - @internal True when create() received the session option (do not pass manually). It defaults to TRUE, unlike its siblings: a plugin module annotates its parameter as the bare Lambder<SessionData>, and that annotation has to keep registering session APIs. create() is where the option is actually known, so create() is where the false comes from; `new Lambder(...)` keeps only the registration-time throw.
53
+ * @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.
54
54
  *
55
55
  * @example
56
56
  * ```typescript
@@ -68,20 +68,19 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
68
68
  /** The instance's file reader (source + caches), or null without the files option. */
69
69
  files: LambderFiles | null;
70
70
  /**
71
- * Type property for extracting the API contract
72
- * Use this to export your API types to the frontend
71
+ * Type property for extracting the API contract: every registered API's
72
+ * input, output, mode and declared options, as a client calls it.
73
73
  *
74
- * Export it as an interface extending LambderFlattenContract, not as a
75
- * type alias. Chaining builds the contract as an intersection one member
76
- * deep per endpoint, and an interface collapses that into one declared
77
- * set of members, which every generic read of the contract (a mock
78
- * registry, a needs map, the typed caller) is then far cheaper against.
79
- * See LambderFlattenContract for the measurements.
74
+ * A small app's client imports it as it is. It is an intersection one
75
+ * member deep per endpoint, so reading it generically costs a large app's
76
+ * client most of its type check; writeApiContract (lambder/build) reads
77
+ * this property off the exported instance and writes the contract out as
78
+ * plain types for such a client to import instead.
80
79
  *
81
80
  * @example
82
81
  * ```typescript
83
- * const lambder = new Lambder().addApi(...).addApi(...);
84
- * export interface ApiContractType extends LambderFlattenContract<typeof lambder.ApiContract> {}
82
+ * export const lambder = initLambder().create({ ... }).addApi(...).addApi(...);
83
+ * export type ApiContractType = typeof lambder.ApiContract;
85
84
  * ```
86
85
  */
87
86
  readonly ApiContract: _TContract;
@@ -108,24 +107,35 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
108
107
  private requireSessionApiGuards;
109
108
  /** Told what a request threw, beside whatever answers it; null outside a test. See LAMBDER_CRASH_WATCH. */
110
109
  private crashWatcher;
110
+ /** The crashes option applied: reporting, and the framework's own 500. */
111
+ private readonly crashHandling;
112
+ /** What this instance binds onto every context it renders (ctx.sessionController, ctx.rateLimit, ctx.isRateLimited). */
113
+ private readonly contextTools;
111
114
  private readonly trustedClientIpHeaders;
115
+ private readonly trustedHostHeaders;
112
116
  private requirePublicApiGuards;
113
117
  constructor(options?: LambderCreateOptions<TSessionData>);
114
118
  setRouteFallbackHandler(routeFallbackHandler: LambderFallbackHandler): this;
115
119
  setApiFallbackHandler(apiFallbackHandler: LambderFallbackHandler): this;
116
120
  setApiInputValidationErrorHandler(apiInputValidationErrorHandler: LambderInputValidationHandler): this;
117
121
  setGlobalErrorHandler(globalErrorHandler: LambderGlobalErrorHandler): this;
118
- /** Response for session routes when the session is missing/expired (non-API). Default: 401. */
122
+ /**
123
+ * Response for a session route when the session is missing or expired,
124
+ * and for any non-API request whose route or hook meets a
125
+ * LambderSessionNotFoundError (the session ended while the request held
126
+ * it, or a session read found none, or cookies naming several: a
127
+ * LambderSessionAmbiguousError). Default: 401.
128
+ */
119
129
  setSessionExpiredRouteHandler(handler: LambderFallbackHandler): this;
120
130
  /**
121
131
  * Terminal public-file layer. Runs only when no route matched, so it can
122
132
  * never shadow routes registered after it. Serves files from the `files`
123
133
  * source configured at creation, under the reader's path rule, mime-typed,
124
134
  * memory-cached, with the immutable-cache heuristic for content-hashed
125
- * assets. Only configured methods reach it, default GET/HEAD, as for
126
- * serveIndexHtml; a gated-out method and a path the source has no file
127
- * for both fall through to setRouteFallbackHandler, where the app decides
128
- * what remains (e.g. render an app shell with res.templateFile).
135
+ * assets. Only configured methods reach it (default GET/HEAD); a
136
+ * gated-out method or a path with no file falls through to
137
+ * setRouteFallbackHandler, where the app decides what remains (e.g.
138
+ * render an app shell with res.templateFile).
129
139
  */
130
140
  servePublicFiles(options?: LambderPublicFilesOptions): this;
131
141
  /**
@@ -138,28 +148,36 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
138
148
  * res.templateFile (markers optional) with no-cache.
139
149
  */
140
150
  serveIndexHtml(handler?: LambderFallbackHandler, options?: LambderIndexHtmlOptions): this;
141
- addRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: (ctx: LambderRenderContext<any, LambderPathParamsOf<TPath>>, resolver: LambderResolver) => MaybePromise<LambderResponse>): this;
151
+ addRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: (ctx: LambderRenderContext<any, LambderPathParamsOf<TPath>, {}, TSessionData, _TRateLimitPolicies>, resolver: LambderResolver) => MaybePromise<LambderResponse>): this;
142
152
  addRoute(condition: RegExp | LambderRouteConditionFn | LambderRouteMatcher, actionFn: LambderRouteHandler): this;
143
- addSessionRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: ((ctx: LambderSessionRenderContext<any, TSessionData, LambderPathParamsOf<TPath>>, resolver: LambderResolver) => MaybePromise<LambderResponse>) & LambderSessionEnabledInstance<_TSessionsEnabled>): this;
153
+ addSessionRoute<TPath extends LambderRoutePath>(condition: TPath, actionFn: ((ctx: LambderSessionRenderContext<any, TSessionData, LambderPathParamsOf<TPath>, {}, _TRateLimitPolicies>, resolver: LambderResolver) => MaybePromise<LambderResponse>) & LambderSessionEnabledInstance<_TSessionsEnabled>): this;
144
154
  addSessionRoute(condition: RegExp | LambderRouteConditionFn | LambderRouteMatcher, actionFn: LambderSessionRouteHandler<TSessionData> & LambderSessionEnabledInstance<_TSessionsEnabled>): this;
145
- addApi<TName extends string, TInput extends z.ZodType, TOutput extends z.ZodType, const TRateOpt extends LambderRateLimitOption<_TRateLimitPolicies, z.infer<TInput>, false> = never, const TGuardsOpt extends LambderGuardsOption<_TGuards, z.infer<TInput>, false> = never, const TIdempotencyOpt extends LambderApiIdempotencyOption = never>(name: TName, schema: {
155
+ addApi<TName extends string, TInput extends z.ZodType, TOutput extends z.ZodType, const TRateOpt extends LambderRateLimitOption<_TRateLimitPolicies, z.input<TInput>, false> = never, const TGuardsOpt extends LambderGuardsOption<_TGuards, z.input<TInput>, false> = never, const TIdempotencyOpt extends LambderApiIdempotencyOption = never>(name: TName, schema: {
146
156
  input: TInput;
147
157
  output: TOutput;
148
158
  } & {
149
- /** Named rate limits, checked in declared order before guards and validation: a name, a list of names, or a { name: true | override } map (windows overridable on perApi budgets, errorMessage on any). The first exceeded one refuses (429 envelope + Retry-After); attempts count on every counter checked before it. */
159
+ /** 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, errorMessage on any). The first exceeded one refuses (429 envelope + Retry-After); attempts count on every counter checked before it. */
150
160
  rateLimit?: TRateOpt;
151
161
  /** Replay-protect this API per client idempotencyKey. Requires the idempotency option at creation. */
152
162
  idempotency?: _TIdempotencyEnabled extends true ? TIdempotencyOpt : never;
153
- } & LambderRequirableGuardsField<_TPublicGuardsRequired, TGuardsOpt>, handler: (ctx: LambderRenderContext<z.infer<TInput>, Record<string, string>, LambderGuardDataOf<_TGuards, TGuardsOpt>>, resolver: LambderResolver<z.infer<TOutput>>) => MaybePromise<LambderResponse>): Lambder<TSessionData, LambderMergeContract<_TContract, TName, LambderContractEntry<z.infer<TInput>, z.infer<TOutput>, "public", LambderGuardInputsOf<_TGuards, TGuardsOpt>, TGuardsOpt, TRateOpt, TIdempotencyOpt>>, _TRateLimitPolicies, _TGuards, _TIdempotencyEnabled, _TSessionGuardsRequired, _TPublicGuardsRequired, _TSessionsEnabled>;
154
- addSessionApi<TName extends string, TInput extends z.ZodType, TOutput extends z.ZodType, const TRateOpt extends LambderRateLimitOption<_TRateLimitPolicies, z.infer<TInput>, true> = never, const TGuardsOpt extends LambderGuardsOption<_TGuards, z.infer<TInput>, true> = never, const TIdempotencyOpt extends LambderApiIdempotencyOption = never>(name: TName, schema: {
163
+ } & LambderRequirableGuardsField<_TPublicGuardsRequired, TGuardsOpt>, handler: (ctx: LambderRenderContext<z.infer<TInput>, Record<string, string>, LambderGuardDataOf<_TGuards, TGuardsOpt>, TSessionData, _TRateLimitPolicies>, resolver: LambderResolver<z.input<TOutput>>) => MaybePromise<LambderResponse>): Lambder<TSessionData, LambderMergeContract<_TContract, TName, LambderContractEntry<z.input<TInput>, LambderJsonOutputOf<z.output<TOutput>>, "public", LambderGuardInputsOf<_TGuards, TGuardsOpt>, TGuardsOpt, TRateOpt, TIdempotencyOpt>>, _TRateLimitPolicies, _TGuards, _TIdempotencyEnabled, _TSessionGuardsRequired, _TPublicGuardsRequired, _TSessionsEnabled>;
164
+ addSessionApi<TName extends string, TInput extends z.ZodType, TOutput extends z.ZodType, const TRateOpt extends LambderRateLimitOption<_TRateLimitPolicies, z.input<TInput>, true> = never, const TGuardsOpt extends LambderGuardsOption<_TGuards, z.input<TInput>, true> = never, const TIdempotencyOpt extends LambderApiIdempotencyOption = never>(name: TName, schema: {
155
165
  input: TInput;
156
166
  output: TOutput;
157
167
  } & {
158
- /** Named rate limits, checked in declared order before guards and validation: a name, a list of names, or a { name: true | override } map (windows overridable on perApi budgets, errorMessage on any). The first exceeded one refuses (429 envelope + Retry-After); attempts count on every counter checked before it. */
168
+ /** 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, errorMessage on any). The first exceeded one refuses (429 envelope + Retry-After); attempts count on every counter checked before it. */
159
169
  rateLimit?: TRateOpt;
160
170
  /** Replay-protect this API per client idempotencyKey. Requires the idempotency option at creation. */
161
171
  idempotency?: _TIdempotencyEnabled extends true ? TIdempotencyOpt : never;
162
- } & LambderRequirableGuardsField<_TSessionGuardsRequired, TGuardsOpt> & LambderSessionEnabledInstance<_TSessionsEnabled>, handler: (ctx: LambderSessionRenderContext<z.infer<TInput>, TSessionData, Record<string, string>, LambderGuardDataOf<_TGuards, TGuardsOpt>>, resolver: LambderResolver<z.infer<TOutput>>) => MaybePromise<LambderResponse>): Lambder<TSessionData, LambderMergeContract<_TContract, TName, LambderContractEntry<z.infer<TInput>, z.infer<TOutput>, "session", LambderGuardInputsOf<_TGuards, TGuardsOpt>, TGuardsOpt, TRateOpt, TIdempotencyOpt>>, _TRateLimitPolicies, _TGuards, _TIdempotencyEnabled, _TSessionGuardsRequired, _TPublicGuardsRequired, _TSessionsEnabled>;
172
+ } & LambderRequirableGuardsField<_TSessionGuardsRequired, TGuardsOpt> & LambderSessionEnabledInstance<_TSessionsEnabled>, handler: (ctx: LambderSessionRenderContext<z.infer<TInput>, TSessionData, Record<string, string>, LambderGuardDataOf<_TGuards, TGuardsOpt>, _TRateLimitPolicies>, resolver: LambderResolver<z.input<TOutput>>) => MaybePromise<LambderResponse>): Lambder<TSessionData, LambderMergeContract<_TContract, TName, LambderContractEntry<z.input<TInput>, LambderJsonOutputOf<z.output<TOutput>>, "session", LambderGuardInputsOf<_TGuards, TGuardsOpt>, TGuardsOpt, TRateOpt, TIdempotencyOpt>>, _TRateLimitPolicies, _TGuards, _TIdempotencyEnabled, _TSessionGuardsRequired, _TPublicGuardsRequired, _TSessionsEnabled>;
173
+ /**
174
+ * What registering an API is, for addApi and addSessionApi alike: the
175
+ * checks that can refuse it, then its definition recorded (what
176
+ * apiSignatures() digests) and its action appended to the first-match
177
+ * chain. The two public methods differ only in the mode and in the types
178
+ * they give the handler.
179
+ */
180
+ private registerApi;
163
181
  addHook(hookEvent: 'created', hookFn: LambderCreatedHook, priority?: number): this;
164
182
  addHook(hookEvent: 'beforeRender', hookFn: LambderBeforeRenderHook, priority?: number): this;
165
183
  addHook(hookEvent: 'afterRender', hookFn: LambderAfterRenderHook, priority?: number): this;
@@ -184,9 +202,11 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
184
202
  addAction(filter: (event: unknown, ctx: LambderRenderContext | null) => boolean, actionFn: (event: unknown, tools: LambderActionTools) => MaybePromise<unknown>): this;
185
203
  use<_TNewContract extends Record<string, any>>(plugin: (lambder: Lambder<TSessionData, _TContract, any, any, any, any, any, any>) => Lambder<TSessionData, _TNewContract, any, any, any, any, any, any>): Lambder<TSessionData, _TNewContract extends _TContract ? _TNewContract : (_TContract & _TNewContract), _TRateLimitPolicies, _TGuards, _TIdempotencyEnabled, _TSessionGuardsRequired, _TPublicGuardsRequired, _TSessionsEnabled>;
186
204
  /**
187
- * Sessions for this request: what handlers create, rotate, refresh and
188
- * end sessions with. An API call presents its posted CSRF token; a route
189
- * presents cookies alone.
205
+ * A session controller for a context: what creates, rotates, refreshes
206
+ * and ends sessions. An API call presents its posted CSRF token; a route
207
+ * presents cookies alone. A context this instance renders already
208
+ * carries one as `ctx.sessionController`; this is for a context it did
209
+ * not render, such as one createContext() built from an event on its own.
190
210
  */
191
211
  getSessionController(ctx: LambderRenderContext | LambderSessionRenderContext<any, TSessionData>): LambderSessionController<TSessionData>;
192
212
  /** The session manager, for code that works on sessions outside a request (maintenance, tests). */
@@ -208,24 +228,22 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
208
228
  /**
209
229
  * Every registered endpoint's signature, keyed by its hashed name: the
210
230
  * LambderApiSignatureMap both sides ship with. A generator imports the
211
- * finished instance, awaits this, and writes the result to a file the
212
- * frontend passes to LambderCaller as apiSignatures and the server passes
213
- * to create() as apiSignatures; at request time the pipeline compares a
214
- * call's signature with the server's copy of the same map. This is the
215
- * one place a digest is computed, so it has nothing to agree with but
216
- * itself. Keys are sorted, so the generated file diffs by endpoint.
231
+ * finished instance, awaits this, and writes a file that LambderCaller
232
+ * and create() both take as apiSignatures; at request time the pipeline
233
+ * compares a call's signature with the server's copy. This is the only
234
+ * place a digest is computed, so there is no second computation to drift
235
+ * from it. Keys are sorted, so the generated file diffs by endpoint.
217
236
  */
218
237
  apiSignatures(): Promise<LambderApiSignatureMap>;
219
238
  /**
220
- * The same signatures with the endpoint name each one was digested from,
221
- * sorted by key as the map is. What apiSignatures() leaves out on purpose:
222
- * the map a client ships lists no names, so a generator that only had the
223
- * map could report that four signatures changed but not which endpoints.
224
- * Reading this instead, it can name them.
239
+ * The same signatures, sorted by key as the map is, with the endpoint
240
+ * name each was digested from. The map a client ships deliberately lists
241
+ * no names, so a generator reading only the map could say how many
242
+ * signatures changed but not which endpoints; this lets it name them.
225
243
  *
226
- * A build-time view by construction. It comes off the server instance,
227
- * which a generator imports and a client never does, so nothing here
228
- * reaches a bundle unless the generator writes it there.
244
+ * A build-time view: it comes off the server instance, which a generator
245
+ * imports and a client never does, so nothing here reaches a bundle
246
+ * unless the generator writes it there.
229
247
  */
230
248
  apiSignatureEntries(): Promise<LambderApiSignatureEntry[]>;
231
249
  getResponseBuilder(ctx?: LambderRenderContext): LambderResponseBuilder<any>;
@@ -239,38 +257,84 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
239
257
  * The beforeRender hooks, in priority order: the replaced context to
240
258
  * continue with, or the response one of them answered with.
241
259
  *
242
- * Its own method because BOTH request paths run it. Left inline after the
243
- * match, it ran for routes and APIs and for nothing else, so a
244
- * servePublicFiles or serveIndexHtml answer, which is every asset and
245
- * every app-shell page, skipped the one hook that can inspect a request,
246
- * replace its context or short-circuit it: a security header written in a
247
- * hook reached the API answers and not the HTML it was written for, and a
248
- * maintenance-mode hook served the whole frontend anyway.
260
+ * Its own method because both request paths run it. Run only after a
261
+ * match, it would skip every servePublicFiles and serveIndexHtml answer
262
+ * (every asset and app-shell page): a security header written in a hook
263
+ * would miss the HTML it was written for, and a maintenance-mode hook
264
+ * would still serve the whole frontend.
265
+ *
266
+ * Each replacement is also handed to `onContextReplaced` as it is made,
267
+ * rather than only returned: render() answers from it after the handler
268
+ * too (the afterRender hooks, a crash's report, reveal and global error
269
+ * handler), and a handler or a later hook that throws returns nothing.
249
270
  */
250
271
  private runBeforeRenderHooks;
251
272
  private handleNoMatchedAction;
252
273
  /**
253
274
  * True for the OPTIONS request the CORS layer answers by itself. Asked
254
- * twice: once to build the 204, once at the end of render() to decide
255
- * which form of the headers goes on. Asking once and letting the tail
256
- * apply the ordinary headers on top of the 204's would put both forms on
257
- * a preflight, answering `Vary: Origin, Origin` and an
258
- * Access-Control-Expose-Headers that means nothing before a request.
275
+ * twice: once to build the 204, once at the end of render() to pick which
276
+ * form of the headers goes on. Applying the ordinary headers on top of
277
+ * the 204's would put both forms on a preflight: `Vary: Origin, Origin`
278
+ * and an Access-Control-Expose-Headers that means nothing before a
279
+ * request.
259
280
  */
260
281
  private isCorsPreflight;
261
282
  private resolveRequest;
262
283
  render(event: LambderHttpEvent, lambdaContext: Context): Promise<LambderHttpResponse>;
284
+ /**
285
+ * A thrown value that is an answer rather than a crash, as the response;
286
+ * anything else is rethrown to the crash path.
287
+ *
288
+ * - A LambderResponse IS the response (res.die.*, throw res.html(...)).
289
+ * - A LambderApiRefusal on an API call is its structured refusal
290
+ * (brand-checked, not instanceof, to survive duplicate installs).
291
+ * - A LambderSessionNotFoundError is a missing session: one that ended
292
+ * while the request held it (a logout or a password change landing
293
+ * mid-request), or one a route or hook asked for that the request
294
+ * never had or whose cookies named several (its subclass
295
+ * LambderSessionAmbiguousError). It is answered the way a missing
296
+ * session is answered here, the decision the API pipeline makes for a
297
+ * handler, applied to the routes and hooks it never sees.
298
+ */
299
+ private answerThrown;
300
+ /**
301
+ * A crash, from the thrown value to the answer. It is told to the test
302
+ * watch and reported before anything answers, so the report depends on
303
+ * nothing the answer might break; then the app's global error handler
304
+ * answers it, or the framework's own 500 does when there is none or it
305
+ * failed too.
306
+ */
307
+ private answerCrash;
308
+ /**
309
+ * An answer to a crash, carrying what the call wrote and its CORS headers.
310
+ * As on the success path, headers belong to the call: a call that wrote a
311
+ * session cookie and then threw still owes the browser that cookie, and a
312
+ * cross-origin caller cannot read the error at all without CORS headers.
313
+ * The CORS verdict is the one the request settled before it crashed, so
314
+ * answering a crash runs none of the app's code.
315
+ */
316
+ private withCallHeaders;
263
317
  /**
264
318
  * Fetch the session for a session route or short-circuit it with the
265
- * sessionExpiredRouteHandler response (default 401). Session APIs never
266
- * come through here: the pipeline answers them with the protocol's
267
- * { sessionExpired: true } envelope itself.
319
+ * answer for a missing session. Session APIs never come through here:
320
+ * the pipeline answers them with the protocol's { sessionExpired: true }
321
+ * envelope itself.
268
322
  */
269
323
  private requireSession;
270
- /** Dispatch a non-HTTP Lambda event to the registered actions. */
324
+ /**
325
+ * The answer to a request that needed a session and has none, whether it
326
+ * never had one or it ended while the request held it: an API call gets
327
+ * the protocol's sessionExpired envelope, as the pipeline gives a session
328
+ * API, and anything else the setSessionExpiredRouteHandler answer, a 401
329
+ * by default.
330
+ */
331
+ private sessionMissingResponse;
332
+ /**
333
+ * Dispatch a non-HTTP Lambda event to the registered actions. What an
334
+ * action throws is reported (crashes.report) and then rethrown untouched,
335
+ * so Lambda's retries and dead-letter queues still see the failure.
336
+ */
271
337
  renderEvent(event: unknown, lambdaContext: Context): Promise<unknown>;
272
- /** Registration-time checks shared by addApi/addSessionApi. */
273
- private assertApiRegistration;
274
338
  /**
275
339
  * The answer for a rejected input: the app's
276
340
  * setApiInputValidationErrorHandler when set, otherwise the standard 422
@@ -284,7 +348,8 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
284
348
  * via res.die.*) becomes the answer the pipeline stores and hands back.
285
349
  * The context is the pipeline's context, so a session it fetched is on
286
350
  * ctx.session and the validated payload is on ctx.apiPayload when the
287
- * handler runs.
351
+ * handler runs. The handler's resolver knows the API's output schema, so
352
+ * every success payload is parsed through it before it is sent.
288
353
  */
289
354
  private runApi;
290
355
  /** A thrown LambderApiRefusal (from a hook, say) as the structured API envelope: the core's one mapping. */
@@ -292,11 +357,10 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
292
357
  }
293
358
  /**
294
359
  * The canonical way to create an instance: fix the session data type first,
295
- * then create with the full configuration in one declaration; the policy,
296
- * guard, and idempotency types are INFERRED from the options, so the
297
- * instance is born fully typed and `typeof lambderApp` is the annotation
298
- * type for api modules. No enable/define chain exists, so there are no
299
- * ordering rules and nothing can be half-configured.
360
+ * then create with the full configuration in one declaration. The policy,
361
+ * guard and idempotency types are inferred from the options, so the instance
362
+ * is born fully typed and `typeof lambderApp` is the annotation type for api
363
+ * modules. There are no ordering rules, and nothing can be half-configured.
300
364
  *
301
365
  * ```typescript
302
366
  * // app.ts (imports no api modules, so modules can import the type back)
@@ -317,16 +381,16 @@ export default class Lambder<TSessionData = any, _TContract extends Record<strin
317
381
  * export const handler = lambder.getHandler();
318
382
  * ```
319
383
  *
320
- * Why curried (`initLambder<S>().create(...)` rather than
321
- * `new Lambder<S>(...)`): TypeScript type arguments are all-or-nothing per
322
- * call, so explicitly passing the session data type to the constructor
323
- * would silently WIDEN the inferred policy and guard types to their {}
324
- * defaults. Fixing the session type in the first call lets the second call
325
- * infer everything else from the options. `new Lambder(options)` remains
326
- * for untyped or session-data-free instances.
384
+ * Curried because TypeScript type arguments are all-or-nothing per call:
385
+ * passing the session data type to `new Lambder<S>(...)` would silently
386
+ * widen the inferred policy and guard types to their {} defaults. Fixing the
387
+ * session type in the first call lets the second infer everything else.
388
+ * `new Lambder(options)` serves untyped or session-data-free instances.
327
389
  */
328
390
  export declare const initLambder: <TSessionData = any>() => {
329
391
  create<const TOptions extends LambderCreateOptions<TSessionData>>(options: LambderNoExtraKeys<TOptions, LambderCreateOptions<TSessionData>> & LambderNestedOptionChecks<TSessionData, TOptions>): Lambder<TSessionData, {}, TOptions["rateLimits"] extends {
330
392
  policies: infer TPolicies extends Record<string, LambderApiRateLimitPolicyConfig>;
331
393
  } ? TPolicies : {}, TOptions["guards"] extends Record<string, LambderApiGuard<any, any, any>> ? LambderGuardMetaMap<TOptions["guards"]> : {}, TOptions["idempotency"] extends LambderApiIdempotencyConfig ? true : false, [LambderGivenOption<TOptions, "requireSessionApiGuards">] extends [false | undefined] ? false : true, [LambderGivenOption<TOptions, "requirePublicApiGuards">] extends [false | undefined] ? false : true, [LambderGivenOption<TOptions, "session">] extends [undefined] ? false : true>;
394
+ guard: import("../api/LambderApiGuards.js").LambderGuardBuilder<LambderRenderContext<any, Record<string, string>, {}, TSessionData>, LambderSessionRenderContext<any, TSessionData>>;
395
+ rateLimitKey: import("../api/LambderApiRateLimits.js").LambderRateLimitKeyBuilder<LambderRenderContext<any, Record<string, string>, {}, TSessionData>>;
332
396
  };