lambder 14.1.1 → 15.0.2
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 +429 -0
- package/README.md +14 -17
- package/dist/api/LambderApiDeclarations.d.ts +11 -5
- package/dist/api/LambderApiDefinition.d.ts +2 -1
- package/dist/api/LambderApiEnvelope.d.ts +2 -2
- package/dist/api/LambderApiEnvelope.js +8 -2
- package/dist/api/LambderApiGuards.d.ts +44 -5
- package/dist/api/LambderApiGuards.js +27 -0
- package/dist/api/LambderApiIdempotency.d.ts +14 -7
- package/dist/api/LambderApiIdempotency.js +39 -27
- package/dist/api/LambderApiPipeline.d.ts +25 -11
- package/dist/api/LambderApiPipeline.js +34 -17
- package/dist/api/LambderApiRateLimits.d.ts +28 -21
- package/dist/api/LambderApiRateLimits.js +55 -35
- package/dist/api/LambderApiRefusals.d.ts +10 -4
- package/dist/api/LambderApiRefusals.js +31 -5
- package/dist/api/LambderApiRequest.d.ts +21 -1
- package/dist/api/LambderApiRequest.js +31 -2
- package/dist/build/checkApiRefusals.d.ts +8 -3
- package/dist/build/checkApiRefusals.js +80 -29
- package/dist/build/contractPrinterProcess.d.ts +11 -0
- package/dist/build/contractPrinterProcess.js +17 -0
- package/dist/build/generateApiFiles.d.ts +26 -5
- package/dist/build/generateApiFiles.js +68 -7
- package/dist/build/writeApiSchemas.d.ts +109 -0
- package/dist/build/writeApiSchemas.js +308 -0
- package/dist/build.d.ts +3 -1
- package/dist/build.js +2 -0
- package/dist/client/LambderCaller.d.ts +25 -11
- package/dist/client/LambderCaller.js +57 -49
- package/dist/client/LambderUploadRunner.d.ts +55 -27
- package/dist/client/LambderUploadRunner.js +89 -34
- package/dist/client.d.ts +6 -6
- package/dist/client.js +2 -2
- package/dist/core/Lambder.d.ts +31 -21
- package/dist/core/Lambder.js +79 -23
- package/dist/core/LambderCallSummary.d.ts +1 -1
- package/dist/core/LambderContext.d.ts +59 -7
- package/dist/core/LambderContext.js +31 -15
- package/dist/core/LambderCrashHandling.d.ts +5 -0
- package/dist/core/LambderCrashHandling.js +11 -1
- package/dist/core/LambderCreateOptions.d.ts +28 -17
- package/dist/core/LambderCreateOptions.js +14 -7
- package/dist/core/LambderResolver.d.ts +3 -2
- package/dist/core/LambderResponseBuilder.d.ts +20 -9
- package/dist/core/LambderResponseBuilder.js +39 -8
- package/dist/core/LambderTemplatingEngine.d.ts +24 -6
- package/dist/core/LambderTemplatingEngine.js +23 -3
- package/dist/index.d.ts +15 -12
- package/dist/index.js +7 -5
- package/dist/invoke/LambderInvokeCaller.d.ts +25 -4
- package/dist/invoke/LambderInvokeCaller.js +47 -9
- package/dist/invoke/LambderInvokeOutcome.d.ts +7 -6
- package/dist/mock/LambderMockAdapterDoor.d.ts +40 -0
- package/dist/mock/LambderMockAdapterDoor.js +10 -0
- package/dist/mock/LambderMockApiSchemas.d.ts +28 -0
- package/dist/mock/LambderMockApiSchemas.js +150 -0
- package/dist/mock/LambderMockApp.d.ts +56 -48
- package/dist/mock/LambderMockApp.js +107 -62
- package/dist/mock/LambderMockBrowserCookies.js +18 -5
- package/dist/mock/LambderMockCreateOptions.d.ts +51 -4
- package/dist/mock/LambderMockFailureInjector.d.ts +12 -3
- package/dist/mock/LambderMockFailureInjector.js +12 -8
- package/dist/mock/LambderMockTypes.d.ts +8 -4
- package/dist/mock/lambderMockInvokeTransport.js +2 -9
- package/dist/mock/lambderMockMswHandler.d.ts +19 -13
- package/dist/mock/lambderMockMswHandler.js +25 -22
- package/dist/mock.d.ts +1 -0
- package/dist/secrets/LambderOneShotSecrets.d.ts +1 -1
- package/dist/secrets/LambderOneShotSecrets.js +6 -36
- package/dist/secrets/LambderPasswordHasher.d.ts +56 -0
- package/dist/secrets/LambderPasswordHasher.js +168 -0
- package/dist/session/LambderSessionController.d.ts +37 -4
- package/dist/session/LambderSessionController.js +36 -6
- package/dist/session/LambderSessionManager.d.ts +33 -3
- package/dist/session/LambderSessionManager.js +55 -16
- package/dist/shared/LambderHtml.d.ts +23 -4
- package/dist/shared/LambderHtml.js +17 -5
- package/dist/shared/LambderI18n.d.ts +106 -16
- package/dist/shared/LambderI18n.js +259 -74
- package/dist/shared/contracts/LambderCache.d.ts +14 -1
- package/dist/shared/contracts/LambderRateLimiter.d.ts +5 -6
- package/dist/shared/transport/LambderApiTransport.d.ts +3 -2
- package/dist/shared/util/LambderBackoffTimer.d.ts +24 -13
- package/dist/shared/util/LambderBackoffTimer.js +40 -12
- package/dist/shared/util/LambderCallAbort.d.ts +22 -6
- package/dist/shared/util/LambderCallAbort.js +37 -9
- package/dist/shared/util/LambderErrorReportMark.d.ts +4 -0
- package/dist/shared/util/LambderErrorReportMark.js +22 -0
- package/dist/shared/util/LambderKeyFieldDigest.d.ts +46 -0
- package/dist/shared/util/LambderKeyFieldDigest.js +75 -0
- package/dist/shared/util/LambderSignedClaims.d.ts +19 -0
- package/dist/shared/util/LambderSignedClaims.js +54 -0
- package/dist/shared/util/LambderSwappableInstances.d.ts +29 -0
- package/dist/shared/util/LambderSwappableInstances.js +54 -0
- package/dist/shared/util/LambderTestingDoors.d.ts +6 -2
- package/dist/shared/util/LambderTestingDoors.js +6 -2
- package/dist/shared/util/LambderTextDigest.d.ts +5 -5
- package/dist/shared/util/LambderTextDigest.js +5 -5
- package/dist/shared/wire/LambderApiContract.d.ts +1 -1
- package/dist/shared/wire/LambderApiOptionEntries.d.ts +9 -1
- package/dist/shared/wire/LambderApiOptionEntries.js +15 -0
- package/dist/shared/wire/LambderApiOptionValues.d.ts +3 -2
- package/dist/shared/wire/LambderApiOutcome.d.ts +37 -19
- package/dist/shared/wire/LambderApiOutcome.js +1 -1
- package/dist/shared/wire/LambderApiRefusal.d.ts +39 -12
- package/dist/shared/wire/LambderApiRefusal.js +3 -3
- package/dist/shared/wire/LambderApiSchemaEntries.d.ts +21 -0
- package/dist/shared/wire/LambderApiSchemaEntries.js +18 -0
- package/dist/shared/wire/LambderCallOptions.d.ts +3 -3
- package/dist/shared/wire/LambderCallOutcome.d.ts +2 -1
- package/dist/shared/wire/LambderCallOutcome.js +3 -2
- package/dist/shared/wire/LambderIdempotencyKeyScope.d.ts +5 -3
- package/dist/shared/wire/LambderIdempotencyKeyScope.js +5 -3
- package/dist/shared/wire/LambderInvokeApiId.d.ts +3 -3
- package/dist/shared/wire/LambderInvokeApiId.js +3 -3
- package/dist/shared/wire/LambderOutcomeAssertions.d.ts +7 -6
- package/dist/shared/wire/LambderOutcomeAssertions.js +1 -1
- package/dist/stores/LambderCacheValues.d.ts +2 -5
- package/dist/stores/LambderDdbCache.d.ts +15 -9
- package/dist/stores/LambderDdbCache.js +25 -6
- package/dist/stores/LambderDdbIdempotencyStore.d.ts +6 -4
- package/dist/stores/LambderDdbIdempotencyStore.js +32 -52
- package/dist/stores/LambderDdbOneShotSecretStore.d.ts +11 -0
- package/dist/stores/LambderDdbOneShotSecretStore.js +17 -5
- package/dist/stores/LambderDdbSdk.d.ts +59 -29
- package/dist/stores/LambderDdbSdk.js +116 -44
- package/dist/stores/LambderDdbSessionStore.d.ts +26 -11
- package/dist/stores/LambderDdbSessionStore.js +133 -68
- package/dist/stores/LambderMemoryCache.d.ts +2 -2
- package/dist/stores/LambderS3FileSource.d.ts +3 -2
- package/dist/stores/LambderS3FileSource.js +11 -13
- package/dist/stores/LambderS3UploadBucket.d.ts +12 -0
- package/dist/stores/LambderS3UploadBucket.js +23 -0
- package/dist/stores/LambderStorageBackedCache.d.ts +2 -2
- package/dist/stores/LambderStoredText.d.ts +26 -0
- package/dist/stores/LambderStoredText.js +25 -0
- package/dist/testing/LambderConformanceRunner.d.ts +9 -2
- package/dist/testing/LambderConformanceRunner.js +9 -2
- package/dist/testing/LambderTestApp.d.ts +65 -7
- package/dist/testing/LambderTestApp.js +101 -6
- package/dist/testing/LambderTestVisitor.d.ts +43 -12
- package/dist/testing/LambderTestVisitor.js +35 -11
- package/dist/testing/bootLambdaPackage.d.ts +105 -0
- package/dist/testing/bootLambdaPackage.js +265 -0
- package/dist/testing/lambdaPackageBootProcess.d.ts +39 -0
- package/dist/testing/lambdaPackageBootProcess.js +130 -0
- package/dist/testing/lambderCacheConformance.d.ts +26 -0
- package/dist/testing/lambderCacheConformance.js +287 -0
- package/dist/testing/lambderCacheStorageConformance.d.ts +25 -0
- package/dist/testing/lambderCacheStorageConformance.js +159 -0
- package/dist/testing/lambderSessionStoreConformance.d.ts +3 -3
- package/dist/testing/lambderSessionStoreConformance.js +3 -3
- package/dist/testing.d.ts +7 -1
- package/dist/testing.js +5 -0
- package/package.json +1 -6
- package/dist/shared/util/boundKeyField.d.ts +0 -20
- package/dist/shared/util/boundKeyField.js +0 -34
|
@@ -292,9 +292,18 @@ const collectNames = (nodes, slots, conditions) => {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
};
|
|
295
|
+
/** A name list in an error message: quoted and comma-separated, or "none". */
|
|
296
|
+
const listNames = (names) => names.length === 0 ? "none" : names.map((name) => JSON.stringify(name)).join(", ");
|
|
297
|
+
/**
|
|
298
|
+
* A comment-only HTML template, compiled once. TNames is the caller's
|
|
299
|
+
* statement of its slot and condition names, which types render()'s data;
|
|
300
|
+
* left out, any name compiles, and render() checks every key either way.
|
|
301
|
+
*/
|
|
295
302
|
export class LambderTemplatingEngine {
|
|
296
303
|
nodes;
|
|
297
|
-
/**
|
|
304
|
+
/** Every slot and condition name: what a data key has to be one of. */
|
|
305
|
+
names;
|
|
306
|
+
/** Slot names discovered at compile time. */
|
|
298
307
|
slotNames;
|
|
299
308
|
/** Condition names discovered at compile time. */
|
|
300
309
|
conditionNames;
|
|
@@ -306,6 +315,7 @@ export class LambderTemplatingEngine {
|
|
|
306
315
|
collectNames(this.nodes, slots, conditions);
|
|
307
316
|
this.slotNames = [...slots];
|
|
308
317
|
this.conditionNames = [...conditions];
|
|
318
|
+
this.names = new Set([...slots, ...conditions]);
|
|
309
319
|
}
|
|
310
320
|
/** Read and parse a template file (compile once, render many times). */
|
|
311
321
|
static async fromFile(filePath, options = {}) {
|
|
@@ -317,10 +327,20 @@ export class LambderTemplatingEngine {
|
|
|
317
327
|
}
|
|
318
328
|
/** True when the template declares `name` as a slot or condition. */
|
|
319
329
|
has(name) {
|
|
320
|
-
return this.
|
|
330
|
+
return this.names.has(name);
|
|
321
331
|
}
|
|
322
|
-
/**
|
|
332
|
+
/**
|
|
333
|
+
* Render with escaped-by-default data; omitted slots keep their defaults.
|
|
334
|
+
* Throws for a key the template has no slot or condition for, naming it
|
|
335
|
+
* and the template's names.
|
|
336
|
+
*/
|
|
323
337
|
render(data = {}) {
|
|
338
|
+
const unknownKeys = Object.keys(data).filter((key) => !this.names.has(key));
|
|
339
|
+
if (unknownKeys.length > 0) {
|
|
340
|
+
throw new Error(`LambderTemplatingEngine: the data carries ${listNames(unknownKeys)}, which the template has no slot or condition for, ` +
|
|
341
|
+
`so ${unknownKeys.length === 1 ? "its value" : "their values"} would be dropped. Its slots: ${listNames(this.slotNames)}; ` +
|
|
342
|
+
`its conditions: ${listNames(this.conditionNames)}.`);
|
|
343
|
+
}
|
|
324
344
|
const output = { html: "", firstDataIndex: -1 };
|
|
325
345
|
renderNodes(this.nodes, data, output);
|
|
326
346
|
return output.html;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export { LambderCookieJar, parseSetCookie } from "./shared/transport/LambderCook
|
|
|
18
18
|
export { LambderExpiringMap, LambderExpiringMapFullError } from "./shared/util/LambderExpiringMap.js";
|
|
19
19
|
export { LambderBackoffTimer } from "./shared/util/LambderBackoffTimer.js";
|
|
20
20
|
export type { LambderBackoffTimerOptions } from "./shared/util/LambderBackoffTimer.js";
|
|
21
|
-
export { LambderSignedClaims, keyedDigest, randomSecret } from "./shared/util/LambderSignedClaims.js";
|
|
21
|
+
export { LambderSignedClaims, keyedDigest, randomSecret, randomCode } from "./shared/util/LambderSignedClaims.js";
|
|
22
22
|
export type { LambderSignedClaimsOptions } from "./shared/util/LambderSignedClaims.js";
|
|
23
23
|
export { constantTimeEquals } from "./shared/util/LambderTextDigest.js";
|
|
24
24
|
export type { LambderStoredCookie } from "./shared/transport/LambderCookieJar.js";
|
|
@@ -28,7 +28,7 @@ export { synthesizeLambdaHttpEvent, decodeLambdaHttpResult, localLambdaContext,
|
|
|
28
28
|
export type { LambderSynthesizedRequest, LambderLambdaHttpResult, LambderInvokeSession } from "./invoke/LambderLambdaEvent.js";
|
|
29
29
|
export { LambderApiPipeline } from "./api/LambderApiPipeline.js";
|
|
30
30
|
export type { LambderApiPipelineOptions, LambderApiSessionsConfig, LambderApiInputRefusal, LambderApiRunResult, LambderApiExec } from "./api/LambderApiPipeline.js";
|
|
31
|
-
export { readApiEnvelope, restoreCompressedPayload } from "./api/LambderApiRequest.js";
|
|
31
|
+
export { readApiEnvelope, readApiEnvelopeText, restoreCompressedPayload } from "./api/LambderApiRequest.js";
|
|
32
32
|
export type { LambderApiRequest, LambderApiRequestInfo, LambderCompressedPayloadFields, LambderRestorePayloadResult } from "./api/LambderApiRequest.js";
|
|
33
33
|
export { toHttpAnswer } from "./api/LambderApiAnswer.js";
|
|
34
34
|
export type { LambderApiAnswer } from "./api/LambderApiAnswer.js";
|
|
@@ -54,7 +54,7 @@ export type { LambderInvokeCallerOptions, LambderInvokeCallOptions, LambderInvok
|
|
|
54
54
|
export { describeCrash, errorFromCrashDetail } from "./shared/wire/LambderCrashDetail.js";
|
|
55
55
|
export type { LambderCrashDetail, LambderCrashCause } from "./shared/wire/LambderCrashDetail.js";
|
|
56
56
|
export { LambderApiRefusal, isLambderApiRefusal, isLambderRefusalCode, refuse, refusalMessageOf, LAMBDER_REFUSAL_CODES } from "./shared/wire/LambderApiRefusal.js";
|
|
57
|
-
export type { LambderApiRefusalOptions, LambderRefusalMessage, LambderPlainRefusalMessage, LambderUncheckedRefusalMessage, LambderRefusalCode, LambderRefuseOptions, LambderDeclaredRefuseOptions, LambderDeclaredRefuse, } from "./shared/wire/LambderApiRefusal.js";
|
|
57
|
+
export type { LambderApiRefusalOptions, LambderRefusalMessage, LambderPlainRefusalMessage, LambderRateLimitRefusalData, LambderUncheckedRefusalMessage, LambderRefusalCode, LambderRefuseOptions, LambderDeclaredRefuseOptions, LambderDeclaredRefuse, } from "./shared/wire/LambderApiRefusal.js";
|
|
58
58
|
export { isObjectPayload } from "./shared/wire/LambderObjectPayload.js";
|
|
59
59
|
export { default as LambderResponseBuilder } from "./core/LambderResponseBuilder.js";
|
|
60
60
|
export { default as LambderResolver } from "./core/LambderResolver.js";
|
|
@@ -69,12 +69,12 @@ export { LambderWebCrypto, LambderPlainSessionCrypto, isWebCryptoAvailable } fro
|
|
|
69
69
|
export type { LambderSessionCrypto } from "./session/LambderSessionCrypto.js";
|
|
70
70
|
export { LambderDdbSessionStore } from "./stores/LambderDdbSessionStore.js";
|
|
71
71
|
export type { LambderDdbSessionStoreOptions } from "./stores/LambderDdbSessionStore.js";
|
|
72
|
-
export { LambderResponse,
|
|
72
|
+
export { LambderResponse, type LambderHttpResponse, type LambderHeadersInput, type LambderResponseCompressionSettings, type LambderResponseCompressionOption, } from "./core/LambderResponse.js";
|
|
73
73
|
export type { LambderHttpStatusCode, LambderRefusalStatusCode } from "./shared/wire/LambderHttpStatus.js";
|
|
74
|
-
export { html, xml, raw, jsonScript, escapeHtml, renderHtmlValue, LambderSafeHtml, type LambderHtmlValue } from "./shared/LambderHtml.js";
|
|
74
|
+
export { html, xml, raw, jsonScript, escapeHtml, renderHtmlValue, LambderSafeHtml, type LambderHtmlValue, type LambderJsonScriptOptions } from "./shared/LambderHtml.js";
|
|
75
75
|
export { LambderTemplatingEngine } from "./core/LambderTemplatingEngine.js";
|
|
76
76
|
export type { LambderTemplateData, LambderTemplatingEngineOptions } from "./core/LambderTemplatingEngine.js";
|
|
77
|
-
export type { LambderResponseOptions, LambderRawResponseInit, } from "./core/LambderResponseBuilder.js";
|
|
77
|
+
export type { LambderResponseOptions, LambderRawResponseInit, LambderTemplateFileOptions, } from "./core/LambderResponseBuilder.js";
|
|
78
78
|
export type { LambderRouteMatcher, LambderRouteConditionFn, LambderRouteCondition, LambderPathParamsOf, LambderRoutePath } from "./core/LambderRouting.js";
|
|
79
79
|
export type { LambderCorsConfig } from "./core/LambderCors.js";
|
|
80
80
|
export type { LambderCreateOptions, LambderSessionOptions, LambderActionTools, LambderHandler, } from "./core/LambderCreateOptions.js";
|
|
@@ -107,9 +107,9 @@ export { compressText, restoreBytes, restoreText, LambderCompressionError, LAMBD
|
|
|
107
107
|
export type { LambderRestoreFailure, LambderRestoreBound } from "./shared/wire/LambderCompressionCodec.js";
|
|
108
108
|
export { LambderSessionDataRefreshError, LambderSessionReadError } from "./session/LambderSessionManager.js";
|
|
109
109
|
export { LambderSessionNotFoundError, LambderSessionAmbiguousError } from "./session/LambderSessionController.js";
|
|
110
|
-
export type { LambderCache, LambderCacheKey, LambderCacheSetOptions, LambderCacheListOptions } from "./shared/contracts/LambderCache.js";
|
|
110
|
+
export type { LambderCache, LambderCacheKey, LambderCacheSetOptions, LambderCacheGetOrSetOptions, LambderCacheListOptions, } from "./shared/contracts/LambderCache.js";
|
|
111
111
|
export { LambderDdbCache } from "./stores/LambderDdbCache.js";
|
|
112
|
-
export type { LambderDdbCacheOptions
|
|
112
|
+
export type { LambderDdbCacheOptions } from "./stores/LambderDdbCache.js";
|
|
113
113
|
export { LambderMemoryCache } from "./stores/LambderMemoryCache.js";
|
|
114
114
|
export type { LambderMemoryCacheOptions } from "./stores/LambderMemoryCache.js";
|
|
115
115
|
export { LambderStorageBackedCache } from "./stores/LambderStorageBackedCache.js";
|
|
@@ -120,6 +120,8 @@ export type { LambderRateLimiter, LambderRateLimitWindow, LambderRateLimitPolicy
|
|
|
120
120
|
export { LambderDdbRateLimiter } from "./stores/LambderDdbRateLimiter.js";
|
|
121
121
|
export type { LambderDdbRateLimiterOptions } from "./stores/LambderDdbRateLimiter.js";
|
|
122
122
|
export { LambderMemoryRateLimiter } from "./stores/LambderMemoryRateLimiter.js";
|
|
123
|
+
export { LambderPasswordHasher } from "./secrets/LambderPasswordHasher.js";
|
|
124
|
+
export type { LambderPasswordHasherOptions } from "./secrets/LambderPasswordHasher.js";
|
|
123
125
|
export { LambderOneShotSecrets } from "./secrets/LambderOneShotSecrets.js";
|
|
124
126
|
export type { LambderOneShotSecretKind, LambderOneShotSecretsOptions, LambderOneShotIssueResult, LambderOneShotRedeemResult, LambderOneShotCodeKindNames, LambderOneShotTokenKindNames, } from "./secrets/LambderOneShotSecrets.js";
|
|
125
127
|
export type { LambderOneShotSecretStore, LambderOneShotSecretRecord, LambderOneShotSecretDraft, LambderOneShotSecretShape, LambderOneShotIssueOutcome, } from "./shared/contracts/LambderOneShotSecretStore.js";
|
|
@@ -140,16 +142,17 @@ export type { LambderRateLimitKeyBuilder } from "./api/LambderApiRateLimits.js";
|
|
|
140
142
|
export type { LambderContextRateLimit, LambderContextRateLimitCheck, LambderRateLimitCheckResult, LambderChargeablePolicyNames, LambderChargeKeyArgs, LambderRateLimitKeyFn, LambderRateLimitPer, LambderRateLimitBudget, LambderRateLimitChargeAt, LambderApiRateLimitPolicyConfig, LambderApiRateLimitsConfig, LambderAllowedPolicyNames, LambderPolicyNamesInputLacks, LambderRateLimitOption, } from "./api/LambderApiRateLimits.js";
|
|
141
143
|
export type { LambderApiIdempotencyConfig } from "./api/LambderApiIdempotency.js";
|
|
142
144
|
export type { LambderGuardsOptionValue, LambderRateLimitMessage, LambderRateLimitOverride, LambderRateLimitOptionValue, LambderRefusalsOptionValue, LambderApiIdempotencyOption, } from "./shared/wire/LambderApiOptionValues.js";
|
|
143
|
-
export { apiGuardParam, apiGuardParamExportName } from "./shared/wire/LambderApiOptionEntries.js";
|
|
145
|
+
export { apiGuardParam, apiGuardParamExportName, apisWithGuard } from "./shared/wire/LambderApiOptionEntries.js";
|
|
144
146
|
export type { LambderApiOptionEntries, LambderApiOptionEntry, LambderRateLimitPolicyEntry, LambderGuardDeclarationEntry, LambderApisWithGuard, LambderApisGuardedBy, LambderApisWithMode, LambderGuardParamOf, LambderApiGuardParam, } from "./shared/wire/LambderApiOptionEntries.js";
|
|
145
147
|
export { createLambderI18n } from "./shared/LambderI18n.js";
|
|
146
|
-
export type { LambderLanguageMeta, LambderI18nConfig, LambderI18nInstance, LambderI18nTranslator, LambderI18nExtractParams, LambderI18nDictionaryLoader, LambderI18nCodes, LambderI18nKeys, LambderI18nTranslatorFor, } from "./shared/LambderI18n.js";
|
|
148
|
+
export type { LambderLanguageMeta, LambderI18nConfig, LambderI18nInstance, LambderI18nReadonlyInstance, LambderI18nTranslator, LambderI18nExtractParams, LambderI18nDictionaryLoader, LambderI18nDictionaryEntry, LambderI18nPluralEntry, LambderI18nPluralCategory, LambderI18nCodes, LambderI18nKeys, LambderI18nTranslatorFor, } from "./shared/LambderI18n.js";
|
|
147
149
|
export type { LambderApiContractShape, LambderApiMode, LambderApiEnvelopeBody, LambderApiSuccessEnvelope, LambderApiRefusalEnvelope, LambderRefusalEnvelopeFields, LambderApiRefusalConfig, LambderContractEntry, LambderGuardNamesIn, LambderContractMode, LambderContractKeysWithMode, LambderContractKeysWithGuard, LambderJsonOf, LambderContractRefusalsOf, LambderContractRefusalMessage, LambderContractRefusals, LambderContractAnyRefusalMessage, LambderContractGuardsOf, LambderContractGuardNames, LambderContractGuardInputsOf, LambderContractGuardInput, LambderContractGuardInputNames, LambderContractRateLimitOf, LambderContractRateLimitNames, LambderContractIdempotencyOf, } from "./shared/wire/LambderApiContract.js";
|
|
148
150
|
export type { LambderRenderContext, LambderSessionRenderContext, LambderHttpEvent, LambderHttpEventFormat } from "./core/LambderContext.js";
|
|
149
|
-
export type {
|
|
151
|
+
export type { LambderRenderContextOf, LambderSessionRenderContextOf } from "./core/LambderContext.js";
|
|
152
|
+
export type { LambderApiAnswerOutcome, LambderApiSuccessOutcome, LambderApiFailure, LambderApiCallFailure, LambderApiValidationFailure, LambderApiEnvelopeFailure, LambderApiHttpAnswer, } from "./shared/wire/LambderApiOutcome.js";
|
|
150
153
|
export { resolveApiOutcome } from "./shared/wire/LambderApiOutcome.js";
|
|
151
154
|
export { createContext, isV2HttpEvent } from "./core/LambderContext.js";
|
|
152
|
-
export type { LambderContextOptions, LambderOriginProof } from "./core/LambderContext.js";
|
|
155
|
+
export type { LambderContextOptions, LambderOriginProof, LambderRequestArrival } from "./core/LambderContext.js";
|
|
153
156
|
export type { LambderCallSummary, LambderCallSummaryOption } from "./core/LambderCallSummary.js";
|
|
154
157
|
export type { LambderCallOutcome, LambderCallOutcomeHint } from "./shared/wire/LambderCallOutcome.js";
|
|
155
158
|
export { COMPRESSED_PAYLOAD_GZ_FIELD, COMPRESSED_PAYLOAD_BR_FIELD, COMPRESSED_PAYLOAD_BYTES_FIELD, DEFAULT_REQUEST_COMPRESSION_SETTINGS, DEFAULT_MAX_RESTORED_PAYLOAD_BYTES, DEFAULT_INVOKE_REQUEST_COMPRESSION_SETTINGS, compressPayloadBrotli, } from "./shared/wire/LambderRequestPayload.js";
|
package/dist/index.js
CHANGED
|
@@ -13,14 +13,14 @@ export { LambderCookieJar, parseSetCookie } from "./shared/transport/LambderCook
|
|
|
13
13
|
export { LambderExpiringMap, LambderExpiringMapFullError } from "./shared/util/LambderExpiringMap.js";
|
|
14
14
|
// Waiting longer after each failure, once: what the upload runner and an app's own retrying code climb.
|
|
15
15
|
export { LambderBackoffTimer } from "./shared/util/LambderBackoffTimer.js";
|
|
16
|
-
// Signed claims tokens, and the keyed digest and random
|
|
17
|
-
export { LambderSignedClaims, keyedDigest, randomSecret } from "./shared/util/LambderSignedClaims.js";
|
|
16
|
+
// Signed claims tokens, and the keyed digest, random secret and random code for the secrets an app stores.
|
|
17
|
+
export { LambderSignedClaims, keyedDigest, randomSecret, randomCode } from "./shared/util/LambderSignedClaims.js";
|
|
18
18
|
export { constantTimeEquals } from "./shared/util/LambderTextDigest.js";
|
|
19
19
|
export { lambderHandlerTransport } from "./invoke/lambderHandlerTransport.js";
|
|
20
20
|
export { synthesizeLambdaHttpEvent, decodeLambdaHttpResult, localLambdaContext, LAMBDER_INVOKE_HEADER, LAMBDER_INVOKED_BY_HEADER, LAMBDER_PARENT_REQUEST_HEADER, LAMBDER_INVOKE_PROTOCOL, } from "./invoke/LambderLambdaEvent.js";
|
|
21
21
|
// The API core: the request, answer, envelope and pipeline both the server and the mock runtime run
|
|
22
22
|
export { LambderApiPipeline } from "./api/LambderApiPipeline.js";
|
|
23
|
-
export { readApiEnvelope, restoreCompressedPayload } from "./api/LambderApiRequest.js";
|
|
23
|
+
export { readApiEnvelope, readApiEnvelopeText, restoreCompressedPayload } from "./api/LambderApiRequest.js";
|
|
24
24
|
export { toHttpAnswer } from "./api/LambderApiAnswer.js";
|
|
25
25
|
export { LambderAnswerHeaders, getAnswerHeader, setAnswerHeader, addAnswerHeader } from "./shared/wire/LambderAnswerHeaders.js";
|
|
26
26
|
export { createApiCallContext } from "./api/LambderApiCallContext.js";
|
|
@@ -50,7 +50,7 @@ export { LambderMemorySessionStore } from "./stores/LambderMemorySessionStore.js
|
|
|
50
50
|
export { LambderWebCrypto, LambderPlainSessionCrypto, isWebCryptoAvailable } from "./session/LambderSessionCrypto.js";
|
|
51
51
|
export { LambderDdbSessionStore } from "./stores/LambderDdbSessionStore.js";
|
|
52
52
|
// Response model
|
|
53
|
-
export { LambderResponse,
|
|
53
|
+
export { LambderResponse, } from "./core/LambderResponse.js";
|
|
54
54
|
// Type-safe templating (tagged templates with auto-escaping)
|
|
55
55
|
export { html, xml, raw, jsonScript, escapeHtml, renderHtmlValue, LambderSafeHtml } from "./shared/LambderHtml.js";
|
|
56
56
|
// Comment-based HTML templating engine (build-pipeline-safe slots and conditionals, standalone)
|
|
@@ -81,6 +81,8 @@ export { LambderStorageBackedCache } from "./stores/LambderStorageBackedCache.js
|
|
|
81
81
|
export { RATE_LIMIT_WINDOWS } from "./shared/contracts/LambderRateLimiter.js";
|
|
82
82
|
export { LambderDdbRateLimiter } from "./stores/LambderDdbRateLimiter.js";
|
|
83
83
|
export { LambderMemoryRateLimiter } from "./stores/LambderMemoryRateLimiter.js";
|
|
84
|
+
// Passwords at rest: argon2id PHC strings through node:crypto
|
|
85
|
+
export { LambderPasswordHasher } from "./secrets/LambderPasswordHasher.js";
|
|
84
86
|
// One-shot secrets: codes and tokens handed out once and taken back once, the
|
|
85
87
|
// store interface they live in, and the DynamoDB and in-memory stores
|
|
86
88
|
export { LambderOneShotSecrets } from "./secrets/LambderOneShotSecrets.js";
|
|
@@ -97,7 +99,7 @@ export { LambderApiRefusalValidationError } from "./api/LambderApiRefusals.js";
|
|
|
97
99
|
export { lambderRateLimitKeyBuilder, rateLimitRefusal, DEFAULT_RATE_LIMIT_REFUSAL } from "./api/LambderApiRateLimits.js";
|
|
98
100
|
// The declared options as plain data: what apiOptionEntries() reports and
|
|
99
101
|
// writeApiOptions writes, and the readers over the generated tables.
|
|
100
|
-
export { apiGuardParam, apiGuardParamExportName } from "./shared/wire/LambderApiOptionEntries.js";
|
|
102
|
+
export { apiGuardParam, apiGuardParamExportName, apisWithGuard } from "./shared/wire/LambderApiOptionEntries.js";
|
|
101
103
|
// Typed translations (standalone, isomorphic)
|
|
102
104
|
export { createLambderI18n } from "./shared/LambderI18n.js";
|
|
103
105
|
export { resolveApiOutcome } from "./shared/wire/LambderApiOutcome.js";
|
|
@@ -27,6 +27,7 @@ import { type LambderApiSignatureMap } from "../shared/wire/LambderApiSignatureM
|
|
|
27
27
|
import type { LambdaClient, LambdaClientConfig } from "@aws-sdk/client-lambda";
|
|
28
28
|
import type { LambderApiContractShape, LambderContractRefusalMessage } from "../shared/wire/LambderApiContract.js";
|
|
29
29
|
import { type LambderCallArgs, type LambderContractOutputOf, type LambderGuardInputsProviderOption, type LambderSharedCallOptions } from "../shared/wire/LambderCallOptions.js";
|
|
30
|
+
import { LAMBDER_BACKEND_SWAP } from "../shared/util/LambderTestingDoors.js";
|
|
30
31
|
import { type LambderCompressionOption } from "../shared/wire/LambderCompressionOption.js";
|
|
31
32
|
import { type LambderInvokeSession, type LambderLambdaHttpResult } from "./LambderLambdaEvent.js";
|
|
32
33
|
/**
|
|
@@ -57,7 +58,11 @@ export type LambderInvokeLogListHandler = (apiName: string, logList: unknown[])
|
|
|
57
58
|
export type LambderInvokeCallCheck = (name: string, info: {
|
|
58
59
|
functionName: string;
|
|
59
60
|
}) => void;
|
|
60
|
-
/**
|
|
61
|
+
/**
|
|
62
|
+
* The onFailure option: every failed call, once, awaited before api() throws
|
|
63
|
+
* or apiOutcome() returns, but for a call its own signal aborted, which is the
|
|
64
|
+
* calling code's choice rather than a failure to report.
|
|
65
|
+
*/
|
|
61
66
|
export type LambderInvokeFailureHandler = (failure: LambderInvokeFailure, info: {
|
|
62
67
|
apiName: string;
|
|
63
68
|
functionName: string;
|
|
@@ -120,8 +125,11 @@ type LambderInvokeCallerBaseOptions = {
|
|
|
120
125
|
/**
|
|
121
126
|
* Called and awaited for every failed call before api() throws or
|
|
122
127
|
* apiOutcome() returns, so failures are reported in one place, before the
|
|
123
|
-
* lambda answers. A
|
|
124
|
-
*
|
|
128
|
+
* lambda answers. A call its own signal aborted is not told: the calling
|
|
129
|
+
* code gave it up. A throw inside it is logged and otherwise ignored, so
|
|
130
|
+
* apiOutcome() never throws. The error of a failure it took is marked as
|
|
131
|
+
* reported, so the instance's crash reporting does not report it again
|
|
132
|
+
* when api() throws it up through a handler.
|
|
125
133
|
*/
|
|
126
134
|
onFailure?: LambderInvokeFailureHandler;
|
|
127
135
|
/**
|
|
@@ -183,6 +191,19 @@ export type LambderInvokeEventInit = {
|
|
|
183
191
|
declare class LambderInvokeCallerCore<TContract extends LambderApiContractShape = any, TProvidedGuards extends string = never> {
|
|
184
192
|
#private;
|
|
185
193
|
constructor(options: LambderInvokeCallerOptions<TContract, TProvidedGuards>);
|
|
194
|
+
/**
|
|
195
|
+
* Points this caller, in place of the Lambda SDK, at what
|
|
196
|
+
* `lambder/testing` answers its function with: a mock app the test
|
|
197
|
+
* supplied for it, or a transport that fails every call naming the
|
|
198
|
+
* function. Keyed by a symbol no entry point exports; see
|
|
199
|
+
* registerSwappableInstance.
|
|
200
|
+
*/
|
|
201
|
+
[LAMBDER_BACKEND_SWAP](twins: {
|
|
202
|
+
invokeTransport(callee: {
|
|
203
|
+
functionName: string;
|
|
204
|
+
apiPath: string;
|
|
205
|
+
}): LambderInvokeTransport;
|
|
206
|
+
}): void;
|
|
186
207
|
/**
|
|
187
208
|
* The event api() would send for this call, with a plain payload. For
|
|
188
209
|
* tests and boot checks that hand a built package an event file.
|
|
@@ -238,7 +259,7 @@ export type LambderInvokeGroupCalls<TContract, TProvidedGuards extends string> =
|
|
|
238
259
|
};
|
|
239
260
|
};
|
|
240
261
|
/**
|
|
241
|
-
* A typed client of another Lambder function, over a
|
|
262
|
+
* A typed client of another Lambder function, over a Lambda invoke:
|
|
242
263
|
* `caller.email.send(input)` for the callee's endpoint `email.send`,
|
|
243
264
|
* `.outcome(input)` for its outcome, and `caller.api("email.send", input)`
|
|
244
265
|
* for code that has the name as a value.
|
|
@@ -29,8 +29,11 @@ import { resolveApiOutcome } from "../shared/wire/LambderApiOutcome.js";
|
|
|
29
29
|
import { mergeGuardInputs, } from "../shared/wire/LambderCallOptions.js";
|
|
30
30
|
import { beginIdempotentAttempt, IDEMPOTENT_ATTEMPT_NOT_SENT } from "../shared/wire/LambderIdempotencyKeyScope.js";
|
|
31
31
|
import { createCallAbort, stopWaitingWhenAborted } from "../shared/util/LambderCallAbort.js";
|
|
32
|
+
import { markErrorReported } from "../shared/util/LambderErrorReportMark.js";
|
|
32
33
|
import { coerceToError, errorFromCrashDetail } from "../shared/wire/LambderCrashDetail.js";
|
|
33
34
|
import { assertPositiveInteger } from "../shared/util/LambderOptionChecks.js";
|
|
35
|
+
import { LAMBDER_BACKEND_SWAP } from "../shared/util/LambderTestingDoors.js";
|
|
36
|
+
import { registerSwappableInstance } from "../shared/util/LambderSwappableInstances.js";
|
|
34
37
|
import { resolveCompressionOption } from "../shared/wire/LambderCompressionOption.js";
|
|
35
38
|
import { DEFAULT_INVOKE_REQUEST_COMPRESSION_SETTINGS, DEFAULT_MAX_RESTORED_PAYLOAD_BYTES, compressPayloadBrotli, resolveRequestCompressionMinBytes, } from "../shared/wire/LambderRequestPayload.js";
|
|
36
39
|
import { DEFAULT_API_PATH } from "../shared/wire/LambderDefaultApiPath.js";
|
|
@@ -63,6 +66,7 @@ class LambderInvokeCallerCore {
|
|
|
63
66
|
#beforeCall;
|
|
64
67
|
#guardInputsProvider;
|
|
65
68
|
#sessionTokenCookieKey;
|
|
69
|
+
/** The transport given, or the Lambda SDK; `lambder/testing` replaces the SDK's through the swap door below. */
|
|
66
70
|
#transport;
|
|
67
71
|
#clientConfig;
|
|
68
72
|
#client;
|
|
@@ -88,12 +92,26 @@ class LambderInvokeCallerCore {
|
|
|
88
92
|
this.#guardInputsProvider = guardInputsProvider;
|
|
89
93
|
this.#sessionTokenCookieKey = sessionTokenCookieKey ?? DEFAULT_SESSION_TOKEN_COOKIE_KEY;
|
|
90
94
|
this.#transport = transport ?? ((_event, { eventJson, signal }) => this.#invokeThroughSdk(eventJson, signal));
|
|
95
|
+
// A caller given a transport reaches what the transport reaches, which
|
|
96
|
+
// its author chose; only the SDK path is the test kit's to replace.
|
|
97
|
+
if (!transport)
|
|
98
|
+
registerSwappableInstance(this);
|
|
91
99
|
// Each group of the callee's contract, as a property:
|
|
92
100
|
// caller.email.send(input) is caller.api("email.send", input), and
|
|
93
101
|
// .outcome the apiOutcome.
|
|
94
102
|
const byName = this;
|
|
95
103
|
return withApiGroupCalls(this, (apiName, args) => byName.api(apiName, ...args), (apiName, args) => byName.apiOutcome(apiName, ...args));
|
|
96
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Points this caller, in place of the Lambda SDK, at what
|
|
107
|
+
* `lambder/testing` answers its function with: a mock app the test
|
|
108
|
+
* supplied for it, or a transport that fails every call naming the
|
|
109
|
+
* function. Keyed by a symbol no entry point exports; see
|
|
110
|
+
* registerSwappableInstance.
|
|
111
|
+
*/
|
|
112
|
+
[LAMBDER_BACKEND_SWAP](twins) {
|
|
113
|
+
this.#transport = twins.invokeTransport({ functionName: this.#functionName, apiPath: this.#apiPath });
|
|
114
|
+
}
|
|
97
115
|
/**
|
|
98
116
|
* The event api() would send for this call, with a plain payload. For
|
|
99
117
|
* tests and boot checks that hand a built package an event file.
|
|
@@ -184,7 +202,12 @@ class LambderInvokeCallerCore {
|
|
|
184
202
|
}
|
|
185
203
|
return { functionError: output.FunctionError ?? null, result };
|
|
186
204
|
}
|
|
187
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* Delivers one event, serialized exactly once; an event over the invoke
|
|
207
|
+
* cap, a rejected transport, or one that answered after the call was given
|
|
208
|
+
* up on, is a failure. `reachedTransport` says whether the transport was
|
|
209
|
+
* handed the event, since only then may the callee have run.
|
|
210
|
+
*/
|
|
188
211
|
async #deliverEvent(event, eventJson, options) {
|
|
189
212
|
// Measured here so every path that delivers an event is capped: an
|
|
190
213
|
// oversized event would otherwise come back as the SDK's
|
|
@@ -192,7 +215,7 @@ class LambderInvokeCallerCore {
|
|
|
192
215
|
// names neither the size nor the cap.
|
|
193
216
|
const bytes = Buffer.byteLength(eventJson, "utf8");
|
|
194
217
|
if (bytes > LAMBDER_INVOKE_MAX_EVENT_BYTES) {
|
|
195
|
-
return { failed: {
|
|
218
|
+
return { reachedTransport: false, failed: {
|
|
196
219
|
reason: 'payloadTooLarge', bytes,
|
|
197
220
|
detail: `the event is ${bytes} bytes, over the ${LAMBDER_INVOKE_MAX_EVENT_BYTES} byte invoke cap`,
|
|
198
221
|
} };
|
|
@@ -206,21 +229,22 @@ class LambderInvokeCallerCore {
|
|
|
206
229
|
// and not every transport meets it.
|
|
207
230
|
const refused = abort.abortFailure("beforeSending");
|
|
208
231
|
if (refused)
|
|
209
|
-
return { failed: { reason: refused.reason, cause: refused.error, detail: refused.error.message } };
|
|
232
|
+
return { reachedTransport: false, failed: { reason: refused.reason, cause: refused.error, detail: refused.error.message } };
|
|
210
233
|
const sent = await this.#transport(event, { functionName: this.#functionName, eventJson, signal: abort.signal });
|
|
211
234
|
// An answer that arrives after the abort is not a success: a
|
|
212
235
|
// transport that ignores the signal resolves late, and trusting it
|
|
213
236
|
// would hand the call site data it had already abandoned.
|
|
214
237
|
const late = abort.abortFailure("afterAnswering");
|
|
215
238
|
if (late)
|
|
216
|
-
return { failed: { reason: late.reason, cause: late.error, detail: late.error.message } };
|
|
239
|
+
return { reachedTransport: true, failed: { reason: late.reason, cause: late.error, detail: late.error.message } };
|
|
217
240
|
return { sent };
|
|
218
241
|
}
|
|
219
242
|
catch (err) {
|
|
220
243
|
const cause = coerceToError(err, "the invoke failed");
|
|
221
|
-
// The caller's own
|
|
222
|
-
//
|
|
223
|
-
|
|
244
|
+
// The caller's own abort wins, timeout or signal, since only the
|
|
245
|
+
// caller knows which aborted the call; otherwise the rejection
|
|
246
|
+
// says what it was.
|
|
247
|
+
return { reachedTransport: true, failed: { reason: abort.abortReason() ?? classifyDeliveryFailure(cause), cause } };
|
|
224
248
|
}
|
|
225
249
|
finally {
|
|
226
250
|
abort.detach();
|
|
@@ -267,11 +291,18 @@ class LambderInvokeCallerCore {
|
|
|
267
291
|
...(init.response !== undefined ? { response: init.response } : {}),
|
|
268
292
|
};
|
|
269
293
|
error.outcome = failure;
|
|
270
|
-
|
|
294
|
+
// The calling code aborted this call itself, so there is nothing to
|
|
295
|
+
// report: the error still reaches whoever reads the outcome.
|
|
296
|
+
if (this.#onFailure && failure.reason !== 'aborted') {
|
|
271
297
|
// A reporting hook that breaks must not turn apiOutcome() into a
|
|
272
298
|
// throwing call, nor replace the failure it was told about.
|
|
273
299
|
try {
|
|
274
300
|
await this.#onFailure(failure, { apiName, functionName: this.#functionName });
|
|
301
|
+
// Reported now, so the crash reporting a thrown api() reaches
|
|
302
|
+
// skips it rather than recording the one failure twice. Only
|
|
303
|
+
// once the hook returned: one that threw may have reported
|
|
304
|
+
// nothing, and a duplicate is better than a loss.
|
|
305
|
+
markErrorReported(error);
|
|
275
306
|
}
|
|
276
307
|
catch (err) {
|
|
277
308
|
console.error(`[lambder invoke] onFailure threw for ${this.#functionName} ${apiName}`, err);
|
|
@@ -368,8 +399,15 @@ class LambderInvokeCallerCore {
|
|
|
368
399
|
return await this.#failureOutcome(apiName, { reason: 'unknown', cause: coerceToError(err, "the call could not be built") });
|
|
369
400
|
}
|
|
370
401
|
const delivery = await this.#deliverEvent(event, eventJson, options);
|
|
371
|
-
if ("failed" in delivery)
|
|
402
|
+
if ("failed" in delivery) {
|
|
403
|
+
// An event the transport was never handed did not use the key,
|
|
404
|
+
// whatever the failure reads as (an abort reads as aborted or
|
|
405
|
+
// timeout): the same as the browser caller's failure before
|
|
406
|
+
// sending.
|
|
407
|
+
if (!delivery.reachedTransport)
|
|
408
|
+
idempotentAttempt.settle(IDEMPOTENT_ATTEMPT_NOT_SENT);
|
|
372
409
|
return await this.#failureOutcome(apiName, delivery.failed);
|
|
410
|
+
}
|
|
373
411
|
if (delivery.sent.functionError) {
|
|
374
412
|
return await this.#failureOutcome(apiName, { reason: 'crash', functionError: parseFunctionError(delivery.sent.result) });
|
|
375
413
|
}
|
|
@@ -69,14 +69,15 @@ export type LambderInvokeEnvelopeFailure<TMessage extends LambderUncheckedRefusa
|
|
|
69
69
|
refusal: TMessage;
|
|
70
70
|
});
|
|
71
71
|
/**
|
|
72
|
-
* Nothing usable came back: the invoke never arrived or was given up on
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
72
|
+
* Nothing usable came back: the invoke never arrived or was given up on (by
|
|
73
|
+
* its timeout, or by the calling code through its signal), the Lambda service
|
|
74
|
+
* answered instead of the callee, the callee answered 5xx, or something
|
|
75
|
+
* around the call threw. A 5xx carries `response` when the callee answered
|
|
76
|
+
* with Lambder's own envelope, which is how a crash detail and a logList
|
|
77
|
+
* arrive with it.
|
|
77
78
|
*/
|
|
78
79
|
export type LambderInvokeDeliveryFailure<TMessage extends LambderUncheckedRefusalMessage = LambderUncheckedRefusalMessage> = LambderInvokeFailureFields<TMessage> & {
|
|
79
|
-
reason: 'network' | 'timeout' | 'server' | 'protocol' | 'unknown';
|
|
80
|
+
reason: 'network' | 'timeout' | 'aborted' | 'server' | 'protocol' | 'unknown';
|
|
80
81
|
response?: LambderApiRefusalEnvelope;
|
|
81
82
|
/** The callee's crash detail, when its global error handler sent one (the envelope's `crash` field). */
|
|
82
83
|
crash?: LambderCrashDetail;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { LambderApiRequest } from "../api/LambderApiRequest.js";
|
|
2
|
+
/**
|
|
3
|
+
* The key of the door the mock's own adapters open on a LambderMockApp: what
|
|
4
|
+
* an adapter asks of the runtime and tells it beyond handing it a call.
|
|
5
|
+
*
|
|
6
|
+
* A symbol rather than named members, and exported by no entry point: the
|
|
7
|
+
* package's exports map is what a consumer can import, so only an adapter of
|
|
8
|
+
* the package's own (the MSW handler) can name the key, and nothing on the
|
|
9
|
+
* app's typed surface offers an app the adapter's bookkeeping as an API.
|
|
10
|
+
*/
|
|
11
|
+
export declare const LAMBDER_MOCK_ADAPTER_DOOR: unique symbol;
|
|
12
|
+
/** What a LambderMockApp answers to LAMBDER_MOCK_ADAPTER_DOOR. */
|
|
13
|
+
export type LambderMockAdapterDoor = {
|
|
14
|
+
/**
|
|
15
|
+
* Whether a call to this name would be answered from the registry, which
|
|
16
|
+
* is what an adapter asks before passing one on. Asked once per request,
|
|
17
|
+
* so not a list to scan.
|
|
18
|
+
*
|
|
19
|
+
* True for every name once a rest entry is registered, since it answers
|
|
20
|
+
* whatever nothing else claimed. That makes a rest entry and the MSW
|
|
21
|
+
* adapter's `onUnmocked: "passthrough"` alternatives rather than layers:
|
|
22
|
+
* with one registered, nothing is handed on to the network.
|
|
23
|
+
*/
|
|
24
|
+
hasRegisteredEntry(apiName: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Records a call the adapter handed on instead of answering: the MSW
|
|
27
|
+
* adapter's passthrough. Without it a name the registry does not know
|
|
28
|
+
* leaves no trace at all, and a mistyped endpoint reaches the real
|
|
29
|
+
* network with nothing in the call log or on the subscription to say so,
|
|
30
|
+
* which is the one failure the log exists to make visible.
|
|
31
|
+
*/
|
|
32
|
+
notePassthrough(request: LambderApiRequest): void;
|
|
33
|
+
/**
|
|
34
|
+
* Mirrors an answer's non-HttpOnly cookies into document.cookie and
|
|
35
|
+
* remembers them, so reset() expires them again. The direct transport's
|
|
36
|
+
* "document" mode and the MSW adapter both come through the runtime's one
|
|
37
|
+
* mirror, so there is one record of what was planted.
|
|
38
|
+
*/
|
|
39
|
+
mirrorCookiesIntoDocument(setCookies: readonly string[]): void;
|
|
40
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The key of the door the mock's own adapters open on a LambderMockApp: what
|
|
3
|
+
* an adapter asks of the runtime and tells it beyond handing it a call.
|
|
4
|
+
*
|
|
5
|
+
* A symbol rather than named members, and exported by no entry point: the
|
|
6
|
+
* package's exports map is what a consumer can import, so only an adapter of
|
|
7
|
+
* the package's own (the MSW handler) can name the key, and nothing on the
|
|
8
|
+
* app's typed surface offers an app the adapter's bookkeeping as an API.
|
|
9
|
+
*/
|
|
10
|
+
export const LAMBDER_MOCK_ADAPTER_DOOR = Symbol("lambder.mockAdapterDoor");
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type LambderApiSchemaEntries } from "../shared/wire/LambderApiSchemaEntries.js";
|
|
3
|
+
/**
|
|
4
|
+
* The generated `apiSchemas` table, as the schemas the mock validates every
|
|
5
|
+
* call's input with and parses every answer through.
|
|
6
|
+
*/
|
|
7
|
+
export declare class LambderMockApiSchemas {
|
|
8
|
+
private readonly table;
|
|
9
|
+
private readonly rebuilt;
|
|
10
|
+
constructor(table: LambderApiSchemaEntries);
|
|
11
|
+
/**
|
|
12
|
+
* The schema an entry's input is validated with, as the pipeline takes it
|
|
13
|
+
* at registration: lazy, so it is rebuilt on the first call that reaches
|
|
14
|
+
* it. A name the table does not hold throws here, when the entry is
|
|
15
|
+
* registered, rather than on its first call.
|
|
16
|
+
*/
|
|
17
|
+
inputOf(apiName: string): z.ZodType;
|
|
18
|
+
/**
|
|
19
|
+
* An answer a handler returned, parsed through the server's output schema
|
|
20
|
+
* as the server parses its own: what the schema does not declare dropped,
|
|
21
|
+
* its defaults filled. What it rejects, or a parse that throws, is the
|
|
22
|
+
* handler breaking its contract, the error the server crashes with.
|
|
23
|
+
*/
|
|
24
|
+
parseOutput(apiName: string, returned: unknown): unknown;
|
|
25
|
+
private assertHeld;
|
|
26
|
+
/** One of an API's schemas, rebuilt the first time it is asked for and kept. */
|
|
27
|
+
private rebuiltSchema;
|
|
28
|
+
}
|