@ashishpandeyone/cdk-lambda-web-function 0.1.4 → 0.1.6

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/README.md CHANGED
@@ -16,7 +16,7 @@
16
16
 
17
17
  <!--END STABILITY BANNER-->
18
18
 
19
- [AWS Lambda Web Functions](https://aws.amazon.com/lambda/) run an ordinary Node.js HTTP server (Express, Fastify, Hono, `node:http`) on Lambda and give it an HTTPS endpoint, optionally served from several regions. `WebFunction` deploys one, following the conventions of `aws-cdk-lib/aws-lambda` where the two services overlap.
19
+ [AWS Lambda Web Functions](https://docs.aws.amazon.com/lambda/latest/dg/web-functions.html) run an ordinary Node.js HTTP server (Express, Fastify, Hono, `node:http`) on Lambda and give it an HTTPS endpoint, optionally served from several regions. `WebFunction` deploys one, following the conventions of `aws-cdk-lib/aws-lambda` where the two services overlap.
20
20
 
21
21
  ```ts fixture=bare
22
22
  import * as lambda from 'aws-cdk-lib/aws-lambda';
@@ -37,10 +37,18 @@ new CfnOutput(this, 'Url', { value: fn.endpoint.url }); // https://<id>.lambda-w
37
37
 
38
38
  The stack's region is the function's **home region**. Multi-region endpoints need a stack with an explicit `env.region`.
39
39
 
40
+ ## Installation
41
+
42
+ ```bash
43
+ npm install @ashishpandeyone/cdk-lambda-web-function
44
+ ```
45
+
46
+ It needs `aws-cdk-lib` 2.273.0 or later and `constructs` 10.5.1 or later (peer dependencies), and Node.js 22 or later. The package is published for TypeScript and JavaScript only.
47
+
40
48
  ## Writing the server
41
49
 
42
50
  1. Listen on the host and port in **`AWS_LAMBDA_HTTP_ENDPOINT`** (`0.0.0.0:3000` today). `PORT` is not set.
43
- 2. Start listening within **about 9 seconds**, or initialisation fails with `Application.TimeoutListenError`.
51
+ 2. Start listening within **10 seconds**, or initialisation fails with `Application.TimeoutListenError`.
44
52
  3. Put the entry file at the root of your bundle as **`index.js`**, or set `entrypoint`.
45
53
  4. The runtime has **no AWS SDK**: bundle the clients you import.
46
54
  5. Code runs on **arm64**.
@@ -148,6 +156,7 @@ import { SignatureV4a } from '@smithy/signature-v4a';
148
156
  import { Sha256 } from '@aws-crypto/sha256-js';
149
157
  import { fromNodeProviderChain } from '@aws-sdk/credential-providers';
150
158
 
159
+ const host = new URL(url).hostname; // url: the endpoint's URL
151
160
  const signer = new SignatureV4a({ service: 'lambda', region: '*', sha256: Sha256, credentials: fromNodeProviderChain() });
152
161
  const signed = await signer.sign(
153
162
  { method: 'GET', protocol: 'https:', hostname: host, path: '/', headers: { host } },
@@ -156,6 +165,71 @@ const signed = await signer.sign(
156
165
  const response = await fetch(`https://${host}/`, { headers: signed.headers });
157
166
  ```
158
167
 
168
+ ### Other accounts and AWS services
169
+
170
+ A caller in another account needs permission twice: in its own IAM policy, and in the function's **resource policy**. `grantInvoke` handles the function's side: a role in the function's account only gets an IAM policy statement, while a principal in another account or an AWS service also gets a statement in the resource policy.
171
+
172
+ ```ts
173
+ fn.grantInvoke(iam.Role.fromRoleArn(this, 'Partner', 'arn:aws:iam::444455556666:role/caller'));
174
+ ```
175
+
176
+ For principals you can't grant to (a whole account, an organization, an AWS service with conditions), use `addPermission`. The `id` becomes the statement's `Sid`:
177
+
178
+ ```ts
179
+ fn.addPermission('PartnerAccount', { principal: new iam.AccountPrincipal('444455556666') });
180
+ fn.addPermission('MyOrg', { principal: new iam.OrganizationPrincipal('o-a1b2c3d4e5'), endpoint: fn.endpoint });
181
+ fn.addPermission('Cdn', {
182
+ principal: new iam.ServicePrincipal('cloudfront.amazonaws.com'),
183
+ sourceArn: `arn:aws:cloudfront::${this.account}:distribution/EDFDVBD6EXAMPLE`,
184
+ });
185
+ ```
186
+
187
+ `addPermission` allows calling every endpoint unless you pass `endpoint`. For other actions, such as letting another account create revisions, use `fn.addToResourcePolicy(statement)`. Statements use the endpoint ARN for invoking and the function ARN for actions on the function.
188
+
189
+ - **One resource policy per function, written by the function's stack.** The construct creates it (`AWS::Lambda::ResourcePolicy`) with the first statement. CloudFormation can't attach a second one: another stack, or a `CfnResourcePolicy` of your own on the function, fails at change-set validation with "already exists". If you attached one yourself, move its statements into `addPermission` or `addToResourcePolicy`. Each update of the policy replaces any statements added outside CloudFormation.
190
+ - **Public policies are rejected.** Lambda refuses a policy that lets anyone call the function, and the construct fails synthesis first. A `*` principal is only accepted with a condition that pins the caller, such as `aws:PrincipalOrgID` (`iam.OrganizationPrincipal`) or `aws:SourceAccount`. For a public endpoint, use `authType: NONE`.
191
+ - **Scope AWS services to your resource.** Lambda accepts a service principal with no condition, which would let that service call the endpoint on behalf of any account. The construct warns unless you give `sourceArn` or `sourceAccount` (or an `aws:SourceArn`, `aws:SourceAccount`, `aws:SourceOrgID` or `aws:SourceOrgPaths` condition).
192
+ - Lambda copies the policy to every region the function's endpoints serve from. The copy is eventually consistent, and in tests changes applied in every region within seconds.
193
+
194
+ ### CloudFront
195
+
196
+ Put a CloudFront distribution (`aws-cdk-lib/aws-cloudfront`) in front of an `AWS_IAM` endpoint to serve the public with a custom domain, caching and AWS WAF. Viewers don't sign anything, and only your distribution may call the endpoint:
197
+
198
+ ```ts
199
+ new cloudfront.Distribution(this, 'Cdn', {
200
+ defaultBehavior: {
201
+ origin: WebFunctionOrigin.withOriginAccessControl(fn.endpoint),
202
+ viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
203
+ allowedMethods: cloudfront.AllowedMethods.ALLOW_ALL,
204
+ cachePolicy: cloudfront.CachePolicy.CACHING_DISABLED,
205
+ originRequestPolicy: cloudfront.OriginRequestPolicy.ALL_VIEWER_EXCEPT_HOST_HEADER,
206
+ },
207
+ });
208
+ ```
209
+
210
+ `withOriginAccessControl` adds:
211
+ - an origin access control (origin type `lambda`, signing behavior `always-amz-auth`, the only one CloudFront accepts for Web Function origins), one per stack and signing protocol: SigV4 for a regional domain, SigV4a for a `MULTI_REGION` endpoint's global domain;
212
+ - a statement in the function's resource policy that allows `cloudfront.amazonaws.com` to call this endpoint on behalf of this distribution only (`aws:SourceArn`).
213
+
214
+ Some things to know:
215
+ - **Forward everything except `Host`.** The endpoint answers 404 when `Host` is the distribution's domain, so use `ALL_VIEWER_EXCEPT_HOST_HEADER` (not `ALL_VIEWER`), or a policy of your own without `Host`.
216
+ - **Your application can still authenticate viewers.** CloudFront signs in its own headers and passes the viewer's `Authorization` header (a JWT, for example) through unchanged, but only when `Authorization` is in the cache policy. CloudFront drops it from `GET` and `HEAD` requests otherwise:
217
+
218
+ ```ts
219
+ const forwardAuthorization = new cloudfront.CachePolicy(this, 'ForwardAuthorization', {
220
+ headerBehavior: cloudfront.CacheHeaderBehavior.allowList('Authorization'),
221
+ minTtl: Duration.seconds(0),
222
+ defaultTtl: Duration.seconds(0),
223
+ maxTtl: Duration.seconds(1), // a cache key with headers needs caching enabled; 0/0/1 keeps it off in practice
224
+ });
225
+ ```
226
+ - Request bodies work without clients sending `x-amz-content-sha256`: CloudFront signs `POST`, `PUT` and `PATCH` requests with an unsigned payload.
227
+ - A `PER_REGION` endpoint's origin calls one region: the home region, or the one you pass as `region`. Use one origin per region, for example in an origin group.
228
+ - A `MULTI_REGION` endpoint can't include opt-in regions (such as `me-central-1`), because CloudFront can't sign for them. The construct fails synthesis.
229
+ - The distribution must be in the function's stack. Lambda@Edge origin-request and origin-response triggers aren't supported on behaviors with this origin.
230
+ - The endpoint stays reachable at its own domain for signed requests your policies allow. Until a new distribution finishes deploying, requests through it can get a transient 403.
231
+ - `new WebFunctionOrigin(endpoint)` is for a public (`NONE`) endpoint, for example behind AWS WAF. Lambda doesn't authenticate those requests, so the endpoint's own domain stays public too.
232
+
159
233
  ### Functions defined elsewhere
160
234
 
161
235
  Import a Web Function defined in another stack or app to grant access to it, read its metrics, or reference its revisions:
@@ -173,7 +247,7 @@ live.metricConcurrentRequests().createAlarm(this, 'Busy', { threshold: 60, evalu
173
247
 
174
248
  An imported function's metrics default to its own region. Its endpoints, revisions and log groups stay with the stack that defines it.
175
249
 
176
- `grantInvoke` adds to the caller's IAM policy, which is all a caller in the function's account needs. A caller in another account also needs the function's resource policy to allow it, which this library doesn't manage yet.
250
+ An imported function's `grantInvoke` adds to the caller's IAM policy only, which is all a caller in the function's account needs. A caller in another account also needs the function's resource policy to allow it, which only the function's own stack can change: `addToResourcePolicy` on an imported function adds nothing and warns.
177
251
 
178
252
  ## Configuration
179
253
 
@@ -194,6 +268,7 @@ api.addEnvironment('FEATURE_FLAG', 'on');
194
268
  table.grantReadWriteData(api); // the default role trusts lambda.amazonaws.com
195
269
  ```
196
270
 
271
+ - **Each execution environment has 2 vCPUs and 2 GB of memory.** There's no memory setting as on Lambda functions; scale with `maxConcurrencyPerEnvironment` and more environments instead.
197
272
  - Requests handled by one environment share module-level state, so keep handlers concurrency-safe.
198
273
  - Environment variable names starting with `AWS_` are reserved.
199
274
  - **Renaming the function replaces it and changes its URL.** A generated name depends on the construct path, so moving the construct renames it too.
@@ -228,7 +303,7 @@ new NodejsWebFunction(this, 'Api', {
228
303
 
229
304
  Lambda Web Functions download code as the `lambda.amazonaws.com` service principal, from a **versioned** bucket, and the CDK bootstrap bucket allows neither. So each stack gets a small code bucket, and the code is copied into it on deploy. The bucket is emptied and deleted with the stack.
230
305
 
231
- Code copies, log groups in other regions, revision cleanup and the bucket's emptying run in one custom resource Lambda per stack. Its logs go to a log group the stack owns, kept for a month and deleted with the stack.
306
+ Copying code, managing the function's log groups in every region, looking up regional URLs, cleaning up old revisions, creating rollback alarms in other regions and emptying the code bucket all run in one custom resource Lambda per stack. Its logs go to a log group the stack owns, kept for a month and deleted with the stack.
232
307
 
233
308
  ## Revisions
234
309
 
@@ -364,7 +439,7 @@ Web Functions log in two tiers:
364
439
  └──────────────────┘ └──────────────────────────────────────────┘
365
440
  ```
366
441
 
367
- **Query `fn.logGroup`**, the home-region group that receives every region's logs. The service would create missing groups without retention and never delete them, so the construct creates and owns all of them: both home-region groups, and `<group>.local` in every other region of the endpoint.
442
+ **Query `fn.logGroup`**, the home-region group that receives every region's logs. The service would create missing groups without retention and never delete them, so the construct creates and owns all of them: both home-region groups, and `<group>.local` in every other region any of its endpoints serves from.
368
443
 
369
444
  ```ts
370
445
  new WebFunction(this, 'Api', {
@@ -385,8 +460,9 @@ new WebFunction(this, 'Api', {
385
460
 
386
461
  ## Limitations
387
462
 
388
- - Not yet supported: VPC access (network connectors), resource-policy permissions, KMS encryption, tracing, and a CloudFront origin.
389
- - `cdk deploy --hotswap` and `cdk watch` don't support Web Functions.
463
+ - Not yet supported: VPC access (network connectors), KMS encryption, and tracing.
464
+ - **Hotswap skips Web Functions without a warning.** `cdk deploy --hotswap` and `cdk watch`, which hotswaps by default, report `(no changes)` for a code or configuration change and the endpoint keeps serving the old revision. Use `cdk watch --hotswap-fallback` (or `cdk deploy --hotswap-fallback`): it deploys Web Function changes through CloudFormation, in about 40 seconds for a home-region endpoint.
465
+ - Fixed limits: 512 MB of code (unzipped) and 32 KB of environment variables per revision, 512 MB of `/tmp` per execution environment, and 128 KiB of headers per request.
390
466
  - Quotas: 10 endpoints and about 50 revisions per function (Lambda cleans up older revisions automatically), and 10,000 requests per second per endpoint. Per account and region: 100,000 requests per second and 2,000 Arm64 vCPUs (each execution environment uses 2). The account quotas are adjustable, and new accounts start lower. See [Lambda quotas](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html).
391
467
 
392
468
  ## Development
package/lib/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './enums';
2
2
  export * from './web-function';
3
3
  export * from './web-function-endpoint';
4
+ export * from './web-function-origin';
4
5
  export * from './web-function-grants';
5
6
  export * from './nodejs-web-function';
6
7
  export * from './web-function-revision';
package/lib/index.js CHANGED
@@ -17,8 +17,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./enums"), exports);
18
18
  __exportStar(require("./web-function"), exports);
19
19
  __exportStar(require("./web-function-endpoint"), exports);
20
+ __exportStar(require("./web-function-origin"), exports);
20
21
  __exportStar(require("./web-function-grants"), exports);
21
22
  __exportStar(require("./nodejs-web-function"), exports);
22
23
  __exportStar(require("./web-function-revision"), exports);
23
24
  __exportStar(require("./web-function-deployment"), exports);
24
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDBDQUF3QjtBQUN4QixpREFBK0I7QUFDL0IsMERBQXdDO0FBQ3hDLHdEQUFzQztBQUN0Qyx3REFBc0M7QUFDdEMsMERBQXdDO0FBQ3hDLDREQUEwQyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCAqIGZyb20gJy4vZW51bXMnO1xuZXhwb3J0ICogZnJvbSAnLi93ZWItZnVuY3Rpb24nO1xuZXhwb3J0ICogZnJvbSAnLi93ZWItZnVuY3Rpb24tZW5kcG9pbnQnO1xuZXhwb3J0ICogZnJvbSAnLi93ZWItZnVuY3Rpb24tZ3JhbnRzJztcbmV4cG9ydCAqIGZyb20gJy4vbm9kZWpzLXdlYi1mdW5jdGlvbic7XG5leHBvcnQgKiBmcm9tICcuL3dlYi1mdW5jdGlvbi1yZXZpc2lvbic7XG5leHBvcnQgKiBmcm9tICcuL3dlYi1mdW5jdGlvbi1kZXBsb3ltZW50JztcbiJdfQ==
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDBDQUF3QjtBQUN4QixpREFBK0I7QUFDL0IsMERBQXdDO0FBQ3hDLHdEQUFzQztBQUN0Qyx3REFBc0M7QUFDdEMsd0RBQXNDO0FBQ3RDLDBEQUF3QztBQUN4Qyw0REFBMEMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2VudW1zJztcbmV4cG9ydCAqIGZyb20gJy4vd2ViLWZ1bmN0aW9uJztcbmV4cG9ydCAqIGZyb20gJy4vd2ViLWZ1bmN0aW9uLWVuZHBvaW50JztcbmV4cG9ydCAqIGZyb20gJy4vd2ViLWZ1bmN0aW9uLW9yaWdpbic7XG5leHBvcnQgKiBmcm9tICcuL3dlYi1mdW5jdGlvbi1ncmFudHMnO1xuZXhwb3J0ICogZnJvbSAnLi9ub2RlanMtd2ViLWZ1bmN0aW9uJztcbmV4cG9ydCAqIGZyb20gJy4vd2ViLWZ1bmN0aW9uLXJldmlzaW9uJztcbmV4cG9ydCAqIGZyb20gJy4vd2ViLWZ1bmN0aW9uLWRlcGxveW1lbnQnO1xuIl19
@@ -49,7 +49,7 @@ const web_function_1 = require("./web-function");
49
49
  * bundle, and `NODE_OPTIONS=--enable-source-maps` when source maps are on.
50
50
  */
51
51
  class NodejsWebFunction extends web_function_1.WebFunction {
52
- static [JSII_RTTI_SYMBOL_1] = { fqn: "@ashishpandeyone/cdk-lambda-web-function.NodejsWebFunction", version: "0.1.4" };
52
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@ashishpandeyone/cdk-lambda-web-function.NodejsWebFunction", version: "0.1.6" };
53
53
  constructor(scope, id, props) {
54
54
  const runtime = props.runtime ?? lambda.Runtime.NODEJS_24_X;
55
55
  const entry = (0, bundling_1.resolveEntry)(props.entry);
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Checks on a Web Function's resource policy, run at synthesis on the resolved document.
3
+ *
4
+ * Lambda rejects a public policy at deploy time ("Lambda blocked the creation of this policy because it would grant
5
+ * public access"): a `*` principal is only accepted when a trusted condition key pins the caller. A service principal
6
+ * without a source condition is accepted, but lets any account's use of that service call the endpoint.
7
+ */
8
+ export interface ResourcePolicyFindings {
9
+ /** Statements Lambda would reject as public. */
10
+ readonly errors: string[];
11
+ /** Service principals allowed without a source condition. */
12
+ readonly unscopedServices: string[];
13
+ }
14
+ /** Inspects a resolved policy document (`{ Statement: [...] }`). */
15
+ export declare function inspectResourcePolicy(document: any): ResourcePolicyFindings;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * Checks on a Web Function's resource policy, run at synthesis on the resolved document.
4
+ *
5
+ * Lambda rejects a public policy at deploy time ("Lambda blocked the creation of this policy because it would grant
6
+ * public access"): a `*` principal is only accepted when a trusted condition key pins the caller. A service principal
7
+ * without a source condition is accepted, but lets any account's use of that service call the endpoint.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.inspectResourcePolicy = inspectResourcePolicy;
11
+ /** Condition keys Lambda accepts to make a `*` principal non-public (Lambda Web Function permissions docs, 2026-10). */
12
+ const TRUSTED_KEYS = [
13
+ 'aws:PrincipalAccount', 'aws:PrincipalArn', 'aws:PrincipalOrgID', 'aws:PrincipalOrgPaths', 'aws:SourceAccount', 'aws:SourceArn',
14
+ 'aws:SourceOrgID', 'aws:SourceOrgPaths', 'aws:SourceVpc', 'aws:SourceVpcArn', 'aws:SourceVpce', 'aws:VpceAccount', 'aws:VpceOrgID',
15
+ 'aws:VpceOrgPaths', 'aws:Ec2InstanceSourceVpc', 'aws:UserId', 'aws:PrincipalServiceName', 'aws:PrincipalServiceNamesList',
16
+ 'aws:PrincipalIsAWSService', 'lambda:SourceFunctionArn',
17
+ ].map((k) => k.toLowerCase());
18
+ /** Condition keys that tie a service principal to the resource or account calling on its behalf. */
19
+ const SOURCE_KEYS = ['aws:SourceArn', 'aws:SourceAccount', 'aws:SourceOrgID', 'aws:SourceOrgPaths'].map((k) => k.toLowerCase());
20
+ /** Inspects a resolved policy document (`{ Statement: [...] }`). */
21
+ function inspectResourcePolicy(document) {
22
+ const errors = [];
23
+ const unscopedServices = [];
24
+ for (const [i, s] of (document?.Statement ?? []).entries()) {
25
+ if (s.Effect !== 'Allow')
26
+ continue;
27
+ const keys = conditionKeys(s.Condition);
28
+ const name = s.Sid ? `statement '${s.Sid}'` : `statement ${i + 1}`;
29
+ if (isWildcard(s.Principal) && !keys.some((k) => TRUSTED_KEYS.includes(k))) {
30
+ errors.push(`${name} allows principal '*': Lambda rejects public resource policies. Pin the caller with a condition such as aws:PrincipalOrgID or aws:SourceAccount (e.g. iam.OrganizationPrincipal), or name the accounts`);
31
+ }
32
+ const services = list(s.Principal?.Service).map(String);
33
+ if (services.length > 0 && !keys.some((k) => SOURCE_KEYS.includes(k))) {
34
+ unscopedServices.push(...services);
35
+ }
36
+ }
37
+ return { errors, unscopedServices };
38
+ }
39
+ function isWildcard(principal) {
40
+ return principal === '*' || list(principal?.AWS).includes('*');
41
+ }
42
+ function conditionKeys(condition) {
43
+ return Object.values(condition ?? {}).flatMap((byKey) => Object.keys(byKey ?? {})).map((k) => k.toLowerCase());
44
+ }
45
+ function list(value) {
46
+ return value === undefined ? [] : Array.isArray(value) ? value : [value];
47
+ }
48
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtcG9saWN5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3ByaXZhdGUvcmVzb3VyY2UtcG9saWN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBcUJILHNEQWdCQztBQW5DRCx3SEFBd0g7QUFDeEgsTUFBTSxZQUFZLEdBQUc7SUFDbkIsc0JBQXNCLEVBQUUsa0JBQWtCLEVBQUUsb0JBQW9CLEVBQUUsdUJBQXVCLEVBQUUsbUJBQW1CLEVBQUUsZUFBZTtJQUMvSCxpQkFBaUIsRUFBRSxvQkFBb0IsRUFBRSxlQUFlLEVBQUUsa0JBQWtCLEVBQUUsZ0JBQWdCLEVBQUUsaUJBQWlCLEVBQUUsZUFBZTtJQUNsSSxrQkFBa0IsRUFBRSwwQkFBMEIsRUFBRSxZQUFZLEVBQUUsMEJBQTBCLEVBQUUsK0JBQStCO0lBQ3pILDJCQUEyQixFQUFFLDBCQUEwQjtDQUN4RCxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7QUFFOUIsb0dBQW9HO0FBQ3BHLE1BQU0sV0FBVyxHQUFHLENBQUMsZUFBZSxFQUFFLG1CQUFtQixFQUFFLGlCQUFpQixFQUFFLG9CQUFvQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztBQVNoSSxvRUFBb0U7QUFDcEUsU0FBZ0IscUJBQXFCLENBQUMsUUFBYTtJQUNqRCxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFDNUIsTUFBTSxnQkFBZ0IsR0FBYSxFQUFFLENBQUM7SUFDdEMsS0FBSyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1FBQzNELElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxPQUFPO1lBQUUsU0FBUztRQUNuQyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNuRSxJQUFJLFVBQVUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUMzRSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSx3TUFBd00sQ0FBQyxDQUFDO1FBQy9OLENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDeEQsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3RFLGdCQUFnQixDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxDQUFDO0FBQ3RDLENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FBQyxTQUFjO0lBQ2hDLE9BQU8sU0FBUyxLQUFLLEdBQUcsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNqRSxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsU0FBYztJQUNuQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQVUsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQ3RILENBQUM7QUFFRCxTQUFTLElBQUksQ0FBQyxLQUFjO0lBQzFCLE9BQU8sS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDM0UsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2hlY2tzIG9uIGEgV2ViIEZ1bmN0aW9uJ3MgcmVzb3VyY2UgcG9saWN5LCBydW4gYXQgc3ludGhlc2lzIG9uIHRoZSByZXNvbHZlZCBkb2N1bWVudC5cbiAqXG4gKiBMYW1iZGEgcmVqZWN0cyBhIHB1YmxpYyBwb2xpY3kgYXQgZGVwbG95IHRpbWUgKFwiTGFtYmRhIGJsb2NrZWQgdGhlIGNyZWF0aW9uIG9mIHRoaXMgcG9saWN5IGJlY2F1c2UgaXQgd291bGQgZ3JhbnRcbiAqIHB1YmxpYyBhY2Nlc3NcIik6IGEgYCpgIHByaW5jaXBhbCBpcyBvbmx5IGFjY2VwdGVkIHdoZW4gYSB0cnVzdGVkIGNvbmRpdGlvbiBrZXkgcGlucyB0aGUgY2FsbGVyLiBBIHNlcnZpY2UgcHJpbmNpcGFsXG4gKiB3aXRob3V0IGEgc291cmNlIGNvbmRpdGlvbiBpcyBhY2NlcHRlZCwgYnV0IGxldHMgYW55IGFjY291bnQncyB1c2Ugb2YgdGhhdCBzZXJ2aWNlIGNhbGwgdGhlIGVuZHBvaW50LlxuICovXG5cbi8qKiBDb25kaXRpb24ga2V5cyBMYW1iZGEgYWNjZXB0cyB0byBtYWtlIGEgYCpgIHByaW5jaXBhbCBub24tcHVibGljIChMYW1iZGEgV2ViIEZ1bmN0aW9uIHBlcm1pc3Npb25zIGRvY3MsIDIwMjYtMTApLiAqL1xuY29uc3QgVFJVU1RFRF9LRVlTID0gW1xuICAnYXdzOlByaW5jaXBhbEFjY291bnQnLCAnYXdzOlByaW5jaXBhbEFybicsICdhd3M6UHJpbmNpcGFsT3JnSUQnLCAnYXdzOlByaW5jaXBhbE9yZ1BhdGhzJywgJ2F3czpTb3VyY2VBY2NvdW50JywgJ2F3czpTb3VyY2VBcm4nLFxuICAnYXdzOlNvdXJjZU9yZ0lEJywgJ2F3czpTb3VyY2VPcmdQYXRocycsICdhd3M6U291cmNlVnBjJywgJ2F3czpTb3VyY2VWcGNBcm4nLCAnYXdzOlNvdXJjZVZwY2UnLCAnYXdzOlZwY2VBY2NvdW50JywgJ2F3czpWcGNlT3JnSUQnLFxuICAnYXdzOlZwY2VPcmdQYXRocycsICdhd3M6RWMySW5zdGFuY2VTb3VyY2VWcGMnLCAnYXdzOlVzZXJJZCcsICdhd3M6UHJpbmNpcGFsU2VydmljZU5hbWUnLCAnYXdzOlByaW5jaXBhbFNlcnZpY2VOYW1lc0xpc3QnLFxuICAnYXdzOlByaW5jaXBhbElzQVdTU2VydmljZScsICdsYW1iZGE6U291cmNlRnVuY3Rpb25Bcm4nLFxuXS5tYXAoKGspID0+IGsudG9Mb3dlckNhc2UoKSk7XG5cbi8qKiBDb25kaXRpb24ga2V5cyB0aGF0IHRpZSBhIHNlcnZpY2UgcHJpbmNpcGFsIHRvIHRoZSByZXNvdXJjZSBvciBhY2NvdW50IGNhbGxpbmcgb24gaXRzIGJlaGFsZi4gKi9cbmNvbnN0IFNPVVJDRV9LRVlTID0gWydhd3M6U291cmNlQXJuJywgJ2F3czpTb3VyY2VBY2NvdW50JywgJ2F3czpTb3VyY2VPcmdJRCcsICdhd3M6U291cmNlT3JnUGF0aHMnXS5tYXAoKGspID0+IGsudG9Mb3dlckNhc2UoKSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VQb2xpY3lGaW5kaW5ncyB7XG4gIC8qKiBTdGF0ZW1lbnRzIExhbWJkYSB3b3VsZCByZWplY3QgYXMgcHVibGljLiAqL1xuICByZWFkb25seSBlcnJvcnM6IHN0cmluZ1tdO1xuICAvKiogU2VydmljZSBwcmluY2lwYWxzIGFsbG93ZWQgd2l0aG91dCBhIHNvdXJjZSBjb25kaXRpb24uICovXG4gIHJlYWRvbmx5IHVuc2NvcGVkU2VydmljZXM6IHN0cmluZ1tdO1xufVxuXG4vKiogSW5zcGVjdHMgYSByZXNvbHZlZCBwb2xpY3kgZG9jdW1lbnQgKGB7IFN0YXRlbWVudDogWy4uLl0gfWApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluc3BlY3RSZXNvdXJjZVBvbGljeShkb2N1bWVudDogYW55KTogUmVzb3VyY2VQb2xpY3lGaW5kaW5ncyB7XG4gIGNvbnN0IGVycm9yczogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgdW5zY29wZWRTZXJ2aWNlczogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBbaSwgc10gb2YgKGRvY3VtZW50Py5TdGF0ZW1lbnQgPz8gW10pLmVudHJpZXMoKSkge1xuICAgIGlmIChzLkVmZmVjdCAhPT0gJ0FsbG93JykgY29udGludWU7XG4gICAgY29uc3Qga2V5cyA9IGNvbmRpdGlvbktleXMocy5Db25kaXRpb24pO1xuICAgIGNvbnN0IG5hbWUgPSBzLlNpZCA/IGBzdGF0ZW1lbnQgJyR7cy5TaWR9J2AgOiBgc3RhdGVtZW50ICR7aSArIDF9YDtcbiAgICBpZiAoaXNXaWxkY2FyZChzLlByaW5jaXBhbCkgJiYgIWtleXMuc29tZSgoaykgPT4gVFJVU1RFRF9LRVlTLmluY2x1ZGVzKGspKSkge1xuICAgICAgZXJyb3JzLnB1c2goYCR7bmFtZX0gYWxsb3dzIHByaW5jaXBhbCAnKic6IExhbWJkYSByZWplY3RzIHB1YmxpYyByZXNvdXJjZSBwb2xpY2llcy4gUGluIHRoZSBjYWxsZXIgd2l0aCBhIGNvbmRpdGlvbiBzdWNoIGFzIGF3czpQcmluY2lwYWxPcmdJRCBvciBhd3M6U291cmNlQWNjb3VudCAoZS5nLiBpYW0uT3JnYW5pemF0aW9uUHJpbmNpcGFsKSwgb3IgbmFtZSB0aGUgYWNjb3VudHNgKTtcbiAgICB9XG4gICAgY29uc3Qgc2VydmljZXMgPSBsaXN0KHMuUHJpbmNpcGFsPy5TZXJ2aWNlKS5tYXAoU3RyaW5nKTtcbiAgICBpZiAoc2VydmljZXMubGVuZ3RoID4gMCAmJiAha2V5cy5zb21lKChrKSA9PiBTT1VSQ0VfS0VZUy5pbmNsdWRlcyhrKSkpIHtcbiAgICAgIHVuc2NvcGVkU2VydmljZXMucHVzaCguLi5zZXJ2aWNlcyk7XG4gICAgfVxuICB9XG4gIHJldHVybiB7IGVycm9ycywgdW5zY29wZWRTZXJ2aWNlcyB9O1xufVxuXG5mdW5jdGlvbiBpc1dpbGRjYXJkKHByaW5jaXBhbDogYW55KTogYm9vbGVhbiB7XG4gIHJldHVybiBwcmluY2lwYWwgPT09ICcqJyB8fCBsaXN0KHByaW5jaXBhbD8uQVdTKS5pbmNsdWRlcygnKicpO1xufVxuXG5mdW5jdGlvbiBjb25kaXRpb25LZXlzKGNvbmRpdGlvbjogYW55KTogc3RyaW5nW10ge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhjb25kaXRpb24gPz8ge30pLmZsYXRNYXAoKGJ5S2V5OiBhbnkpID0+IE9iamVjdC5rZXlzKGJ5S2V5ID8/IHt9KSkubWFwKChrKSA9PiBrLnRvTG93ZXJDYXNlKCkpO1xufVxuXG5mdW5jdGlvbiBsaXN0KHZhbHVlOiB1bmtub3duKTogdW5rbm93bltdIHtcbiAgcmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgPyBbXSA6IEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdO1xufVxuIl19
@@ -11,7 +11,7 @@ const MAX_STEPS = 20;
11
11
  * How an endpoint moves its traffic to a new revision.
12
12
  */
13
13
  class WebFunctionDeployment {
14
- static [JSII_RTTI_SYMBOL_1] = { fqn: "@ashishpandeyone/cdk-lambda-web-function.WebFunctionDeployment", version: "0.1.4" };
14
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "@ashishpandeyone/cdk-lambda-web-function.WebFunctionDeployment", version: "0.1.6" };
15
15
  /**
16
16
  * All traffic moves to the new revision at once, as soon as it's ready (the default).
17
17
  */
@@ -152,13 +152,14 @@ export declare class WebFunctionEndpoint extends Construct {
152
152
  readonly url: string;
153
153
  /** Grants on this endpoint (e.g. `grants.invoke(principal)`). */
154
154
  readonly grants: WebFunctionGrants;
155
+ /** The function this endpoint belongs to. */
156
+ readonly webFunction: IWebFunction;
155
157
  /**
156
158
  * The alarms this endpoint created for its deployment's `rollbackOn`, one per threshold in every region it serves from
157
159
  * (the home region's first). Empty without `rollbackOn`.
158
160
  */
159
161
  readonly rollbackAlarms: cloudwatch.IAlarm[];
160
162
  private readonly homeRegion;
161
- private readonly webFunction;
162
163
  private readonly resource;
163
164
  private weights;
164
165
  private routed;
@@ -171,6 +172,12 @@ export declare class WebFunctionEndpoint extends Construct {
171
172
  * @param region one of `regions`
172
173
  */
173
174
  regionalUrl(region: string): string;
175
+ /**
176
+ * The domain name of this endpoint in one region. Only for `PER_REGION` endpoints.
177
+ *
178
+ * @param region one of `regions`
179
+ */
180
+ regionalDomainName(region: string): string;
174
181
  /**
175
182
  * Routes the endpoint to `revision` instead of the function's current revision, optionally sharing
176
183
  * traffic with one more revision (`additionalRevisions`, which gets its weight; `revision` gets the rest).