cdk-local-lambda 0.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/LICENSE +202 -0
- package/README.md +94 -0
- package/lib/aspect/docker-function-hook.d.ts +18 -0
- package/lib/aspect/docker-function-hook.js +31 -0
- package/lib/aspect/live-lambda-aspect.d.ts +85 -0
- package/lib/aspect/live-lambda-aspect.js +277 -0
- package/lib/aspect/live-lambda-bootstrap.d.ts +17 -0
- package/lib/aspect/live-lambda-bootstrap.js +260 -0
- package/lib/aspect/nodejs-function-hook.d.ts +20 -0
- package/lib/aspect/nodejs-function-hook.js +27 -0
- package/lib/bootstrap-stack/bootstrap-stack.d.ts +60 -0
- package/lib/bootstrap-stack/bootstrap-stack.js +338 -0
- package/lib/cli/appsync/client.d.ts +30 -0
- package/lib/cli/appsync/client.js +227 -0
- package/lib/cli/cdk-app.d.ts +7 -0
- package/lib/cli/cdk-app.js +25 -0
- package/lib/cli/commands/bootstrap.d.ts +9 -0
- package/lib/cli/commands/bootstrap.js +50 -0
- package/lib/cli/commands/local.d.ts +40 -0
- package/lib/cli/commands/local.js +1172 -0
- package/lib/cli/daemon.d.ts +22 -0
- package/lib/cli/daemon.js +18 -0
- package/lib/cli/docker/container.d.ts +116 -0
- package/lib/cli/docker/container.js +414 -0
- package/lib/cli/docker/types.d.ts +71 -0
- package/lib/cli/docker/types.js +5 -0
- package/lib/cli/docker/watcher.d.ts +44 -0
- package/lib/cli/docker/watcher.js +115 -0
- package/lib/cli/index.d.ts +9 -0
- package/lib/cli/index.js +26 -0
- package/lib/cli/runtime-api/server.d.ts +102 -0
- package/lib/cli/runtime-api/server.js +396 -0
- package/lib/cli/runtime-api/types.d.ts +149 -0
- package/lib/cli/runtime-api/types.js +10 -0
- package/lib/cli/runtime-wrapper/nodejs-runtime.d.ts +16 -0
- package/lib/cli/runtime-wrapper/nodejs-runtime.js +248 -0
- package/lib/cli/watcher/file-watcher.d.ts +32 -0
- package/lib/cli/watcher/file-watcher.js +57 -0
- package/lib/functions/bridge/appsync-client.d.ts +73 -0
- package/lib/functions/bridge/appsync-client.js +345 -0
- package/lib/functions/bridge/handler.d.ts +17 -0
- package/lib/functions/bridge/handler.js +79 -0
- package/lib/functions/bridge/ssm-config.d.ts +19 -0
- package/lib/functions/bridge/ssm-config.js +45 -0
- package/lib/functions/bridge-builder/handler.d.ts +12 -0
- package/lib/functions/bridge-builder/handler.js +181 -0
- package/lib/functions/bridge-docker/runtime.d.ts +9 -0
- package/lib/functions/bridge-docker/runtime.js +127 -0
- package/lib/index.d.ts +24 -0
- package/lib/index.js +28 -0
- package/lib/shared/types.d.ts +102 -0
- package/lib/shared/types.js +125 -0
- package/package.json +111 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDK Aspect to transform Lambda functions for live debugging
|
|
3
|
+
*
|
|
4
|
+
* When applied to a CDK app/stack, this aspect:
|
|
5
|
+
* 1. Replaces Lambda code with the bridge handler from the bootstrap stack's S3 bucket
|
|
6
|
+
* 2. Grants IAM permissions for AppSync Events
|
|
7
|
+
* 3. Adds a tag with the local handler path for the daemon to discover
|
|
8
|
+
*
|
|
9
|
+
* The bridge uses AWS_LAMBDA_FUNCTION_NAME (auto-injected by Lambda) for channel routing.
|
|
10
|
+
* The daemon discovers functions by querying Lambda API for functions with the live-lambda tag.
|
|
11
|
+
*/
|
|
12
|
+
import * as cdk from "aws-cdk-lib";
|
|
13
|
+
import * as iam from "aws-cdk-lib/aws-iam";
|
|
14
|
+
import * as ssm from "aws-cdk-lib/aws-ssm";
|
|
15
|
+
import { LIVE_LAMBDA_DOCKER_TAG, LIVE_LAMBDA_TAG, SSM_BASE_PATH, } from "../shared/types.js";
|
|
16
|
+
import { getDockerContextPath, isDockerImageFunction, } from "./docker-function-hook.js";
|
|
17
|
+
import { getEntryPath, getHandlerName } from "./nodejs-function-hook.js";
|
|
18
|
+
// Regex to strip file extension from entry path
|
|
19
|
+
const EXTENSION_REGEX = /\.(ts|js|mjs|cjs|mts|cts)$/;
|
|
20
|
+
/**
|
|
21
|
+
* CDK Aspect that transforms Lambda functions for live debugging.
|
|
22
|
+
*
|
|
23
|
+
* Usage in bin/app.ts:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const app = new cdk.App();
|
|
26
|
+
* const stack = new MyStack(app, 'MyStack');
|
|
27
|
+
*
|
|
28
|
+
* if (process.env.CDK_LIVE === 'true') {
|
|
29
|
+
* cdk.Aspects.of(app).add(new LiveLambdaAspect());
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export class LiveLambdaAspect {
|
|
34
|
+
props;
|
|
35
|
+
processedFunctions = new Set();
|
|
36
|
+
constructor(props = {}) {
|
|
37
|
+
this.props = props;
|
|
38
|
+
}
|
|
39
|
+
visit(node) {
|
|
40
|
+
// Check if this is a Lambda Function using duck-typing instead of instanceof
|
|
41
|
+
// This avoids issues with multiple copies of aws-cdk-lib being loaded
|
|
42
|
+
if (!this.isLambdaFunction(node)) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Cast to lambda.Function for type checking (we've verified it's a Lambda)
|
|
46
|
+
const fn = node;
|
|
47
|
+
// Skip if already processed (aspects can visit multiple times)
|
|
48
|
+
const nodeId = node.node.addr;
|
|
49
|
+
if (this.processedFunctions.has(nodeId)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Generate a unique function ID from the construct path
|
|
53
|
+
const functionId = this.generateFunctionId(fn);
|
|
54
|
+
// Check exclusion list
|
|
55
|
+
if (this.props.excludeFunctions?.includes(functionId)) {
|
|
56
|
+
console.log(`[LiveLambda] Skipping excluded function: ${functionId}`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Check pattern match
|
|
60
|
+
if (this.props.functionPattern &&
|
|
61
|
+
!this.props.functionPattern.test(functionId)) {
|
|
62
|
+
console.log(`[LiveLambda] Skipping non-matching function: ${functionId}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
console.log(`[LiveLambda] Transforming function: ${functionId}`);
|
|
66
|
+
const stackName = this.props.stackName || cdk.Stack.of(fn).stackName;
|
|
67
|
+
// Check if this is a DockerImageFunction
|
|
68
|
+
const isDockerFunction = isDockerImageFunction(fn);
|
|
69
|
+
if (isDockerFunction) {
|
|
70
|
+
console.log(`[LiveLambda] Detected DockerImageFunction: ${functionId}`);
|
|
71
|
+
this.transformDockerFunction(fn, stackName, functionId);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Get handler paths before we modify anything
|
|
75
|
+
const handlerPaths = this.getHandlerPaths(fn);
|
|
76
|
+
// Skip unsupported functions (not NodejsFunction or DockerImageFunction)
|
|
77
|
+
if (!handlerPaths) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const { originalHandler, localHandler } = handlerPaths;
|
|
81
|
+
// Transform the function
|
|
82
|
+
this.transformFunction(fn, stackName, functionId, originalHandler, localHandler);
|
|
83
|
+
}
|
|
84
|
+
this.processedFunctions.add(nodeId);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Check if a construct is a Lambda Function using duck-typing.
|
|
88
|
+
* This avoids instanceof issues when multiple copies of aws-cdk-lib are loaded.
|
|
89
|
+
*/
|
|
90
|
+
isLambdaFunction(node) {
|
|
91
|
+
// Check by constructor name - handles Function, DockerImageFunction, NodejsFunction, etc.
|
|
92
|
+
// Also handles our patched versions like DockerImageFunctionWithCapture
|
|
93
|
+
const constructorName = node.constructor.name;
|
|
94
|
+
// CDK appends "2" to class names in some versions
|
|
95
|
+
const isFunction = constructorName === "Function" ||
|
|
96
|
+
constructorName === "Function2" ||
|
|
97
|
+
constructorName.endsWith("Function") ||
|
|
98
|
+
constructorName.endsWith("Function2") ||
|
|
99
|
+
constructorName.includes("Function"); // Catch patched versions like DockerImageFunctionWithCapture
|
|
100
|
+
if (!isFunction) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
// Exclude CfnFunction (the L1 construct)
|
|
104
|
+
if (constructorName === "CfnFunction") {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
// Verify it has expected Lambda Function properties
|
|
108
|
+
const maybeFunction = node;
|
|
109
|
+
// Must have functionName and functionArn (IFunction interface)
|
|
110
|
+
if (!maybeFunction.functionName || !maybeFunction.functionArn) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
// Must have a defaultChild (the CfnFunction)
|
|
114
|
+
if (!maybeFunction.node?.defaultChild) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
generateFunctionId(fn) {
|
|
120
|
+
// Use the construct ID as the function ID
|
|
121
|
+
// For nested constructs, join with dashes
|
|
122
|
+
const parts = fn.node.path.split("/");
|
|
123
|
+
// Skip first part (App) and take the rest
|
|
124
|
+
const relevantParts = parts.slice(1);
|
|
125
|
+
return relevantParts.join("-").replace(/[^a-zA-Z0-9-]/g, "-");
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get handler paths for a function.
|
|
129
|
+
* Returns both the original handler (as set in CfnFunction) and the local handler path.
|
|
130
|
+
* Returns null if the function is not supported (e.g., not a NodejsFunction).
|
|
131
|
+
*/
|
|
132
|
+
getHandlerPaths(fn) {
|
|
133
|
+
const cfnFunction = fn.node.defaultChild;
|
|
134
|
+
const originalHandler = cfnFunction.handler || "index.handler";
|
|
135
|
+
const constructId = fn.node.id;
|
|
136
|
+
// Check if captured by the NodejsFunction hook
|
|
137
|
+
const entryPath = getEntryPath(fn);
|
|
138
|
+
const handlerName = getHandlerName(fn) || "handler";
|
|
139
|
+
if (entryPath) {
|
|
140
|
+
// Convert entry path to local handler path
|
|
141
|
+
// e.g., "functions/s3-writer/handler.ts" + "handler" -> "functions/s3-writer/handler.handler"
|
|
142
|
+
const localHandler = `${entryPath.replace(EXTENSION_REGEX, "")}.${handlerName}`;
|
|
143
|
+
console.log(`[LiveLambda] Using captured entry for ${constructId}: ${localHandler}`);
|
|
144
|
+
return { originalHandler, localHandler };
|
|
145
|
+
}
|
|
146
|
+
// No handler path found - this function is not supported (not a NodejsFunction or DockerImageFunction)
|
|
147
|
+
console.log(`[LiveLambda] Skipping unsupported function "${constructId}": ` +
|
|
148
|
+
`not a NodejsFunction or DockerImageFunction (or bootstrap hook was not installed early enough)`);
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Transform a DockerImageFunction to use the bridge Docker image.
|
|
153
|
+
* Stores the local Docker context path in a tag for the daemon to build/run locally.
|
|
154
|
+
*/
|
|
155
|
+
transformDockerFunction(fn, _stackName, functionId) {
|
|
156
|
+
const cfnFunction = fn.node.defaultChild;
|
|
157
|
+
const stack = cdk.Stack.of(fn);
|
|
158
|
+
// Get the docker context path from the hook
|
|
159
|
+
const dockerContextPath = getDockerContextPath(fn);
|
|
160
|
+
if (!dockerContextPath) {
|
|
161
|
+
throw new Error(`[LiveLambda] No docker context path for "${functionId}". ` +
|
|
162
|
+
`The bootstrap hook was not installed early enough. ` +
|
|
163
|
+
`Fix: import "cdk-local-lambda/bootstrap" before any CDK imports (Node.js), ` +
|
|
164
|
+
`or run Bun with "bun --preload cdk-local-lambda/bootstrap".`);
|
|
165
|
+
}
|
|
166
|
+
// Get SSM parameters
|
|
167
|
+
const bootstrapQualifier = stack.node.tryGetContext("@aws-cdk/core:bootstrapQualifier") ||
|
|
168
|
+
"hnb659fds";
|
|
169
|
+
const ssmBasePath = `${SSM_BASE_PATH}/${bootstrapQualifier}`;
|
|
170
|
+
const apiArn = ssm.StringParameter.valueForStringParameter(stack, `${ssmBasePath}/api-arn`);
|
|
171
|
+
// Determine architecture and get appropriate bridge image
|
|
172
|
+
const architecture = this.getArchitecture(cfnFunction);
|
|
173
|
+
const bridgeImageParam = architecture === "arm64" ? "bridge-image-arm64" : "bridge-image-x86_64";
|
|
174
|
+
const bridgeImageUri = ssm.StringParameter.valueForStringParameter(stack, `${ssmBasePath}/${bridgeImageParam}`);
|
|
175
|
+
// Add tag with docker context path for daemon discovery
|
|
176
|
+
// The daemon uses this tag to build and run the container locally
|
|
177
|
+
cfnFunction.tags.setTag(LIVE_LAMBDA_DOCKER_TAG, dockerContextPath);
|
|
178
|
+
// Grant permissions to publish/subscribe to AppSync Events
|
|
179
|
+
fn.addToRolePolicy(new iam.PolicyStatement({
|
|
180
|
+
effect: iam.Effect.ALLOW,
|
|
181
|
+
actions: [
|
|
182
|
+
"appsync:EventConnect",
|
|
183
|
+
"appsync:EventPublish",
|
|
184
|
+
"appsync:EventSubscribe",
|
|
185
|
+
],
|
|
186
|
+
resources: [apiArn, `${apiArn}/*`],
|
|
187
|
+
}));
|
|
188
|
+
// Grant permissions to read SSM parameters (bridge needs AppSync endpoints)
|
|
189
|
+
fn.addToRolePolicy(new iam.PolicyStatement({
|
|
190
|
+
effect: iam.Effect.ALLOW,
|
|
191
|
+
actions: ["ssm:GetParameter", "ssm:GetParameters"],
|
|
192
|
+
resources: [
|
|
193
|
+
`arn:aws:ssm:${stack.region}:${stack.account}:parameter${ssmBasePath}/*`,
|
|
194
|
+
],
|
|
195
|
+
}));
|
|
196
|
+
// Increase timeout to allow for local debugging
|
|
197
|
+
cfnFunction.timeout = 300; // 5 minutes
|
|
198
|
+
// Replace the Docker image with the bridge image
|
|
199
|
+
cfnFunction.code = {
|
|
200
|
+
imageUri: bridgeImageUri,
|
|
201
|
+
};
|
|
202
|
+
console.log(`[LiveLambda] Replaced Docker image with bridge (${architecture})`);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Determine the architecture of a Lambda function.
|
|
206
|
+
* Defaults to x86_64 if not explicitly set.
|
|
207
|
+
*/
|
|
208
|
+
getArchitecture(cfnFunction) {
|
|
209
|
+
const architectures = cfnFunction.architectures;
|
|
210
|
+
if (architectures?.includes("arm64")) {
|
|
211
|
+
return "arm64";
|
|
212
|
+
}
|
|
213
|
+
return "x86_64";
|
|
214
|
+
}
|
|
215
|
+
transformFunction(fn, _stackName, _functionId, _originalHandler, localHandler) {
|
|
216
|
+
const cfnFunction = fn.node.defaultChild;
|
|
217
|
+
const stack = cdk.Stack.of(fn);
|
|
218
|
+
// Read values from SSM parameters (created by bootstrap stack)
|
|
219
|
+
// Use the CDK bootstrap qualifier for proper scoping
|
|
220
|
+
const bootstrapQualifier = stack.node.tryGetContext("@aws-cdk/core:bootstrapQualifier") ||
|
|
221
|
+
"hnb659fds";
|
|
222
|
+
const ssmBasePath = `${SSM_BASE_PATH}/${bootstrapQualifier}`;
|
|
223
|
+
const apiArn = ssm.StringParameter.valueForStringParameter(stack, `${ssmBasePath}/api-arn`);
|
|
224
|
+
const bridgeBucket = ssm.StringParameter.valueForStringParameter(stack, `${ssmBasePath}/bridge-bucket`);
|
|
225
|
+
const bridgeKey = ssm.StringParameter.valueForStringParameter(stack, `${ssmBasePath}/bridge-key`);
|
|
226
|
+
// Add tag with local handler path for daemon discovery
|
|
227
|
+
// The daemon queries Lambda API for functions with this tag
|
|
228
|
+
cfnFunction.tags.setTag(LIVE_LAMBDA_TAG, localHandler);
|
|
229
|
+
// Grant permissions to publish/subscribe to AppSync Events
|
|
230
|
+
fn.addToRolePolicy(new iam.PolicyStatement({
|
|
231
|
+
effect: iam.Effect.ALLOW,
|
|
232
|
+
actions: [
|
|
233
|
+
"appsync:EventConnect",
|
|
234
|
+
"appsync:EventPublish",
|
|
235
|
+
"appsync:EventSubscribe",
|
|
236
|
+
],
|
|
237
|
+
resources: [apiArn, `${apiArn}/*`],
|
|
238
|
+
}));
|
|
239
|
+
// Grant permissions to read SSM parameters (bridge needs AppSync endpoints)
|
|
240
|
+
fn.addToRolePolicy(new iam.PolicyStatement({
|
|
241
|
+
effect: iam.Effect.ALLOW,
|
|
242
|
+
actions: ["ssm:GetParameter", "ssm:GetParameters"],
|
|
243
|
+
resources: [
|
|
244
|
+
`arn:aws:ssm:${stack.region}:${stack.account}:parameter${ssmBasePath}/*`,
|
|
245
|
+
],
|
|
246
|
+
}));
|
|
247
|
+
// Increase timeout to allow for local debugging
|
|
248
|
+
cfnFunction.timeout = 300; // 5 minutes
|
|
249
|
+
// Replace the code with bridge handler from bootstrap stack's S3 bucket
|
|
250
|
+
cfnFunction.code = {
|
|
251
|
+
s3Bucket: bridgeBucket,
|
|
252
|
+
s3Key: bridgeKey,
|
|
253
|
+
};
|
|
254
|
+
cfnFunction.handler = "index.handler";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Helper function to check if live mode is enabled
|
|
259
|
+
*/
|
|
260
|
+
export function isLiveModeEnabled() {
|
|
261
|
+
return process.env.CDK_LIVE === "true";
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Apply live lambda aspect to a CDK app or stack if live mode is enabled.
|
|
265
|
+
*
|
|
266
|
+
* @param scope The CDK app or stack to apply the aspect to
|
|
267
|
+
* @param props Optional configuration for the live lambda aspect
|
|
268
|
+
*/
|
|
269
|
+
export function applyLiveLambdaAspect(scope, props = {}) {
|
|
270
|
+
if (!isLiveModeEnabled()) {
|
|
271
|
+
console.log("[LiveLambda] Live mode not enabled (set CDK_LIVE=true to enable)");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
console.log("[LiveLambda] Live mode enabled - transforming Lambda functions");
|
|
275
|
+
cdk.Aspects.of(scope).add(new LiveLambdaAspect(props));
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGl2ZS1sYW1iZGEtYXNwZWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2FzcGVjdC9saXZlLWxhbWJkYS1hc3BlY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRztBQUVILE9BQU8sS0FBSyxHQUFHLE1BQU0sYUFBYSxDQUFBO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0scUJBQXFCLENBQUE7QUFFMUMsT0FBTyxLQUFLLEdBQUcsTUFBTSxxQkFBcUIsQ0FBQTtBQUUxQyxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLGVBQWUsRUFDZixhQUFhLEdBQ2QsTUFBTSxvQkFBb0IsQ0FBQTtBQUMzQixPQUFPLEVBQ0wsb0JBQW9CLEVBQ3BCLHFCQUFxQixHQUN0QixNQUFNLDJCQUEyQixDQUFBO0FBQ2xDLE9BQU8sRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLE1BQU0sMkJBQTJCLENBQUE7QUFFeEUsZ0RBQWdEO0FBQ2hELE1BQU0sZUFBZSxHQUFHLDRCQUE0QixDQUFBO0FBd0JwRDs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQ1YsS0FBSyxDQUF1QjtJQUM1QixrQkFBa0IsR0FBZ0IsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUU1RCxZQUFZLFFBQStCLEVBQUU7UUFDM0MsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUE7SUFDcEIsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFnQjtRQUNwQiw2RUFBNkU7UUFDN0Usc0VBQXNFO1FBQ3RFLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztZQUNqQyxPQUFNO1FBQ1IsQ0FBQztRQUVELDJFQUEyRTtRQUMzRSxNQUFNLEVBQUUsR0FBRyxJQUFrQyxDQUFBO1FBRTdDLCtEQUErRDtRQUMvRCxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQTtRQUM3QixJ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QUNqQixRQUErQixFQUFFO0lBRWpDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLENBQUM7UUFDekIsT0FBTyxDQUFDLEdBQUcsQ0FDVCxrRUFBa0UsQ0FDbkUsQ0FBQTtRQUNELE9BQU07SUFDUixDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnRUFBZ0UsQ0FBQyxDQUFBO0lBQzdFLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7QUFDeEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ0RLIEFzcGVjdCB0byB0cmFuc2Zvcm0gTGFtYmRhIGZ1bmN0aW9ucyBmb3IgbGl2ZSBkZWJ1Z2dpbmdcbiAqXG4gKiBXaGVuIGFwcGxpZWQgdG8gYSBDREsgYXBwL3N0YWNrLCB0aGlzIGFzcGVjdDpcbiAqIDEuIFJlcGxhY2VzIExhbWJkYSBjb2RlIHdpdGggdGhlIGJyaWRnZSBoYW5kbGVyIGZyb20gdGhlIGJvb3RzdHJhcCBzdGFjaydzIFMzIGJ1Y2tldFxuICogMi4gR3JhbnRzIElBTSBwZXJtaXNzaW9ucyBmb3IgQXBwU3luYyBFdmVudHNcbiAqIDMuIEFkZHMgYSB0YWcgd2l0aCB0aGUgbG9jYWwgaGFuZGxlciBwYXRoIGZvciB0aGUgZGFlbW9uIHRvIGRpc2NvdmVyXG4gKlxuICogVGhlIGJyaWRnZSB1c2VzIEFXU19MQU1CREFfRlVOQ1RJT05fTkFNRSAoYXV0by1pbmplY3RlZCBieSBMYW1iZGEpIGZvciBjaGFubmVsIHJvdXRpbmcuXG4gKiBUaGUgZGFlbW9uIGRpc2NvdmVycyBmdW5jdGlvbnMgYnkgcXVlcnlpbmcgTGFtYmRhIEFQSSBmb3IgZnVuY3Rpb25zIHdpdGggdGhlIGxpdmUtbGFtYmRhIHRhZy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBjZGsgZnJvbSBcImF3cy1jZGstbGliXCJcbmltcG9ydCAqIGFzIGlhbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWlhbVwiXG5pbXBvcnQgdHlwZSAqIGFzIGxhbWJkYSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWxhbWJkYVwiXG5pbXBvcnQgKiBhcyBzc20gZnJvbSBcImF3cy1jZGstbGliL2F3cy1zc21cIlxuaW1wb3J0IHR5cGUgeyBJQ29uc3RydWN0IH0gZnJvbSBcImNvbnN0cnVjdHNcIlxuaW1wb3J0IHtcbiAgTElWRV9MQU1CREFfRE9DS0VSX1RBRyxcbiAgTElWRV9MQU1CREFfVEFHLFxuICBTU01fQkFTRV9QQVRILFxufSBmcm9tIFwiLi4vc2hhcmVkL3R5cGVzLmpzXCJcbmltcG9ydCB7XG4gIGdldERvY2tlckNvbnRleHRQYXRoLFxuICBpc0RvY2tlckltYWdlRnVuY3Rpb24sXG59IGZyb20gXCIuL2RvY2tlci1mdW5jdGlvbi1ob29rLmpzXCJcbmltcG9ydCB7IGdldEVudHJ5UGF0aCwgZ2V0SGFuZGxlck5hbWUgfSBmcm9tIFwiLi9ub2RlanMtZnVuY3Rpb24taG9vay5qc1wiXG5cbi8vIFJlZ2V4IHRvIHN0cmlwIGZpbGUgZXh0ZW5zaW9uIGZyb20gZW50cnkgcGF0aFxuY29uc3QgRVhURU5TSU9OX1JFR0VYID0gL1xcLih0c3xqc3xtanN8Y2pzfG10c3xjdHMpJC9cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBMaXZlTGFtYmRhQXNwZWN0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTGl2ZUxhbWJkYUFzcGVjdFByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBzdGFjayBuYW1lIHRvIHVzZSBmb3IgY2hhbm5lbCByb3V0aW5nLlxuICAgKiBJZiBub3QgcHJvdmlkZWQsIHVzZXMgdGhlIHN0YWNrIG5hbWUgZnJvbSB0aGUgZnVuY3Rpb24ncyBzdGFjay5cbiAgICovXG4gIHN0YWNrTmFtZT86IHN0cmluZ1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbDogUGF0dGVybiB0byBtYXRjaCBmdW5jdGlvbiBjb25zdHJ1Y3QgSURzIHRvIHRyYW5zZm9ybS5cbiAgICogSWYgbm90IHByb3ZpZGVkLCBhbGwgTGFtYmRhIGZ1bmN0aW9ucyBhcmUgdHJhbnNmb3JtZWQuXG4gICAqL1xuICBmdW5jdGlvblBhdHRlcm4/OiBSZWdFeHBcblxuICAvKipcbiAgICogT3B0aW9uYWw6IEZ1bmN0aW9uIGNvbnN0cnVjdCBJRHMgdG8gZXhjbHVkZSBmcm9tIHRyYW5zZm9ybWF0aW9uLlxuICAgKi9cbiAgZXhjbHVkZUZ1bmN0aW9ucz86IHN0cmluZ1tdXG59XG5cbi8qKlxuICogQ0RLIEFzcGVjdCB0aGF0IHRyYW5zZm9ybXMgTGFtYmRhIGZ1bmN0aW9ucyBmb3IgbGl2ZSBkZWJ1Z2dpbmcuXG4gKlxuICogVXNhZ2UgaW4gYmluL2FwcC50czpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGFwcCA9IG5ldyBjZGsuQXBwKCk7XG4gKiBjb25zdCBzdGFjayA9IG5ldyBNeVN0YWNrKGFwcCwgJ015U3RhY2snKTtcbiAqXG4gKiBpZiAocHJvY2Vzcy5lbnYuQ0RLX0xJVkUgPT09ICd0cnVlJykge1xuICogICBjZGsuQXNwZWN0cy5vZihhcHApLmFkZChuZXcgTGl2ZUxhbWJkYUFzcGVjdCgpKTtcbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgTGl2ZUxhbWJkYUFzcGVjdCBpbXBsZW1lbnRzIGNkay5JQXNwZWN0IHtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9wczogTGl2ZUxhbWJkYUFzcGVjdFByb3BzXG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvY2Vzc2VkRnVuY3Rpb25zOiBTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoKVxuXG4gIGNvbnN0cnVjdG9yKHByb3BzOiBMaXZlTGFtYmRhQXNwZWN0UHJvcHMgPSB7fSkge1xuICAgIHRoaXMucHJvcHMgPSBwcm9wc1xuICB9XG5cbiAgdmlzaXQobm9kZTogSUNvbnN0cnVjdCk6IHZvaWQge1xuICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBMYW1iZGEgRnVuY3Rpb24gdXNpbmcgZHVjay10eXBpbmcgaW5zdGVhZCBvZiBpbnN0YW5jZW9mXG4gICAgLy8gVGhpcyBhdm9pZHMgaXNzdWVzIHdpdGggbXVsdGlwbGUgY29waWVzIG9mIGF3cy1jZGstbGliIGJlaW5nIGxvYWRlZFxuICAgIGlmICghdGhpcy5pc0xhbWJkYUZ1bmN0aW9uKG5vZGUpKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBDYXN0IHRvIGxhbWJkYS5GdW5jdGlvbiBmb3IgdHlwZSBjaGVja2luZyAod2UndmUgdmVyaWZpZWQgaXQncyBhIExhbWJkYSlcbiAgICBjb25zdCBmbiA9IG5vZGUgYXMgdW5rbm93biBhcyBsYW1iZGEuRnVuY3Rpb25cblxuICAgIC8vIFNraXAgaWYgYWxyZWFkeSBwcm9jZXNzZWQgKGFzcGVjdHMgY2FuIHZpc2l0IG11bHRpcGxlIHRpbWVzKVxuICAgIGNvbnN0IG5vZGVJZCA9IG5vZGUubm9kZS5hZGRyXG4gICAgaWYgKHRoaXMucHJvY2Vzc2VkRnVuY3Rpb25zLmhhcyhub2RlSWQpKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBHZW5lcmF0ZSBhIHVuaXF1ZSBmdW5jdGlvbiBJRCBmcm9tIHRoZSBjb25zdHJ1Y3QgcGF0aFxuICAgIGNvbnN0IGZ1bmN0aW9uSWQgPSB0aGlzLmdlbmVyYXRlRnVuY3Rpb25JZChmbilcblxuICAgIC8vIENoZWNrIGV4Y2x1c2lvbiBsaXN0XG4gICAgaWYgKHRoaXMucHJvcHMuZXhjbHVkZUZ1bmN0aW9ucz8uaW5jbHVkZXMoZnVuY3Rpb25JZCkpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBbTGl2ZUxhbWJkYV0gU2tpcHBpbmcgZXhjbHVkZWQgZnVuY3Rpb246ICR7ZnVuY3Rpb25JZH1gKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgcGF0dGVybiBtYXRjaFxuICAgIGlmIChcbiAgICAgIHRoaXMucHJvcHMuZnVuY3Rpb25QYXR0ZXJuICYmXG4gICAgICAhdGhpcy5wcm9wcy5mdW5jdGlvblBhdHRlcm4udGVzdChmdW5jdGlvbklkKVxuICAgICkge1xuICAgICAgY29uc29sZS5sb2coYFtMaXZlTGFtYmRhXSBTa2lwcGluZyBub24tbWF0Y2hpbmcgZnVuY3Rpb246ICR7ZnVuY3Rpb25JZH1gKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc29sZS5sb2coYFtMaXZlTGFtYmRhXSBUcmFuc2Zvcm1pbmcgZnVuY3Rpb246ICR7ZnVuY3Rpb25JZH1gKVxuXG4gICAgY29uc3Qgc3RhY2tOYW1lID0gdGhpcy5wcm9wcy5zdGFja05hbWUgfHwgY2RrLlN0YWNrLm9mKGZuKS5zdGFja05hbWVcblxuICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYSBEb2NrZXJJbWFnZUZ1bmN0aW9uXG4gICAgY29uc3QgaXNEb2NrZXJGdW5jdGlvbiA9IGlzRG9ja2VySW1hZ2VGdW5jdGlvbihmbilcblxuICAgIGlmIChpc0RvY2tlckZ1bmN0aW9uKSB7XG4gICAgICBjb25zb2xlLmxvZyhgW0xpdmVMYW1iZGFdIERldGVjdGVkIERvY2tlckltYWdlRnVuY3Rpb246ICR7ZnVuY3Rpb25JZH1gKVxuICAgICAgdGhpcy50cmFuc2Zvcm1Eb2NrZXJGdW5jdGlvbihmbiwgc3RhY2tOYW1lLCBmdW5jdGlvbklkKVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBHZXQgaGFuZGxlciBwYXRocyBiZWZvcmUgd2UgbW9kaWZ5IGFueXRoaW5nXG4gICAgICBjb25zdCBoYW5kbGVyUGF0aHMgPSB0aGlzLmdldEhhbmRsZXJQYXRocyhmbilcblxuICAgICAgLy8gU2tpcCB1bnN1cHBvcnRlZCBmdW5jdGlvbnMgKG5vdCBOb2RlanNGdW5jdGlvbiBvciBEb2NrZXJJbWFnZUZ1bmN0aW9uKVxuICAgICAgaWYgKCFoYW5kbGVyUGF0aHMpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHsgb3JpZ2luYWxIYW5kbGVyLCBsb2NhbEhhbmRsZXIgfSA9IGhhbmRsZXJQYXRoc1xuXG4gICAgICAvLyBUcmFuc2Zvcm0gdGhlIGZ1bmN0aW9uXG4gICAgICB0aGlzLnRyYW5zZm9ybUZ1bmN0aW9uKFxuICAgICAgICBmbixcbiAgICAgICAgc3RhY2tOYW1lLFxuICAgICAgICBmdW5jdGlvbklkLFxuICAgICAgICBvcmlnaW5hbEhhbmRsZXIsXG4gICAgICAgIGxvY2FsSGFuZGxlcixcbiAgICAgIClcbiAgICB9XG5cbiAgICB0aGlzLnByb2Nlc3NlZEZ1bmN0aW9ucy5hZGQobm9kZUlkKVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGEgY29uc3RydWN0IGlzIGEgTGFtYmRhIEZ1bmN0aW9uIHVzaW5nIGR1Y2stdHlwaW5nLlxuICAgKiBUaGlzIGF2b2lkcyBpbnN0YW5jZW9mIGlzc3VlcyB3aGVuIG11bHRpcGxlIGNvcGllcyBvZiBhd3MtY2RrLWxpYiBhcmUgbG9hZGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBpc0xhbWJkYUZ1bmN0aW9uKG5vZGU6IElDb25zdHJ1Y3QpOiBib29sZWFuIHtcbiAgICAvLyBDaGVjayBieSBjb25zdHJ1Y3RvciBuYW1lIC0gaGFuZGxlcyBGdW5jdGlvbiwgRG9ja2VySW1hZ2VGdW5jdGlvbiwgTm9kZWpzRnVuY3Rpb24sIGV0Yy5cbiAgICAvLyBBbHNvIGhhbmRsZXMgb3VyIHBhdGNoZWQgdmVyc2lvbnMgbGlrZSBEb2NrZXJJbWFnZUZ1bmN0aW9uV2l0aENhcHR1cmVcbiAgICBjb25zdCBjb25zdHJ1Y3Rvck5hbWUgPSBub2RlLmNvbnN0cnVjdG9yLm5hbWVcbiAgICAvLyBDREsgYXBwZW5kcyBcIjJcIiB0byBjbGFzcyBuYW1lcyBpbiBzb21lIHZlcnNpb25zXG4gICAgY29uc3QgaXNGdW5jdGlvbiA9XG4gICAgICBjb25zdHJ1Y3Rvck5hbWUgPT09IFwiRnVuY3Rpb25cIiB8fFxuICAgICAgY29uc3RydWN0b3JOYW1lID09PSBcIkZ1bmN0aW9uMlwiIHx8XG4gICAgICBjb25zdHJ1Y3Rvck5hbWUuZW5kc1dpdGgoXCJGdW5jdGlvblwiKSB8fFxuICAgICAgY29uc3RydWN0b3JOYW1lLmVuZHNXaXRoKFwiRnVuY3Rpb24yXCIpIHx8XG4gICAgICBjb25zdHJ1Y3Rvck5hbWUuaW5jbHVkZXMoXCJGdW5jdGlvblwiKSAvLyBDYXRjaCBwYXRjaGVkIHZlcnNpb25zIGxpa2UgRG9ja2VySW1hZ2VGdW5jdGlvbldpdGhDYXB0dXJlXG5cbiAgICBpZiAoIWlzRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIC8vIEV4Y2x1ZGUgQ2ZuRnVuY3Rpb24gKHRoZSBMMSBjb25zdHJ1Y3QpXG4gICAgaWYgKGNvbnN0cnVjdG9yTmFtZSA9PT0gXCJDZm5GdW5jdGlvblwiKSB7XG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9XG5cbiAgICAvLyBWZXJpZnkgaXQgaGFzIGV4cGVjdGVkIExhbWJkYSBGdW5jdGlvbiBwcm9wZXJ0aWVzXG4gICAgY29uc3QgbWF5YmVGdW5jdGlvbiA9IG5vZGUgYXMgdW5rbm93biBhcyB7XG4gICAgICBmdW5jdGlvbk5hbWU/OiB1bmtub3duXG4gICAgICBmdW5jdGlvbkFybj86IHVua25vd25cbiAgICAgIG5vZGU/OiB7IGRlZmF1bHRDaGlsZD86IHVua25vd24gfVxuICAgIH1cblxuICAgIC8vIE11c3QgaGF2ZSBmdW5jdGlvbk5hbWUgYW5kIGZ1bmN0aW9uQXJuIChJRnVuY3Rpb24gaW50ZXJmYWNlKVxuICAgIGlmICghbWF5YmVGdW5jdGlvbi5mdW5jdGlvbk5hbWUgfHwgIW1heWJlRnVuY3Rpb24uZnVuY3Rpb25Bcm4pIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIC8vIE11c3QgaGF2ZSBhIGRlZmF1bHRDaGlsZCAodGhlIENmbkZ1bmN0aW9uKVxuICAgIGlmICghbWF5YmVGdW5jdGlvbi5ub2RlPy5kZWZhdWx0Q2hpbGQpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBwcml2YXRlIGdlbmVyYXRlRnVuY3Rpb25JZChmbjogbGFtYmRhLkZ1bmN0aW9uKTogc3RyaW5nIHtcbiAgICAvLyBVc2UgdGhlIGNvbnN0cnVjdCBJRCBhcyB0aGUgZnVuY3Rpb24gSURcbiAgICAvLyBGb3IgbmVzdGVkIGNvbnN0cnVjdHMsIGpvaW4gd2l0aCBkYXNoZXNcbiAgICBjb25zdCBwYXJ0cyA9IGZuLm5vZGUucGF0aC5zcGxpdChcIi9cIilcbiAgICAvLyBTa2lwIGZpcnN0IHBhcnQgKEFwcCkgYW5kIHRha2UgdGhlIHJlc3RcbiAgICBjb25zdCByZWxldmFudFBhcnRzID0gcGFydHMuc2xpY2UoMSlcbiAgICByZXR1cm4gcmVsZXZhbnRQYXJ0cy5qb2luKFwiLVwiKS5yZXBsYWNlKC9bXmEtekEtWjAtOS1dL2csIFwiLVwiKVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCBoYW5kbGVyIHBhdGhzIGZvciBhIGZ1bmN0aW9uLlxuICAgKiBSZXR1cm5zIGJvdGggdGhlIG9yaWdpbmFsIGhhbmRsZXIgKGFzIHNldCBpbiBDZm5GdW5jdGlvbikgYW5kIHRoZSBsb2NhbCBoYW5kbGVyIHBhdGguXG4gICAqIFJldHVybnMgbnVsbCBpZiB0aGUgZnVuY3Rpb24gaXMgbm90IHN1cHBvcnRlZCAoZS5nLiwgbm90IGEgTm9kZWpzRnVuY3Rpb24pLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRIYW5kbGVyUGF0aHMoZm46IGxhbWJkYS5GdW5jdGlvbik6IHtcbiAgICBvcmlnaW5hbEhhbmRsZXI6IHN0cmluZ1xuICAgIGxvY2FsSGFuZGxlcjogc3RyaW5nXG4gIH0gfCBudWxsIHtcbiAgICBjb25zdCBjZm5GdW5jdGlvbiA9IGZuLm5vZGUuZGVmYXVsdENoaWxkIGFzIGxhbWJkYS5DZm5GdW5jdGlvblxuICAgIGNvbnN0IG9yaWdpbmFsSGFuZGxlciA9IGNmbkZ1bmN0aW9uLmhhbmRsZXIgfHwgXCJpbmRleC5oYW5kbGVyXCJcbiAgICBjb25zdCBjb25zdHJ1Y3RJZCA9IGZuLm5vZGUuaWRcblxuICAgIC8vIENoZWNrIGlmIGNhcHR1cmVkIGJ5IHRoZSBOb2RlanNGdW5jdGlvbiBob29rXG4gICAgY29uc3QgZW50cnlQYXRoID0gZ2V0RW50cnlQYXRoKGZuKVxuICAgIGNvbnN0IGhhbmRsZXJOYW1lID0gZ2V0SGFuZGxlck5hbWUoZm4pIHx8IFwiaGFuZGxlclwiXG4gICAgaWYgKGVudHJ5UGF0aCkge1xuICAgICAgLy8gQ29udmVydCBlbnRyeSBwYXRoIHRvIGxvY2FsIGhhbmRsZXIgcGF0aFxuICAgICAgLy8gZS5nLiwgXCJmdW5jdGlvbnMvczMtd3JpdGVyL2hhbmRsZXIudHNcIiArIFwiaGFuZGxlclwiIC0+IFwiZnVuY3Rpb25zL3MzLXdyaXRlci9oYW5kbGVyLmhhbmRsZXJcIlxuICAgICAgY29uc3QgbG9jYWxIYW5kbGVyID0gYCR7ZW50cnlQYXRoLnJlcGxhY2UoRVhURU5TSU9OX1JFR0VYLCBcIlwiKX0uJHtoYW5kbGVyTmFtZX1gXG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgYFtMaXZlTGFtYmRhXSBVc2luZyBjYXB0dXJlZCBlbnRyeSBmb3IgJHtjb25zdHJ1Y3RJZH06ICR7bG9jYWxIYW5kbGVyfWAsXG4gICAgICApXG4gICAgICByZXR1cm4geyBvcmlnaW5hbEhhbmRsZXIsIGxvY2FsSGFuZGxlciB9XG4gICAgfVxuXG4gICAgLy8gTm8gaGFuZGxlciBwYXRoIGZvdW5kIC0gdGhpcyBmdW5jdGlvbiBpcyBub3Qgc3VwcG9ydGVkIChub3QgYSBOb2RlanNGdW5jdGlvbiBvciBEb2NrZXJJbWFnZUZ1bmN0aW9uKVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgYFtMaXZlTGFtYmRhXSBTa2lwcGluZyB1bnN1cHBvcnRlZCBmdW5jdGlvbiBcIiR7Y29uc3RydWN0SWR9XCI6IGAgK1xuICAgICAgICBgbm90IGEgTm9kZWpzRnVuY3Rpb24gb3IgRG9ja2VySW1hZ2VGdW5jdGlvbiAob3IgYm9vdHN0cmFwIGhvb2sgd2FzIG5vdCBpbnN0YWxsZWQgZWFybHkgZW5vdWdoKWAsXG4gICAgKVxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIGEgRG9ja2VySW1hZ2VGdW5jdGlvbiB0byB1c2UgdGhlIGJyaWRnZSBEb2NrZXIgaW1hZ2UuXG4gICAqIFN0b3JlcyB0aGUgbG9jYWwgRG9ja2VyIGNvbnRleHQgcGF0aCBpbiBhIHRhZyBmb3IgdGhlIGRhZW1vbiB0byBidWlsZC9ydW4gbG9jYWxseS5cbiAgICovXG4gIHByaXZhdGUgdHJhbnNmb3JtRG9ja2VyRnVuY3Rpb24oXG4gICAgZm46IGxhbWJkYS5GdW5jdGlvbixcbiAgICBfc3RhY2tOYW1lOiBzdHJpbmcsXG4gICAgZnVuY3Rpb25JZDogc3RyaW5nLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBjZm5GdW5jdGlvbiA9IGZuLm5vZGUuZGVmYXVsdENoaWxkIGFzIGxhbWJkYS5DZm5GdW5jdGlvblxuICAgIGNvbnN0IHN0YWNrID0gY2RrLlN0YWNrLm9mKGZuKVxuXG4gICAgLy8gR2V0IHRoZSBkb2NrZXIgY29udGV4dCBwYXRoIGZyb20gdGhlIGhvb2tcbiAgICBjb25zdCBkb2NrZXJDb250ZXh0UGF0aCA9IGdldERvY2tlckNvbnRleHRQYXRoKGZuKVxuICAgIGlmICghZG9ja2VyQ29udGV4dFBhdGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFtMaXZlTGFtYmRhXSBObyBkb2NrZXIgY29udGV4dCBwYXRoIGZvciBcIiR7ZnVuY3Rpb25JZH1cIi4gYCArXG4gICAgICAgICAgYFRoZSBib290c3RyYXAgaG9vayB3YXMgbm90IGluc3RhbGxlZCBlYXJseSBlbm91Z2guIGAgK1xuICAgICAgICAgIGBGaXg6IGltcG9ydCBcImNkay1sb2NhbC1sYW1iZGEvYm9vdHN0cmFwXCIgYmVmb3JlIGFueSBDREsgaW1wb3J0cyAoTm9kZS5qcyksIGAgK1xuICAgICAgICAgIGBvciBydW4gQnVuIHdpdGggXCJidW4gLS1wcmVsb2FkIGNkay1sb2NhbC1sYW1iZGEvYm9vdHN0cmFwXCIuYCxcbiAgICAgIClcbiAgICB9XG5cbiAgICAvLyBHZXQgU1NNIHBhcmFtZXRlcnNcbiAgICBjb25zdCBib290c3RyYXBRdWFsaWZpZXIgPVxuICAgICAgc3RhY2subm9kZS50cnlHZXRDb250ZXh0KFwiQGF3cy1jZGsvY29yZTpib290c3RyYXBRdWFsaWZpZXJcIikgfHxcbiAgICAgIFwiaG5iNjU5ZmRzXCJcbiAgICBjb25zdCBzc21CYXNlUGF0aCA9IGAke1NTTV9CQVNFX1BBVEh9LyR7Ym9vdHN0cmFwUXVhbGlmaWVyfWBcblxuICAgIGNvbnN0IGFwaUFybiA9IHNzbS5TdHJpbmdQYXJhbWV0ZXIudmFsdWVGb3JTdHJpbmdQYXJhbWV0ZXIoXG4gICAgICBzdGFjayxcbiAgICAgIGAke3NzbUJhc2VQYXRofS9hcGktYXJuYCxcbiAgICApXG5cbiAgICAvLyBEZXRlcm1pbmUgYXJjaGl0ZWN0dXJlIGFuZCBnZXQgYXBwcm9wcmlhdGUgYnJpZGdlIGltYWdlXG4gICAgY29uc3QgYXJjaGl0ZWN0dXJlID0gdGhpcy5nZXRBcmNoaXRlY3R1cmUoY2ZuRnVuY3Rpb24pXG4gICAgY29uc3QgYnJpZGdlSW1hZ2VQYXJhbSA9XG4gICAgICBhcmNoaXRlY3R1cmUgPT09IFwiYXJtNjRcIiA/IFwiYnJpZGdlLWltYWdlLWFybTY0XCIgOiBcImJyaWRnZS1pbWFnZS14ODZfNjRcIlxuXG4gICAgY29uc3QgYnJpZGdlSW1hZ2VVcmkgPSBzc20uU3RyaW5nUGFyYW1ldGVyLnZhbHVlRm9yU3RyaW5nUGFyYW1ldGVyKFxuICAgICAgc3RhY2ssXG4gICAgICBgJHtzc21CYXNlUGF0aH0vJHticmlkZ2VJbWFnZVBhcmFtfWAsXG4gICAgKVxuXG4gICAgLy8gQWRkIHRhZyB3aXRoIGRvY2tlciBjb250ZXh0IHBhdGggZm9yIGRhZW1vbiBkaXNjb3ZlcnlcbiAgICAvLyBUaGUgZGFlbW9uIHVzZXMgdGhpcyB0YWcgdG8gYnVpbGQgYW5kIHJ1biB0aGUgY29udGFpbmVyIGxvY2FsbHlcbiAgICBjZm5GdW5jdGlvbi50YWdzLnNldFRhZyhMSVZFX0xBTUJEQV9ET0NLRVJfVEFHLCBkb2NrZXJDb250ZXh0UGF0aClcblxuICAgIC8vIEdyYW50IHBlcm1pc3Npb25zIHRvIHB1Ymxpc2gvc3Vic2NyaWJlIHRvIEFwcFN5bmMgRXZlbnRzXG4gICAgZm4uYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcImFwcHN5bmM6RXZlbnRDb25uZWN0XCIsXG4gICAgICAgICAgXCJhcHBzeW5jOkV2ZW50UHVibGlzaFwiLFxuICAgICAgICAgIFwiYXBwc3luYzpFdmVudFN1YnNjcmliZVwiLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFthcGlBcm4sIGAke2FwaUFybn0vKmBdLFxuICAgICAgfSksXG4gICAgKVxuXG4gICAgLy8gR3JhbnQgcGVybWlzc2lvbnMgdG8gcmVhZCBTU00gcGFyYW1ldGVycyAoYnJpZGdlIG5lZWRzIEFwcFN5bmMgZW5kcG9pbnRzKVxuICAgIGZuLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbXCJzc206R2V0UGFyYW1ldGVyXCIsIFwic3NtOkdldFBhcmFtZXRlcnNcIl0sXG4gICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgIGBhcm46YXdzOnNzbToke3N0YWNrLnJlZ2lvbn06JHtzdGFjay5hY2NvdW50fTpwYXJhbWV0ZXIke3NzbUJhc2VQYXRofS8qYCxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgIClcblxuICAgIC8vIEluY3JlYXNlIHRpbWVvdXQgdG8gYWxsb3cgZm9yIGxvY2FsIGRlYnVnZ2luZ1xuICAgIGNmbkZ1bmN0aW9uLnRpbWVvdXQgPSAzMDAgLy8gNSBtaW51dGVzXG5cbiAgICAvLyBSZXBsYWNlIHRoZSBEb2NrZXIgaW1hZ2Ugd2l0aCB0aGUgYnJpZGdlIGltYWdlXG4gICAgY2ZuRnVuY3Rpb24uY29kZSA9IHtcbiAgICAgIGltYWdlVXJpOiBicmlkZ2VJbWFnZVVyaSxcbiAgICB9XG5cbiAgICBjb25zb2xlLmxvZyhcbiAgICAgIGBbTGl2ZUxhbWJkYV0gUmVwbGFjZWQgRG9ja2VyIGltYWdlIHdpdGggYnJpZGdlICgke2FyY2hpdGVjdHVyZX0pYCxcbiAgICApXG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lIHRoZSBhcmNoaXRlY3R1cmUgb2YgYSBMYW1iZGEgZnVuY3Rpb24uXG4gICAqIERlZmF1bHRzIHRvIHg4Nl82NCBpZiBub3QgZXhwbGljaXRseSBzZXQuXG4gICAqL1xuICBwcml2YXRlIGdldEFyY2hpdGVjdHVyZShjZm5GdW5jdGlvbjogbGFtYmRhLkNmbkZ1bmN0aW9uKTogXCJhcm02NFwiIHwgXCJ4ODZfNjRcIiB7XG4gICAgY29uc3QgYXJjaGl0ZWN0dXJlcyA9IGNmbkZ1bmN0aW9uLmFyY2hpdGVjdHVyZXMgYXMgc3RyaW5nW10gfCB1bmRlZmluZWRcbiAgICBpZiAoYXJjaGl0ZWN0dXJlcz8uaW5jbHVkZXMoXCJhcm02NFwiKSkge1xuICAgICAgcmV0dXJuIFwiYXJtNjRcIlxuICAgIH1cbiAgICByZXR1cm4gXCJ4ODZfNjRcIlxuICB9XG5cbiAgcHJpdmF0ZSB0cmFuc2Zvcm1GdW5jdGlvbihcbiAgICBmbjogbGFtYmRhLkZ1bmN0aW9uLFxuICAgIF9zdGFja05hbWU6IHN0cmluZyxcbiAgICBfZnVuY3Rpb25JZDogc3RyaW5nLFxuICAgIF9vcmlnaW5hbEhhbmRsZXI6IHN0cmluZyxcbiAgICBsb2NhbEhhbmRsZXI6IHN0cmluZyxcbiAgKTogdm9pZCB7XG4gICAgY29uc3QgY2ZuRnVuY3Rpb24gPSBmbi5ub2RlLmRlZmF1bHRDaGlsZCBhcyBsYW1iZGEuQ2ZuRnVuY3Rpb25cbiAgICBjb25zdCBzdGFjayA9IGNkay5TdGFjay5vZihmbilcblxuICAgIC8vIFJlYWQgdmFsdWVzIGZyb20gU1NNIHBhcmFtZXRlcnMgKGNyZWF0ZWQgYnkgYm9vdHN0cmFwIHN0YWNrKVxuICAgIC8vIFVzZSB0aGUgQ0RLIGJvb3RzdHJhcCBxdWFsaWZpZXIgZm9yIHByb3BlciBzY29waW5nXG4gICAgY29uc3QgYm9vdHN0cmFwUXVhbGlmaWVyID1cbiAgICAgIHN0YWNrLm5vZGUudHJ5R2V0Q29udGV4dChcIkBhd3MtY2RrL2NvcmU6Ym9vdHN0cmFwUXVhbGlmaWVyXCIpIHx8XG4gICAgICBcImhuYjY1OWZkc1wiXG4gICAgY29uc3Qgc3NtQmFzZVBhdGggPSBgJHtTU01fQkFTRV9QQVRIfS8ke2Jvb3RzdHJhcFF1YWxpZmllcn1gXG5cbiAgICBjb25zdCBhcGlBcm4gPSBzc20uU3RyaW5nUGFyYW1ldGVyLnZhbHVlRm9yU3RyaW5nUGFyYW1ldGVyKFxuICAgICAgc3RhY2ssXG4gICAgICBgJHtzc21CYXNlUGF0aH0vYXBpLWFybmAsXG4gICAgKVxuICAgIGNvbnN0IGJyaWRnZUJ1Y2tldCA9IHNzbS5TdHJpbmdQYXJhbWV0ZXIudmFsdWVGb3JTdHJpbmdQYXJhbWV0ZXIoXG4gICAgICBzdGFjayxcbiAgICAgIGAke3NzbUJhc2VQYXRofS9icmlkZ2UtYnVja2V0YCxcbiAgICApXG4gICAgY29uc3QgYnJpZGdlS2V5ID0gc3NtLlN0cmluZ1BhcmFtZXRlci52YWx1ZUZvclN0cmluZ1BhcmFtZXRlcihcbiAgICAgIHN0YWNrLFxuICAgICAgYCR7c3NtQmFzZVBhdGh9L2JyaWRnZS1rZXlgLFxuICAgIClcblxuICAgIC8vIEFkZCB0YWcgd2l0aCBsb2NhbCBoYW5kbGVyIHBhdGggZm9yIGRhZW1vbiBkaXNjb3ZlcnlcbiAgICAvLyBUaGUgZGFlbW9uIHF1ZXJpZXMgTGFtYmRhIEFQSSBmb3IgZnVuY3Rpb25zIHdpdGggdGhpcyB0YWdcbiAgICBjZm5GdW5jdGlvbi50YWdzLnNldFRhZyhMSVZFX0xBTUJEQV9UQUcsIGxvY2FsSGFuZGxlcilcblxuICAgIC8vIEdyYW50IHBlcm1pc3Npb25zIHRvIHB1Ymxpc2gvc3Vic2NyaWJlIHRvIEFwcFN5bmMgRXZlbnRzXG4gICAgZm4uYWRkVG9Sb2xlUG9saWN5KFxuICAgICAgbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IGlhbS5FZmZlY3QuQUxMT1csXG4gICAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAgICBcImFwcHN5bmM6RXZlbnRDb25uZWN0XCIsXG4gICAgICAgICAgXCJhcHBzeW5jOkV2ZW50UHVibGlzaFwiLFxuICAgICAgICAgIFwiYXBwc3luYzpFdmVudFN1YnNjcmliZVwiLFxuICAgICAgICBdLFxuICAgICAgICByZXNvdXJjZXM6IFthcGlBcm4sIGAke2FwaUFybn0vKmBdLFxuICAgICAgfSksXG4gICAgKVxuXG4gICAgLy8gR3JhbnQgcGVybWlzc2lvbnMgdG8gcmVhZCBTU00gcGFyYW1ldGVycyAoYnJpZGdlIG5lZWRzIEFwcFN5bmMgZW5kcG9pbnRzKVxuICAgIGZuLmFkZFRvUm9sZVBvbGljeShcbiAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbXCJzc206R2V0UGFyYW1ldGVyXCIsIFwic3NtOkdldFBhcmFtZXRlcnNcIl0sXG4gICAgICAgIHJlc291cmNlczogW1xuICAgICAgICAgIGBhcm46YXdzOnNzbToke3N0YWNrLnJlZ2lvbn06JHtzdGFjay5hY2NvdW50fTpwYXJhbWV0ZXIke3NzbUJhc2VQYXRofS8qYCxcbiAgICAgICAgXSxcbiAgICAgIH0pLFxuICAgIClcblxuICAgIC8vIEluY3JlYXNlIHRpbWVvdXQgdG8gYWxsb3cgZm9yIGxvY2FsIGRlYnVnZ2luZ1xuICAgIGNmbkZ1bmN0aW9uLnRpbWVvdXQgPSAzMDAgLy8gNSBtaW51dGVzXG5cbiAgICAvLyBSZXBsYWNlIHRoZSBjb2RlIHdpdGggYnJpZGdlIGhhbmRsZXIgZnJvbSBib290c3RyYXAgc3RhY2sncyBTMyBidWNrZXRcbiAgICBjZm5GdW5jdGlvbi5jb2RlID0ge1xuICAgICAgczNCdWNrZXQ6IGJyaWRnZUJ1Y2tldCxcbiAgICAgIHMzS2V5OiBicmlkZ2VLZXksXG4gICAgfVxuICAgIGNmbkZ1bmN0aW9uLmhhbmRsZXIgPSBcImluZGV4LmhhbmRsZXJcIlxuICB9XG59XG5cbi8qKlxuICogSGVscGVyIGZ1bmN0aW9uIHRvIGNoZWNrIGlmIGxpdmUgbW9kZSBpcyBlbmFibGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xpdmVNb2RlRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgcmV0dXJuIHByb2Nlc3MuZW52LkNES19MSVZFID09PSBcInRydWVcIlxufVxuXG4vKipcbiAqIEFwcGx5IGxpdmUgbGFtYmRhIGFzcGVjdCB0byBhIENESyBhcHAgb3Igc3RhY2sgaWYgbGl2ZSBtb2RlIGlzIGVuYWJsZWQuXG4gKlxuICogQHBhcmFtIHNjb3BlIFRoZSBDREsgYXBwIG9yIHN0YWNrIHRvIGFwcGx5IHRoZSBhc3BlY3QgdG9cbiAqIEBwYXJhbSBwcm9wcyBPcHRpb25hbCBjb25maWd1cmF0aW9uIGZvciB0aGUgbGl2ZSBsYW1iZGEgYXNwZWN0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhcHBseUxpdmVMYW1iZGFBc3BlY3QoXG4gIHNjb3BlOiBJQ29uc3RydWN0LFxuICBwcm9wczogTGl2ZUxhbWJkYUFzcGVjdFByb3BzID0ge30sXG4pOiB2b2lkIHtcbiAgaWYgKCFpc0xpdmVNb2RlRW5hYmxlZCgpKSB7XG4gICAgY29uc29sZS5sb2coXG4gICAgICBcIltMaXZlTGFtYmRhXSBMaXZlIG1vZGUgbm90IGVuYWJsZWQgKHNldCBDREtfTElWRT10cnVlIHRvIGVuYWJsZSlcIixcbiAgICApXG4gICAgcmV0dXJuXG4gIH1cblxuICBjb25zb2xlLmxvZyhcIltMaXZlTGFtYmRhXSBMaXZlIG1vZGUgZW5hYmxlZCAtIHRyYW5zZm9ybWluZyBMYW1iZGEgZnVuY3Rpb25zXCIpXG4gIGNkay5Bc3BlY3RzLm9mKHNjb3BlKS5hZGQobmV3IExpdmVMYW1iZGFBc3BlY3QocHJvcHMpKVxufVxuIl19
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootstrap file that installs hooks for NodejsFunction and DockerImageFunction
|
|
3
|
+
* BEFORE any CDK imports.
|
|
4
|
+
*
|
|
5
|
+
* This must be imported as the very first thing in the CDK app entry point,
|
|
6
|
+
* before any other imports.
|
|
7
|
+
*
|
|
8
|
+
* Runtime support:
|
|
9
|
+
* - Node.js: patches Module._load to intercept module loading
|
|
10
|
+
* - Bun: directly imports and patches modules (Module._load not supported)
|
|
11
|
+
*
|
|
12
|
+
* Hooks installed:
|
|
13
|
+
* - NodejsFunction: captures entry and handler props
|
|
14
|
+
* - DockerImageFunction: captures docker context path from code prop
|
|
15
|
+
* - DockerImageCode.fromImageAsset: captures the directory path
|
|
16
|
+
*/
|
|
17
|
+
export {};
|