cdk-aws-lambda-powertools-blueprint 0.1.0

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/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 24
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # cdk-aws-lambda-powertools-blueprint
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Initial version of library
@@ -0,0 +1,82 @@
1
+ # Contributing Guidelines
2
+
3
+ Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
4
+ documentation, we greatly value feedback and contributions from our community.
5
+
6
+ Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
7
+ information to effectively respond to your bug report or contribution.
8
+
9
+ ## Reporting Bugs/Feature Requests
10
+
11
+ We welcome you to use the GitHub issue tracker to report bugs or suggest features.
12
+
13
+ When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
14
+ reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
15
+
16
+ - A reproducible test case or series of steps
17
+ - The version of our code being used
18
+ - Any modifications you've made relevant to the bug
19
+ - Anything unusual about your environment or deployment
20
+
21
+ ## Contributing via Pull Requests
22
+
23
+ ### Pull Request Checklist
24
+
25
+ - [ ] Testing
26
+ - Unit test added (prefer not to modify an existing test, otherwise, it's probably a breaking change)
27
+ - [ ] Docs
28
+ - **README**: README updated if necessary
29
+ - **JSDocs**: Inline JSDocs updated if necessary
30
+ - [ ] Title and Description
31
+ - **Change type**: title prefixed with **fix**, **feat** and module name in parens, which will appear in changelog
32
+ - **Title**: use lower-case and doesn't end with a period
33
+ - **Breaking?**: last paragraph: "BREAKING CHANGE: <describe what changed + link for details>"
34
+ - **Issues**: Indicate issues fixed via: "**Fixes #xxx**" or "**Closes #xxx**"
35
+
36
+ Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
37
+
38
+ 1. You are working against the latest source on the _main_ branch.
39
+
40
+ ---
41
+
42
+ ### Step 1: Open Issue
43
+
44
+ If there isn't one already, open an issue describing what you intend to contribute. It's useful to communicate in advance, because sometimes, someone is already working in this space, so maybe it's worth collaborating with them instead of duplicating the efforts.
45
+
46
+ ### Step 2: Fork the repository
47
+
48
+ GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/). Make sure you are working against the latest source on the _main_ branch.
49
+
50
+ ### Step 3: Setup
51
+
52
+ The following tools need to be installed on your system prior to building `cdk-aws-lambda-powertools-blueprint` locally:
53
+
54
+ - [Node.js >= 22.0.0](https://nodejs.org/download/release/latest-v22.x/)
55
+ - We recommend using a version in [Active LTS](https://nodejs.org/en/about/releases/)
56
+
57
+ Install dependencies
58
+
59
+ - `npm install`
60
+
61
+ ### Step 4: Develop
62
+
63
+ 1. Change code
64
+ 2. If relevant, add [tests](./test/)
65
+ 3. Run tests
66
+ - `npm run test`
67
+ 4. Build
68
+ - `npm run build`
69
+ 5. Update relevant documentation
70
+ 6. Create the commit with relevant files
71
+
72
+ ### Step 5: Make the pull request
73
+
74
+ Send us a [pull request](https://help.github.com/articles/creating-a-pull-request/), answering any default questions in the pull request interface. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
75
+
76
+ ## Finding contributions to work on
77
+
78
+ Looking at the existing issues is a great way to find something to contribute on. Looking at any 'help wanted' issues is a great place to start.
79
+
80
+ ## Licensing
81
+
82
+ See the [LICENSE](./LICENSE) file for the project's licensing.
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2026 Miles Bardon
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,126 @@
1
+ # CDK AWS Lambda Powertools Blueprint
2
+
3
+ This [Blueprint](https://docs.aws.amazon.com/cdk/v2/guide/blueprints.html) enables Function constructs defined in your Stack to have all the necessary properties configured to take advantage of [Powertools for AWS Lambda](https://docs.aws.amazon.com/powertools/).
4
+
5
+ ## Benefits
6
+
7
+ Including the `PowertoolsFunctionDefaults` in your property injectors will apply the following defaults to all Functions in your Stacks.
8
+
9
+ - The official [Powertools Lambda Layer](https://docs.aws.amazon.com/powertools/typescript/latest/getting-started/lambda-layers/) (only on NodeJS and Python runtimes).
10
+ - The POWERTOOLS_SERVICE_NAME environment variable automatically set to the provided `functionName`.
11
+
12
+ ## Usage
13
+
14
+ Different Lambda Function runtimes will take advantage of different behaviour, demonstrated in each section.
15
+
16
+ ### NodeJS Functions
17
+
18
+ Both `Function` and `NodejsFunction` constructs are supported with the `NODEJS` Runtime Family. If you opt to use the latter, you will also benefit from the `bundling` props being updated to exclude the `@aws-lambda-powertools/*` modules from the final bundle. This will have the benefit of reducing the final bundle size, which can lead to performance improvements.
19
+
20
+ ```ts
21
+ import { App } from "aws-cdk-lib";
22
+ import { Runtime } from "aws-cdk-lib/aws-lambda";
23
+ import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
24
+
25
+ import { PowertoolsFunctionDefaults } from "cdk-aws-lambda-powertools-blueprint";
26
+
27
+ const app = new App({
28
+ propertyInjectors: [new PowertoolsFunctionDefaults()],
29
+ });
30
+
31
+ const stack = new Stack(app, "MyStack");
32
+
33
+ const fn = new NodejsFunction(stack, "MyFunction", {
34
+ functionName: "service-my-function",
35
+ runtime: Runtime.NODEJS_22_X,
36
+ });
37
+ ```
38
+
39
+ You can also select a specific Powertools version if you don't want to use the `latest` version of the Lambda Layer. For example;
40
+
41
+ ```ts
42
+ import { App } from "aws-cdk-lib";
43
+
44
+ import { PowertoolsFunctionDefaults } from "cdk-aws-lambda-powertools-blueprint";
45
+
46
+ const app = new App({
47
+ propertyInjectors: [
48
+ new PowertoolsFunctionDefaults({
49
+ powertoolsVersion: "2.30.0",
50
+ }),
51
+ ],
52
+ });
53
+ ```
54
+
55
+ ### Python Functions
56
+
57
+ All `Function` constructs with the `PYTHON` Runtime Family will have the latest [Lambda Layer](https://docs.aws.amazon.com/powertools/python/latest/getting-started/install/#lambda-layer) appropriate to the configured architecture applied. If no `architecture` is applied, the function will fall back to `x86_64` architecture and a warning will be added to your stack annotations.
58
+
59
+ ```ts
60
+ import { App } from "aws-cdk-lib";
61
+ import { Function, Runtime } from "aws-cdk-lib/aws-lambda";
62
+
63
+ import { PowertoolsFunctionDefaults } from "cdk-aws-lambda-powertools-blueprint";
64
+
65
+ const app = new App({
66
+ propertyInjectors: [new PowertoolsFunctionDefaults()],
67
+ });
68
+
69
+ const stack = new Stack(app, "MyStack");
70
+
71
+ const fn = new Function(stack, "MyFunction", {
72
+ functionName: "service-my-function",
73
+ runtime: Runtime.PYTHON_3_13,
74
+ });
75
+ ```
76
+
77
+ ### All other runtimes
78
+
79
+ Every Function runtime is supported, but at the time of writing no others have a Lambda Layer to apply to the function. As a result, only the POWERTOOLS_SERVICE_NAME environment variable will be added to any function that is configured with a different runtime than NodeJS or Python.
80
+
81
+ ```ts
82
+ import { App } from "aws-cdk-lib";
83
+ import { Function, Runtime } from "aws-cdk-lib/aws-lambda";
84
+
85
+ import { PowertoolsFunctionDefaults } from "cdk-aws-lambda-powertools-blueprint";
86
+
87
+ const app = new App({
88
+ propertyInjectors: [new PowertoolsFunctionDefaults()],
89
+ });
90
+
91
+ const stack = new Stack(app, "MyStack");
92
+
93
+ const fn = new Function(stack, "MyFunction", {
94
+ functionName: "service-my-function",
95
+ runtime: Runtime.JAVA_21,
96
+ });
97
+ ```
98
+
99
+ ## Development
100
+
101
+ If you wish to contribute to this project, please follow the [Contribution guidelines](./CONTRIBUTING.md).
102
+
103
+ Install dependencies
104
+
105
+ ```sh
106
+ npm install
107
+ ```
108
+
109
+ Build the package
110
+
111
+ ```sh
112
+ npm run build
113
+ ```
114
+
115
+ Run unit tests
116
+
117
+ ```sh
118
+ npm run test
119
+ ```
120
+
121
+ Run linting checks and fix linting issues
122
+
123
+ ```sh
124
+ npm run lint
125
+ npm run lint:fix
126
+ ```
package/biome.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3
+ "vcs": {
4
+ "enabled": true,
5
+ "clientKind": "git",
6
+ "useIgnoreFile": true
7
+ },
8
+ "files": {
9
+ "ignoreUnknown": false
10
+ },
11
+ "formatter": {
12
+ "enabled": true,
13
+ "indentStyle": "tab"
14
+ },
15
+ "linter": {
16
+ "enabled": true,
17
+ "rules": {
18
+ "recommended": true
19
+ }
20
+ },
21
+ "javascript": {
22
+ "formatter": {
23
+ "quoteStyle": "double"
24
+ }
25
+ },
26
+ "assist": {
27
+ "enabled": true,
28
+ "actions": {
29
+ "source": {
30
+ "organizeImports": "on"
31
+ }
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,27 @@
1
+ import { type InjectionContext, type IPropertyInjector } from "aws-cdk-lib";
2
+ export interface PowertoolsFunctionDefaultsProps {
3
+ /**
4
+ * The Powertools package version to load into the Lambda.
5
+ * Only provide this value if you don't want the latest version.
6
+ *
7
+ * Setting this field will only have an effect on NodeJS Functions.
8
+ *
9
+ * @default "latest"
10
+ */
11
+ readonly powertoolsVersion?: string;
12
+ }
13
+ /**
14
+ * Applies Powertools-specific defaults to Functions in your Stack.
15
+ *
16
+ * For NodeJS and Python Functions, also applies the official Lambda Layer
17
+ * for the appropriate runtime and architecture.
18
+ *
19
+ * NodeJS Functions will also have the '@aws-lambda-powertools/*' modules
20
+ * excluded from being bundled to minimise the bundle size.
21
+ */
22
+ export declare class PowertoolsFunctionDefaults implements IPropertyInjector {
23
+ readonly constructUniqueId: string;
24
+ private powertoolsVersion;
25
+ constructor(props?: PowertoolsFunctionDefaultsProps);
26
+ inject(originalProps: any, context: InjectionContext): any;
27
+ }
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PowertoolsFunctionDefaults = void 0;
4
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
5
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
6
+ const aws_lambda_1 = require("aws-cdk-lib/aws-lambda");
7
+ const aws_lambda_nodejs_1 = require("aws-cdk-lib/aws-lambda-nodejs");
8
+ const aws_ssm_1 = require("aws-cdk-lib/aws-ssm");
9
+ /**
10
+ * Applies Powertools-specific defaults to Functions in your Stack.
11
+ *
12
+ * For NodeJS and Python Functions, also applies the official Lambda Layer
13
+ * for the appropriate runtime and architecture.
14
+ *
15
+ * NodeJS Functions will also have the '@aws-lambda-powertools/*' modules
16
+ * excluded from being bundled to minimise the bundle size.
17
+ */
18
+ class PowertoolsFunctionDefaults {
19
+ static [JSII_RTTI_SYMBOL_1] = { fqn: "cdk-aws-lambda-powertools-blueprint.PowertoolsFunctionDefaults", version: "0.1.0" };
20
+ constructUniqueId;
21
+ powertoolsVersion;
22
+ constructor(props) {
23
+ this.constructUniqueId = aws_lambda_1.Function.PROPERTY_INJECTION_ID;
24
+ this.powertoolsVersion = props?.powertoolsVersion ?? "latest";
25
+ }
26
+ inject(originalProps, context) {
27
+ const originalFunctionProps = originalProps;
28
+ const scope = context.scope;
29
+ let powertoolsLayerParameterName = "";
30
+ // Determine if the Function runtime has a layer available
31
+ switch (originalFunctionProps.runtime?.family) {
32
+ case aws_lambda_1.RuntimeFamily.NODEJS: {
33
+ // https://docs.aws.amazon.com/powertools/typescript/latest/getting-started/lambda-layers/#lookup-layer-arn-via-aws-ssm-parameter-store
34
+ powertoolsLayerParameterName = `/aws/service/powertools/typescript/generic/all/${this.powertoolsVersion}`;
35
+ break;
36
+ }
37
+ case aws_lambda_1.RuntimeFamily.PYTHON: {
38
+ const architecture = originalFunctionProps.architecture ?? aws_lambda_1.Architecture.X86_64;
39
+ if (!originalFunctionProps.architecture) {
40
+ aws_cdk_lib_1.Annotations.of(scope).addWarningV2("cdk-aws-lambda-powertools-blueprint:Blueprint.missingArchitecture", `Function ${context.id} has no specified Architecture and will fall back to ${aws_lambda_1.Architecture.X86_64.name}.`);
41
+ }
42
+ // https://docs.aws.amazon.com/powertools/python/latest/getting-started/install/#using-ssm-parameter-store
43
+ powertoolsLayerParameterName = `/aws/service/powertools/python/${architecture.name}/${originalFunctionProps.runtime.name}/latest`;
44
+ break;
45
+ }
46
+ default: {
47
+ aws_cdk_lib_1.Annotations.of(scope).addInfo(`Function ${context.id} is configured with runtime ${originalFunctionProps.runtime} and will not have the Powertools Lambda Layer applied.`);
48
+ }
49
+ }
50
+ let powertoolsLayer;
51
+ const layers = originalFunctionProps.layers ?? [];
52
+ if (powertoolsLayerParameterName) {
53
+ // Create the LayerVersion construct to apply to the Function
54
+ powertoolsLayer = aws_lambda_1.LayerVersion.fromLayerVersionArn(scope, `${context.id}-PowertoolsLayer`, aws_ssm_1.StringParameter.valueForStringParameter(scope, powertoolsLayerParameterName));
55
+ // Apply the Powertools layer to the end of the layers array
56
+ layers.push(powertoolsLayer);
57
+ // For NodejsFunction Constructs, we also want to override the bundling to make sure the Lambda bundle is as small as possible
58
+ if (context.scope instanceof aws_lambda_nodejs_1.NodejsFunction) {
59
+ const originalNodejsProps = originalFunctionProps;
60
+ return {
61
+ ...originalNodejsProps,
62
+ layers,
63
+ bundling: {
64
+ ...originalNodejsProps.bundling,
65
+ externalModules: [
66
+ ...(originalNodejsProps.bundling?.externalModules ?? []),
67
+ "@aws-sdk/*",
68
+ "@aws-lambda-powertools/*",
69
+ ],
70
+ },
71
+ };
72
+ }
73
+ }
74
+ return {
75
+ ...originalProps,
76
+ layers,
77
+ };
78
+ }
79
+ }
80
+ exports.PowertoolsFunctionDefaults = PowertoolsFunctionDefaults;
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9saWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLDZDQUlxQjtBQUNyQix1REFPZ0M7QUFDaEMscUVBR3VDO0FBQ3ZDLGlEQUFzRDtBQWN0RDs7Ozs7Ozs7R0FRRztBQUNILE1BQWEsMEJBQTBCOztJQUN0QixpQkFBaUIsQ0FBUztJQUVsQyxpQkFBaUIsQ0FBUztJQUVsQyxZQUFZLEtBQXVDO1FBQ2xELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxxQkFBYyxDQUFDLHFCQUFxQixDQUFDO1FBRTlELElBQUksQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsaUJBQWlCLElBQUksUUFBUSxDQUFDO0lBQy9ELENBQUM7SUFFTSxNQUFNLENBQUMsYUFBa0IsRUFBRSxPQUF5QjtRQUMxRCxNQUFNLHFCQUFxQixHQUMxQixhQUFhLENBQUM7UUFFZixNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBdUIsQ0FBQztRQUU5QyxJQUFJLDRCQUE0QixHQUFHLEVBQUUsQ0FBQztRQUV0QywwREFBMEQ7UUFDMUQsUUFBUSxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDL0MsS0FBSywwQkFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQzNCLHVJQUF1STtnQkFDdkksNEJBQTRCLEdBQUcsa0RBQWtELElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO2dCQUMxRyxNQUFNO1lBQ1AsQ0FBQztZQUNELEtBQUssMEJBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUMzQixNQUFNLFlBQVksR0FDakIscUJBQXFCLENBQUMsWUFBWSxJQUFJLHlCQUFZLENBQUMsTUFBTSxDQUFDO2dCQUUzRCxJQUFJLENBQUMscUJBQXFCLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ3pDLHlCQUFXLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLFlBQVksQ0FDakMsbUVBQW1FLEVBQ25FLFlBQVksT0FBTyxDQUFDLEVBQUUsd0RBQXdELHlCQUFZLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxDQUN6RyxDQUFDO2dCQUNILENBQUM7Z0JBRUQsMEdBQTBHO2dCQUMxRyw0QkFBNEIsR0FBRyxrQ0FBa0MsWUFBWSxDQUFDLElBQUksSUFBSSxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxTQUFTLENBQUM7Z0JBQ2xJLE1BQU07WUFDUCxDQUFDO1lBQ0QsT0FBTyxDQUFDLENBQUMsQ0FBQztnQkFDVCx5QkFBVyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxPQUFPLENBQzVCLFlBQVksT0FBTyxDQUFDLEVBQUUsK0JBQStCLHFCQUFxQixDQUFDLE9BQU8seURBQXlELENBQzNJLENBQUM7WUFDSCxDQUFDO1FBQ0YsQ0FBQztRQUVELElBQUksZUFBMEMsQ0FBQztRQUUvQyxNQUFNLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1FBRWxELElBQUksNEJBQTRCLEVBQUUsQ0FBQztZQUNsQyw2REFBNkQ7WUFDN0QsZUFBZSxHQUFHLHlCQUFZLENBQUMsbUJBQW1CLENBQ2pELEtBQUssRUFDTCxHQUFHLE9BQU8sQ0FBQyxFQUFFLGtCQUFrQixFQUMvQix5QkFBZSxDQUFDLHVCQUF1QixDQUN0QyxLQUFLLEVBQ0wsNEJBQTRCLENBQzVCLENBQ0QsQ0FBQztZQUVGLDREQUE0RDtZQUM1RCxNQUFNLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRTdCLDhIQUE4SDtZQUM5SCxJQUFJLE9BQU8sQ0FBQyxLQUFLLFlBQVksa0NBQWMsRUFBRSxDQUFDO2dCQUM3QyxNQUFNLG1CQUFtQixHQUF3QixxQkFBcUIsQ0FBQztnQkFFdkUsT0FBTztvQkFDTixHQUFHLG1CQUFtQjtvQkFDdEIsTUFBTTtvQkFDTixRQUFRLEVBQUU7d0JBQ1QsR0FBRyxtQkFBbUIsQ0FBQyxRQUFRO3dCQUMvQixlQUFlLEVBQUU7NEJBQ2hCLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLEVBQUUsZUFBZSxJQUFJLEVBQUUsQ0FBQzs0QkFDeEQsWUFBWTs0QkFDWiwwQkFBMEI7eUJBQzFCO3FCQUNEO2lCQUNELENBQUM7WUFDSCxDQUFDO1FBQ0YsQ0FBQztRQUVELE9BQU87WUFDTixHQUFHLGFBQWE7WUFDaEIsTUFBTTtTQUNOLENBQUM7SUFDSCxDQUFDOztBQXpGRixnRUEwRkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuXHRBbm5vdGF0aW9ucyxcblx0dHlwZSBJbmplY3Rpb25Db250ZXh0LFxuXHR0eXBlIElQcm9wZXJ0eUluamVjdG9yLFxufSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG5cdEFyY2hpdGVjdHVyZSxcblx0dHlwZSBGdW5jdGlvblByb3BzLFxuXHR0eXBlIElMYXllclZlcnNpb24sXG5cdEZ1bmN0aW9uIGFzIExhbWJkYUZ1bmN0aW9uLFxuXHRMYXllclZlcnNpb24sXG5cdFJ1bnRpbWVGYW1pbHksXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQge1xuXHROb2RlanNGdW5jdGlvbixcblx0dHlwZSBOb2RlanNGdW5jdGlvblByb3BzLFxufSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanNcIjtcbmltcG9ydCB7IFN0cmluZ1BhcmFtZXRlciB9IGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc3NtXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG93ZXJ0b29sc0Z1bmN0aW9uRGVmYXVsdHNQcm9wcyB7XG5cdC8qKlxuXHQgKiBUaGUgUG93ZXJ0b29scyBwYWNrYWdlIHZlcnNpb24gdG8gbG9hZCBpbnRvIHRoZSBMYW1iZGEuXG5cdCAqIE9ubHkgcHJvdmlkZSB0aGlzIHZhbHVlIGlmIHlvdSBkb24ndCB3YW50IHRoZSBsYXRlc3QgdmVyc2lvbi5cblx0ICpcblx0ICogU2V0dGluZyB0aGlzIGZpZWxkIHdpbGwgb25seSBoYXZlIGFuIGVmZmVjdCBvbiBOb2RlSlMgRnVuY3Rpb25zLlxuXHQgKlxuXHQgKiBAZGVmYXVsdCBcImxhdGVzdFwiXG5cdCAqL1xuXHRyZWFkb25seSBwb3dlcnRvb2xzVmVyc2lvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBBcHBsaWVzIFBvd2VydG9vbHMtc3BlY2lmaWMgZGVmYXVsdHMgdG8gRnVuY3Rpb25zIGluIHlvdXIgU3RhY2suXG4gKlxuICogRm9yIE5vZGVKUyBhbmQgUHl0aG9uIEZ1bmN0aW9ucywgYWxzbyBhcHBsaWVzIHRoZSBvZmZpY2lhbCBMYW1iZGEgTGF5ZXJcbiAqIGZvciB0aGUgYXBwcm9wcmlhdGUgcnVudGltZSBhbmQgYXJjaGl0ZWN0dXJlLlxuICpcbiAqIE5vZGVKUyBGdW5jdGlvbnMgd2lsbCBhbHNvIGhhdmUgdGhlICdAYXdzLWxhbWJkYS1wb3dlcnRvb2xzLyonIG1vZHVsZXNcbiAqIGV4Y2x1ZGVkIGZyb20gYmVpbmcgYnVuZGxlZCB0byBtaW5pbWlzZSB0aGUgYnVuZGxlIHNpemUuXG4gKi9cbmV4cG9ydCBjbGFzcyBQb3dlcnRvb2xzRnVuY3Rpb25EZWZhdWx0cyBpbXBsZW1lbnRzIElQcm9wZXJ0eUluamVjdG9yIHtcblx0cHVibGljIHJlYWRvbmx5IGNvbnN0cnVjdFVuaXF1ZUlkOiBzdHJpbmc7XG5cblx0cHJpdmF0ZSBwb3dlcnRvb2xzVmVyc2lvbjogc3RyaW5nO1xuXG5cdGNvbnN0cnVjdG9yKHByb3BzPzogUG93ZXJ0b29sc0Z1bmN0aW9uRGVmYXVsdHNQcm9wcykge1xuXHRcdHRoaXMuY29uc3RydWN0VW5pcXVlSWQgPSBMYW1iZGFGdW5jdGlvbi5QUk9QRVJUWV9JTkpFQ1RJT05fSUQ7XG5cblx0XHR0aGlzLnBvd2VydG9vbHNWZXJzaW9uID0gcHJvcHM/LnBvd2VydG9vbHNWZXJzaW9uID8/IFwibGF0ZXN0XCI7XG5cdH1cblxuXHRwdWJsaWMgaW5qZWN0KG9yaWdpbmFsUHJvcHM6IGFueSwgY29udGV4dDogSW5qZWN0aW9uQ29udGV4dCkge1xuXHRcdGNvbnN0IG9yaWdpbmFsRnVuY3Rpb25Qcm9wczogRnVuY3Rpb25Qcm9wcyB8IE5vZGVqc0Z1bmN0aW9uUHJvcHMgPVxuXHRcdFx0b3JpZ2luYWxQcm9wcztcblxuXHRcdGNvbnN0IHNjb3BlID0gY29udGV4dC5zY29wZSBhcyBMYW1iZGFGdW5jdGlvbjtcblxuXHRcdGxldCBwb3dlcnRvb2xzTGF5ZXJQYXJhbWV0ZXJOYW1lID0gXCJcIjtcblxuXHRcdC8vIERldGVybWluZSBpZiB0aGUgRnVuY3Rpb24gcnVudGltZSBoYXMgYSBsYXllciBhdmFpbGFibGVcblx0XHRzd2l0Y2ggKG9yaWdpbmFsRnVuY3Rpb25Qcm9wcy5ydW50aW1lPy5mYW1pbHkpIHtcblx0XHRcdGNhc2UgUnVudGltZUZhbWlseS5OT0RFSlM6IHtcblx0XHRcdFx0Ly8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3Bvd2VydG9vbHMvdHlwZXNjcmlwdC9sYXRlc3QvZ2V0dGluZy1zdGFydGVkL2xhbWJkYS1sYXllcnMvI2xvb2t1cC1sYXllci1hcm4tdmlhLWF3cy1zc20tcGFyYW1ldGVyLXN0b3JlXG5cdFx0XHRcdHBvd2VydG9vbHNMYXllclBhcmFtZXRlck5hbWUgPSBgL2F3cy9zZXJ2aWNlL3Bvd2VydG9vbHMvdHlwZXNjcmlwdC9nZW5lcmljL2FsbC8ke3RoaXMucG93ZXJ0b29sc1ZlcnNpb259YDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRjYXNlIFJ1bnRpbWVGYW1pbHkuUFlUSE9OOiB7XG5cdFx0XHRcdGNvbnN0IGFyY2hpdGVjdHVyZSA9XG5cdFx0XHRcdFx0b3JpZ2luYWxGdW5jdGlvblByb3BzLmFyY2hpdGVjdHVyZSA/PyBBcmNoaXRlY3R1cmUuWDg2XzY0O1xuXG5cdFx0XHRcdGlmICghb3JpZ2luYWxGdW5jdGlvblByb3BzLmFyY2hpdGVjdHVyZSkge1xuXHRcdFx0XHRcdEFubm90YXRpb25zLm9mKHNjb3BlKS5hZGRXYXJuaW5nVjIoXG5cdFx0XHRcdFx0XHRcImNkay1hd3MtbGFtYmRhLXBvd2VydG9vbHMtYmx1ZXByaW50OkJsdWVwcmludC5taXNzaW5nQXJjaGl0ZWN0dXJlXCIsXG5cdFx0XHRcdFx0XHRgRnVuY3Rpb24gJHtjb250ZXh0LmlkfSBoYXMgbm8gc3BlY2lmaWVkIEFyY2hpdGVjdHVyZSBhbmQgd2lsbCBmYWxsIGJhY2sgdG8gJHtBcmNoaXRlY3R1cmUuWDg2XzY0Lm5hbWV9LmAsXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9wb3dlcnRvb2xzL3B5dGhvbi9sYXRlc3QvZ2V0dGluZy1zdGFydGVkL2luc3RhbGwvI3VzaW5nLXNzbS1wYXJhbWV0ZXItc3RvcmVcblx0XHRcdFx0cG93ZXJ0b29sc0xheWVyUGFyYW1ldGVyTmFtZSA9IGAvYXdzL3NlcnZpY2UvcG93ZXJ0b29scy9weXRob24vJHthcmNoaXRlY3R1cmUubmFtZX0vJHtvcmlnaW5hbEZ1bmN0aW9uUHJvcHMucnVudGltZS5uYW1lfS9sYXRlc3RgO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGRlZmF1bHQ6IHtcblx0XHRcdFx0QW5ub3RhdGlvbnMub2Yoc2NvcGUpLmFkZEluZm8oXG5cdFx0XHRcdFx0YEZ1bmN0aW9uICR7Y29udGV4dC5pZH0gaXMgY29uZmlndXJlZCB3aXRoIHJ1bnRpbWUgJHtvcmlnaW5hbEZ1bmN0aW9uUHJvcHMucnVudGltZX0gYW5kIHdpbGwgbm90IGhhdmUgdGhlIFBvd2VydG9vbHMgTGFtYmRhIExheWVyIGFwcGxpZWQuYCxcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRsZXQgcG93ZXJ0b29sc0xheWVyOiBJTGF5ZXJWZXJzaW9uIHwgdW5kZWZpbmVkO1xuXG5cdFx0Y29uc3QgbGF5ZXJzID0gb3JpZ2luYWxGdW5jdGlvblByb3BzLmxheWVycyA/PyBbXTtcblxuXHRcdGlmIChwb3dlcnRvb2xzTGF5ZXJQYXJhbWV0ZXJOYW1lKSB7XG5cdFx0XHQvLyBDcmVhdGUgdGhlIExheWVyVmVyc2lvbiBjb25zdHJ1Y3QgdG8gYXBwbHkgdG8gdGhlIEZ1bmN0aW9uXG5cdFx0XHRwb3dlcnRvb2xzTGF5ZXIgPSBMYXllclZlcnNpb24uZnJvbUxheWVyVmVyc2lvbkFybihcblx0XHRcdFx0c2NvcGUsXG5cdFx0XHRcdGAke2NvbnRleHQuaWR9LVBvd2VydG9vbHNMYXllcmAsXG5cdFx0XHRcdFN0cmluZ1BhcmFtZXRlci52YWx1ZUZvclN0cmluZ1BhcmFtZXRlcihcblx0XHRcdFx0XHRzY29wZSxcblx0XHRcdFx0XHRwb3dlcnRvb2xzTGF5ZXJQYXJhbWV0ZXJOYW1lLFxuXHRcdFx0XHQpLFxuXHRcdFx0KTtcblxuXHRcdFx0Ly8gQXBwbHkgdGhlIFBvd2VydG9vbHMgbGF5ZXIgdG8gdGhlIGVuZCBvZiB0aGUgbGF5ZXJzIGFycmF5XG5cdFx0XHRsYXllcnMucHVzaChwb3dlcnRvb2xzTGF5ZXIpO1xuXG5cdFx0XHQvLyBGb3IgTm9kZWpzRnVuY3Rpb24gQ29uc3RydWN0cywgd2UgYWxzbyB3YW50IHRvIG92ZXJyaWRlIHRoZSBidW5kbGluZyB0byBtYWtlIHN1cmUgdGhlIExhbWJkYSBidW5kbGUgaXMgYXMgc21hbGwgYXMgcG9zc2libGVcblx0XHRcdGlmIChjb250ZXh0LnNjb3BlIGluc3RhbmNlb2YgTm9kZWpzRnVuY3Rpb24pIHtcblx0XHRcdFx0Y29uc3Qgb3JpZ2luYWxOb2RlanNQcm9wczogTm9kZWpzRnVuY3Rpb25Qcm9wcyA9IG9yaWdpbmFsRnVuY3Rpb25Qcm9wcztcblxuXHRcdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRcdC4uLm9yaWdpbmFsTm9kZWpzUHJvcHMsXG5cdFx0XHRcdFx0bGF5ZXJzLFxuXHRcdFx0XHRcdGJ1bmRsaW5nOiB7XG5cdFx0XHRcdFx0XHQuLi5vcmlnaW5hbE5vZGVqc1Byb3BzLmJ1bmRsaW5nLFxuXHRcdFx0XHRcdFx0ZXh0ZXJuYWxNb2R1bGVzOiBbXG5cdFx0XHRcdFx0XHRcdC4uLihvcmlnaW5hbE5vZGVqc1Byb3BzLmJ1bmRsaW5nPy5leHRlcm5hbE1vZHVsZXMgPz8gW10pLFxuXHRcdFx0XHRcdFx0XHRcIkBhd3Mtc2RrLypcIixcblx0XHRcdFx0XHRcdFx0XCJAYXdzLWxhbWJkYS1wb3dlcnRvb2xzLypcIixcblx0XHRcdFx0XHRcdF0sXG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0Li4ub3JpZ2luYWxQcm9wcyxcblx0XHRcdGxheWVycyxcblx0XHR9O1xuXHR9XG59XG4iXX0=