UNPKG

36 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.StepFunctionsIntegration = void 0;
5const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const fs = require("fs");
8const path = require("path");
9const iam = require("@aws-cdk/aws-iam");
10const sfn = require("@aws-cdk/aws-stepfunctions");
11const core_1 = require("@aws-cdk/core");
12const integration_1 = require("../integration");
13const model_1 = require("../model");
14const aws_1 = require("./aws");
15/**
16 * Options to integrate with various StepFunction API
17 */
18class StepFunctionsIntegration {
19 /**
20 * Integrates a Synchronous Express State Machine from AWS Step Functions to an API Gateway method.
21 *
22 * @example
23 *
24 * const stateMachine = new stepfunctions.StateMachine(this, 'MyStateMachine', {
25 * stateMachineType: stepfunctions.StateMachineType.EXPRESS,
26 * definition: stepfunctions.Chain.start(new stepfunctions.Pass(this, 'Pass')),
27 * });
28 *
29 * const api = new apigateway.RestApi(this, 'Api', {
30 * restApiName: 'MyApi',
31 * });
32 * api.root.addMethod('GET', apigateway.StepFunctionsIntegration.startExecution(stateMachine));
33 */
34 static startExecution(stateMachine, options) {
35 try {
36 jsiiDeprecationWarnings._aws_cdk_aws_apigateway_StepFunctionsExecutionIntegrationOptions(options);
37 }
38 catch (error) {
39 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
40 Error.captureStackTrace(error, this.startExecution);
41 }
42 throw error;
43 }
44 return new StepFunctionsExecutionIntegration(stateMachine, options);
45 }
46}
47exports.StepFunctionsIntegration = StepFunctionsIntegration;
48_a = JSII_RTTI_SYMBOL_1;
49StepFunctionsIntegration[_a] = { fqn: "@aws-cdk/aws-apigateway.StepFunctionsIntegration", version: "1.156.0" };
50class StepFunctionsExecutionIntegration extends aws_1.AwsIntegration {
51 constructor(stateMachine, options = {}) {
52 super({
53 service: 'states',
54 action: 'StartSyncExecution',
55 options: {
56 credentialsRole: options.credentialsRole,
57 integrationResponses: integrationResponse(),
58 passthroughBehavior: integration_1.PassthroughBehavior.NEVER,
59 requestTemplates: requestTemplates(stateMachine, options),
60 ...options,
61 },
62 });
63 this.stateMachine = stateMachine;
64 }
65 bind(method) {
66 var _b, _c;
67 const bindResult = super.bind(method);
68 const credentialsRole = (_c = (_b = bindResult.options) === null || _b === void 0 ? void 0 : _b.credentialsRole) !== null && _c !== void 0 ? _c : new iam.Role(method, 'StartSyncExecutionRole', {
69 assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
70 });
71 this.stateMachine.grantStartSyncExecution(credentialsRole);
72 let stateMachineName;
73 if (this.stateMachine instanceof sfn.StateMachine) {
74 const stateMachineType = this.stateMachine.stateMachineType;
75 if (stateMachineType !== sfn.StateMachineType.EXPRESS) {
76 throw new Error('State Machine must be of type "EXPRESS". Please use StateMachineType.EXPRESS as the stateMachineType');
77 }
78 //if not imported, extract the name from the CFN layer to reach the
79 //literal value if it is given (rather than a token)
80 stateMachineName = this.stateMachine.node.defaultChild.stateMachineName;
81 }
82 else {
83 //imported state machine
84 stateMachineName = `StateMachine-${this.stateMachine.stack.node.addr}`;
85 }
86 let deploymentToken;
87 if (stateMachineName !== undefined && !core_1.Token.isUnresolved(stateMachineName)) {
88 deploymentToken = JSON.stringify({ stateMachineName });
89 }
90 for (const methodResponse of METHOD_RESPONSES) {
91 method.addMethodResponse(methodResponse);
92 }
93 return {
94 ...bindResult,
95 options: {
96 ...bindResult.options,
97 credentialsRole,
98 },
99 deploymentToken,
100 };
101 }
102}
103/**
104 * Defines the integration response that passes the result on success,
105 * or the error on failure, from the synchronous execution to the caller.
106 *
107 * @returns integrationResponse mapping
108 */
109function integrationResponse() {
110 const errorResponse = [
111 {
112 /**
113 * Specifies the regular expression (regex) pattern used to choose
114 * an integration response based on the response from the back end.
115 * In this case it will match all '4XX' HTTP Errors
116 */
117 selectionPattern: '4\\d{2}',
118 statusCode: '400',
119 responseTemplates: {
120 'application/json': `{
121 "error": "Bad request!"
122 }`,
123 },
124 },
125 {
126 /**
127 * Match all '5XX' HTTP Errors
128 */
129 selectionPattern: '5\\d{2}',
130 statusCode: '500',
131 responseTemplates: {
132 'application/json': '"error": $input.path(\'$.error\')',
133 },
134 },
135 ];
136 const integResponse = [
137 {
138 statusCode: '200',
139 responseTemplates: {
140 /* eslint-disable */
141 'application/json': [
142 '#set($inputRoot = $input.path(\'$\'))',
143 '#if($input.path(\'$.status\').toString().equals("FAILED"))',
144 '#set($context.responseOverride.status = 500)',
145 '{',
146 '"error": "$input.path(\'$.error\')",',
147 '"cause": "$input.path(\'$.cause\')"',
148 '}',
149 '#else',
150 '$input.path(\'$.output\')',
151 '#end',
152 ].join('\n'),
153 },
154 },
155 ...errorResponse,
156 ];
157 return integResponse;
158}
159/**
160 * Defines the request template that will be used for the integration
161 * @param stateMachine
162 * @param options
163 * @returns requestTemplate
164 */
165function requestTemplates(stateMachine, options) {
166 const templateStr = templateString(stateMachine, options);
167 const requestTemplate = {
168 'application/json': templateStr,
169 };
170 return requestTemplate;
171}
172/**
173 * Reads the VTL template and returns the template string to be used
174 * for the request template.
175 *
176 * @param stateMachine
177 * @param includeRequestContext
178 * @param options
179 * @reutrns templateString
180 */
181function templateString(stateMachine, options) {
182 var _b, _c, _d, _e;
183 let templateStr;
184 let requestContextStr = '';
185 const includeHeader = (_b = options.headers) !== null && _b !== void 0 ? _b : false;
186 const includeQueryString = (_c = options.querystring) !== null && _c !== void 0 ? _c : true;
187 const includePath = (_d = options.path) !== null && _d !== void 0 ? _d : true;
188 const includeAuthorizer = (_e = options.authorizer) !== null && _e !== void 0 ? _e : false;
189 if (options.requestContext && Object.keys(options.requestContext).length > 0) {
190 requestContextStr = requestContext(options.requestContext);
191 }
192 templateStr = fs.readFileSync(path.join(__dirname, 'stepfunctions.vtl'), { encoding: 'utf-8' });
193 templateStr = templateStr.replace('%STATEMACHINE%', stateMachine.stateMachineArn);
194 templateStr = templateStr.replace('%INCLUDE_HEADERS%', String(includeHeader));
195 templateStr = templateStr.replace('%INCLUDE_QUERYSTRING%', String(includeQueryString));
196 templateStr = templateStr.replace('%INCLUDE_PATH%', String(includePath));
197 templateStr = templateStr.replace('%INCLUDE_AUTHORIZER%', String(includeAuthorizer));
198 templateStr = templateStr.replace('%REQUESTCONTEXT%', requestContextStr);
199 return templateStr;
200}
201function requestContext(requestContextObj) {
202 const context = {
203 accountId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.accountId) ? '$context.identity.accountId' : undefined,
204 apiId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.apiId) ? '$context.apiId' : undefined,
205 apiKey: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.apiKey) ? '$context.identity.apiKey' : undefined,
206 authorizerPrincipalId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.authorizerPrincipalId) ? '$context.authorizer.principalId' : undefined,
207 caller: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.caller) ? '$context.identity.caller' : undefined,
208 cognitoAuthenticationProvider: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.cognitoAuthenticationProvider) ? '$context.identity.cognitoAuthenticationProvider' : undefined,
209 cognitoAuthenticationType: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.cognitoAuthenticationType) ? '$context.identity.cognitoAuthenticationType' : undefined,
210 cognitoIdentityId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.cognitoIdentityId) ? '$context.identity.cognitoIdentityId' : undefined,
211 cognitoIdentityPoolId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.cognitoIdentityPoolId) ? '$context.identity.cognitoIdentityPoolId' : undefined,
212 httpMethod: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.httpMethod) ? '$context.httpMethod' : undefined,
213 stage: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.stage) ? '$context.stage' : undefined,
214 sourceIp: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.sourceIp) ? '$context.identity.sourceIp' : undefined,
215 user: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.user) ? '$context.identity.user' : undefined,
216 userAgent: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.userAgent) ? '$context.identity.userAgent' : undefined,
217 userArn: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.userArn) ? '$context.identity.userArn' : undefined,
218 requestId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.requestId) ? '$context.requestId' : undefined,
219 resourceId: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.resourceId) ? '$context.resourceId' : undefined,
220 resourcePath: (requestContextObj === null || requestContextObj === void 0 ? void 0 : requestContextObj.resourcePath) ? '$context.resourcePath' : undefined,
221 };
222 const contextAsString = JSON.stringify(context);
223 // The VTL Template conflicts with double-quotes (") for strings.
224 // Before sending to the template, we replace double-quotes (") with @@ and replace it back inside the .vtl file
225 const doublequotes = '"';
226 const replaceWith = '@@';
227 return contextAsString.split(doublequotes).join(replaceWith);
228}
229/**
230 * Method response model for each HTTP code response
231 */
232const METHOD_RESPONSES = [
233 {
234 statusCode: '200',
235 responseModels: {
236 'application/json': model_1.Model.EMPTY_MODEL,
237 },
238 },
239 {
240 statusCode: '400',
241 responseModels: {
242 'application/json': model_1.Model.ERROR_MODEL,
243 },
244 },
245 {
246 statusCode: '500',
247 responseModels: {
248 'application/json': model_1.Model.ERROR_MODEL,
249 },
250 },
251];
252//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcGZ1bmN0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInN0ZXBmdW5jdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qix3Q0FBd0M7QUFDeEMsa0RBQWtEO0FBQ2xELHdDQUFzQztBQUV0QyxnREFBNEY7QUFFNUYsb0NBQWlDO0FBQ2pDLCtCQUF1QztBQThFdkM7O0dBRUc7QUFDSCxNQUFhLHdCQUF3QjtJQUNuQzs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNJLE1BQU0sQ0FBQyxjQUFjLENBQUMsWUFBK0IsRUFBRSxPQUFrRDs7Ozs7Ozs7OztRQUM5RyxPQUFPLElBQUksaUNBQWlDLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0tBQ3JFOztBQWxCSCw0REFtQkM7OztBQUVELE1BQU0saUNBQWtDLFNBQVEsb0JBQWM7SUFFNUQsWUFBWSxZQUErQixFQUFFLFVBQW9ELEVBQUU7UUFDakcsS0FBSyxDQUFDO1lBQ0osT0FBTyxFQUFFLFFBQVE7WUFDakIsTUFBTSxFQUFFLG9CQUFvQjtZQUM1QixPQUFPLEVBQUU7Z0JBQ1AsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlO2dCQUN4QyxvQkFBb0IsRUFBRSxtQkFBbUIsRUFBRTtnQkFDM0MsbUJBQW1CLEVBQUUsaUNBQW1CLENBQUMsS0FBSztnQkFDOUMsZ0JBQWdCLEVBQUUsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQztnQkFDekQsR0FBRyxPQUFPO2FBQ1g7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQztLQUNsQztJQUVNLElBQUksQ0FBQyxNQUFjOztRQUN4QixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRXRDLE1BQU0sZUFBZSxlQUFHLFVBQVUsQ0FBQyxPQUFPLDBDQUFFLGVBQWUsbUNBQUksSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSx3QkFBd0IsRUFBRTtZQUM1RyxTQUFTLEVBQUUsSUFBSSxHQUFHLENBQUMsZ0JBQWdCLENBQUMsMEJBQTBCLENBQUM7U0FDaEUsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksQ0FBQyx1QkFBdUIsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUUzRCxJQUFJLGdCQUFnQixDQUFDO1FBRXJCLElBQUksSUFBSSxDQUFDLFlBQVksWUFBWSxHQUFHLENBQUMsWUFBWSxFQUFFO1lBQ2pELE1BQU0sZ0JBQWdCLEdBQUksSUFBSSxDQUFDLFlBQWlDLENBQUMsZ0JBQWdCLENBQUM7WUFDbEYsSUFBSSxnQkFBZ0IsS0FBSyxHQUFHLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFO2dCQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLHNHQUFzRyxDQUFDLENBQUM7YUFDekg7WUFFRCxtRUFBbUU7WUFDbkUsb0RBQW9EO1lBQ3BELGdCQUFnQixHQUFJLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQW9DLENBQUMsZ0JBQWdCLENBQUM7U0FDbEc7YUFBTTtZQUNMLHdCQUF3QjtZQUN4QixnQkFBZ0IsR0FBRyxnQkFBZ0IsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1NBQ3hFO1FBRUQsSUFBSSxlQUFlLENBQUM7UUFFcEIsSUFBSSxnQkFBZ0IsS0FBSyxTQUFTLElBQUksQ0FBQyxZQUFLLENBQUMsWUFBWSxDQUFDLGdCQUFnQixDQUFDLEVBQUU7WUFDM0UsZUFBZSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7U0FDeEQ7UUFFRCxLQUFLLE1BQU0sY0FBYyxJQUFJLGdCQUFnQixFQUFFO1lBQzdDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxjQUFjLENBQUMsQ0FBQztTQUMxQztRQUVELE9BQU87WUFDTCxHQUFHLFVBQVU7WUFDYixPQUFPLEVBQUU7Z0JBQ1AsR0FBRyxVQUFVLENBQUMsT0FBTztnQkFDckIsZUFBZTthQUNoQjtZQUNELGVBQWU7U0FDaEIsQ0FBQztLQUNIO0NBQ0Y7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsbUJBQW1CO0lBQzFCLE1BQU0sYUFBYSxHQUFHO1FBQ3BCO1lBQ0U7Ozs7ZUFJRztZQUNILGdCQUFnQixFQUFFLFNBQVM7WUFDM0IsVUFBVSxFQUFFLEtBQUs7WUFDakIsaUJBQWlCLEVBQUU7Z0JBQ2pCLGtCQUFrQixFQUFFOztZQUVoQjthQUNMO1NBQ0Y7UUFDRDtZQUNFOztlQUVHO1lBQ0gsZ0JBQWdCLEVBQUUsU0FBUztZQUMzQixVQUFVLEVBQUUsS0FBSztZQUNqQixpQkFBaUIsRUFBRTtnQkFDakIsa0JBQWtCLEVBQUUsbUNBQW1DO2FBQ3hEO1NBQ0Y7S0FDRixDQUFDO0lBRUYsTUFBTSxhQUFhLEdBQUc7UUFDcEI7WUFDRSxVQUFVLEVBQUUsS0FBSztZQUNqQixpQkFBaUIsRUFBRTtnQkFDakIsb0JBQW9CO2dCQUNwQixrQkFBa0IsRUFBRTtvQkFDbEIsdUNBQXVDO29CQUN2Qyw0REFBNEQ7b0JBQzFELDhDQUE4QztvQkFDOUMsR0FBRztvQkFDRCxzQ0FBc0M7b0JBQ3RDLHFDQUFxQztvQkFDdkMsR0FBRztvQkFDTCxPQUFPO29CQUNMLDJCQUEyQjtvQkFDN0IsTUFBTTtpQkFFUCxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7YUFDYjtTQUNGO1FBQ0QsR0FBRyxhQUFhO0tBQ2pCLENBQUM7SUFFRixPQUFPLGFBQWEsQ0FBQztBQUN2QixDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxTQUFTLGdCQUFnQixDQUFDLFlBQStCLEVBQUUsT0FBaUQ7SUFDMUcsTUFBTSxXQUFXLEdBQUcsY0FBYyxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUUxRCxNQUFNLGVBQWUsR0FDbkI7UUFDRSxrQkFBa0IsRUFBRSxXQUFXO0tBQ2hDLENBQUM7SUFFSixPQUFPLGVBQWUsQ0FBQztBQUN6QixDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxTQUFTLGNBQWMsQ0FDckIsWUFBK0IsRUFDL0IsT0FBaUQ7O0lBQ2pELElBQUksV0FBbUIsQ0FBQztJQUV4QixJQUFJLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztJQUUzQixNQUFNLGFBQWEsU0FBRyxPQUFPLENBQUMsT0FBTyxtQ0FBRyxLQUFLLENBQUM7SUFDOUMsTUFBTSxrQkFBa0IsU0FBRyxPQUFPLENBQUMsV0FBVyxtQ0FBRyxJQUFJLENBQUM7SUFDdEQsTUFBTSxXQUFXLFNBQUcsT0FBTyxDQUFDLElBQUksbUNBQUcsSUFBSSxDQUFDO0lBQ3hDLE1BQU0saUJBQWlCLFNBQUcsT0FBTyxDQUFDLFVBQVUsbUNBQUksS0FBSyxDQUFDO0lBRXRELElBQUksT0FBTyxDQUFDLGNBQWMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1FBQzVFLGlCQUFpQixHQUFHLGNBQWMsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7S0FDNUQ7SUFFRCxXQUFXLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxtQkFBbUIsQ0FBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDaEcsV0FBVyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ2xGLFdBQVcsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0lBQzlFLFdBQVcsR0FBRyxXQUFXLENBQUMsT0FBTyxDQUFDLHVCQUF1QixFQUFFLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7SUFDdkYsV0FBVyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDekUsV0FBVyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsc0JBQXNCLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQztJQUNyRixXQUFXLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO0lBRXpFLE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxpQkFBNkM7SUFDbkUsTUFBTSxPQUFPLEdBQUc7UUFDZCxTQUFTLEVBQUUsQ0FBQSxpQkFBaUIsYUFBakIsaUJBQWlCLHVCQUFqQixpQkFBaUIsQ0FBRSxTQUFTLEVBQUEsQ0FBQyxDQUFDLDZCQUE2QixDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQ2pGLEtBQUssRUFBRSxDQUFBLGlCQUFpQixhQUFqQixpQkFBaUIsdUJBQWpCLGlCQUFpQixDQUFFLEtBQUssRUFBQSxDQUFDLENBQUMsZ0JBQWdCLENBQUEsQ0FBQyxDQUFDLFNBQVM7UUFDNUQsTUFBTSxFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsTUFBTSxFQUFBLENBQUMsQ0FBQywwQkFBMEIsQ0FBQSxDQUFDLENBQUMsU0FBUztRQUN4RSxxQkFBcUIsRUFBRSxDQUFBLGlCQUFpQixhQUFqQixpQkFBaUIsdUJBQWpCLGlCQUFpQixDQUFFLHFCQUFxQixFQUFBLENBQUMsQ0FBQyxpQ0FBaUMsQ0FBQSxDQUFDLENBQUMsU0FBUztRQUM3RyxNQUFNLEVBQUUsQ0FBQSxpQkFBaUIsYUFBakIsaUJBQWlCLHVCQUFqQixpQkFBaUIsQ0FBRSxNQUFNLEVBQUEsQ0FBQyxDQUFDLDBCQUEwQixDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQ3hFLDZCQUE2QixFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsNkJBQTZCLEVBQUEsQ0FBQyxDQUFDLGlEQUFpRCxDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQzdJLHlCQUF5QixFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUseUJBQXlCLEVBQUEsQ0FBQyxDQUFDLDZDQUE2QyxDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQ2pJLGlCQUFpQixFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsaUJBQWlCLEVBQUEsQ0FBQyxDQUFDLHFDQUFxQyxDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQ3pHLHFCQUFxQixFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUscUJBQXFCLEVBQUEsQ0FBQyxDQUFDLHlDQUF5QyxDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQ3JILFVBQVUsRUFBRSxDQUFBLGlCQUFpQixhQUFqQixpQkFBaUIsdUJBQWpCLGlCQUFpQixDQUFFLFVBQVUsRUFBQSxDQUFDLENBQUMscUJBQXFCLENBQUEsQ0FBQyxDQUFDLFNBQVM7UUFDM0UsS0FBSyxFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsS0FBSyxFQUFBLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQSxDQUFDLENBQUMsU0FBUztRQUM1RCxRQUFRLEVBQUUsQ0FBQSxpQkFBaUIsYUFBakIsaUJBQWlCLHVCQUFqQixpQkFBaUIsQ0FBRSxRQUFRLEVBQUEsQ0FBQyxDQUFDLDRCQUE0QixDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQzlFLElBQUksRUFBRSxDQUFBLGlCQUFpQixhQUFqQixpQkFBaUIsdUJBQWpCLGlCQUFpQixDQUFFLElBQUksRUFBQSxDQUFDLENBQUMsd0JBQXdCLENBQUEsQ0FBQyxDQUFDLFNBQVM7UUFDbEUsU0FBUyxFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsU0FBUyxFQUFBLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQSxDQUFDLENBQUMsU0FBUztRQUNqRixPQUFPLEVBQUUsQ0FBQSxpQkFBaUIsYUFBakIsaUJBQWlCLHVCQUFqQixpQkFBaUIsQ0FBRSxPQUFPLEVBQUEsQ0FBQyxDQUFDLDJCQUEyQixDQUFBLENBQUMsQ0FBQyxTQUFTO1FBQzNFLFNBQVMsRUFBRSxDQUFBLGlCQUFpQixhQUFqQixpQkFBaUIsdUJBQWpCLGlCQUFpQixDQUFFLFNBQVMsRUFBQSxDQUFDLENBQUMsb0JBQW9CLENBQUEsQ0FBQyxDQUFDLFNBQVM7UUFDeEUsVUFBVSxFQUFFLENBQUEsaUJBQWlCLGFBQWpCLGlCQUFpQix1QkFBakIsaUJBQWlCLENBQUUsVUFBVSxFQUFBLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQSxDQUFDLENBQUMsU0FBUztRQUMzRSxZQUFZLEVBQUUsQ0FBQSxpQkFBaUIsYUFBakIsaUJBQWlCLHVCQUFqQixpQkFBaUIsQ0FBRSxZQUFZLEVBQUEsQ0FBQyxDQUFDLHVCQUF1QixDQUFBLENBQUMsQ0FBQyxTQUFTO0tBQ2xGLENBQUM7SUFFRixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRWhELGlFQUFpRTtJQUNqRSxnSEFBZ0g7SUFDaEgsTUFBTSxZQUFZLEdBQUcsR0FBRyxDQUFDO0lBQ3pCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQztJQUN6QixPQUFPLGVBQWUsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQy9ELENBQUM7QUFFRDs7R0FFRztBQUNILE1BQU0sZ0JBQWdCLEdBQUc7SUFDdkI7UUFDRSxVQUFVLEVBQUUsS0FBSztRQUNqQixjQUFjLEVBQUU7WUFDZCxrQkFBa0IsRUFBRSxhQUFLLENBQUMsV0FBVztTQUN0QztLQUNGO0lBQ0Q7UUFDRSxVQUFVLEVBQUUsS0FBSztRQUNqQixjQUFjLEVBQUU7WUFDZCxrQkFBa0IsRUFBRSxhQUFLLENBQUMsV0FBVztTQUN0QztLQUNGO0lBQ0Q7UUFDRSxVQUFVLEVBQUUsS0FBSztRQUNqQixjQUFjLEVBQUU7WUFDZCxrQkFBa0IsRUFBRSxhQUFLLENBQUMsV0FBVztTQUN0QztLQUNGO0NBQ0YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBzZm4gZnJvbSAnQGF3cy1jZGsvYXdzLXN0ZXBmdW5jdGlvbnMnO1xuaW1wb3J0IHsgVG9rZW4gfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IFJlcXVlc3RDb250ZXh0IH0gZnJvbSAnLic7XG5pbXBvcnQgeyBJbnRlZ3JhdGlvbkNvbmZpZywgSW50ZWdyYXRpb25PcHRpb25zLCBQYXNzdGhyb3VnaEJlaGF2aW9yIH0gZnJvbSAnLi4vaW50ZWdyYXRpb24nO1xuaW1wb3J0IHsgTWV0aG9kIH0gZnJvbSAnLi4vbWV0aG9kJztcbmltcG9ydCB7IE1vZGVsIH0gZnJvbSAnLi4vbW9kZWwnO1xuaW1wb3J0IHsgQXdzSW50ZWdyYXRpb24gfSBmcm9tICcuL2F3cyc7XG4vKipcbiAqIE9wdGlvbnMgd2hlbiBjb25maWd1cmluZyBTdGVwIEZ1bmN0aW9ucyBzeW5jaHJvbm91cyBpbnRlZ3JhdGlvbiB3aXRoIFJlc3QgQVBJXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RlcEZ1bmN0aW9uc0V4ZWN1dGlvbkludGVncmF0aW9uT3B0aW9ucyBleHRlbmRzIEludGVncmF0aW9uT3B0aW9ucyB7XG5cbiAgLyoqXG4gICAqIFdoaWNoIGRldGFpbHMgb2YgdGhlIGluY29taW5nIHJlcXVlc3QgbXVzdCBiZSBwYXNzZWQgb250byB0aGUgdW5kZXJseWluZyBzdGF0ZSBtYWNoaW5lLFxuICAgKiBzdWNoIGFzLCBhY2NvdW50IGlkLCB1c2VyIGlkZW50aXR5LCByZXF1ZXN0IGlkLCBldGMuIFRoZSBleGVjdXRpb24gaW5wdXQgd2lsbCBpbmNsdWRlIGEgbmV3IGtleSBgcmVxdWVzdENvbnRleHRgOlxuICAgKlxuICAgKiB7XG4gICAqICAgXCJib2R5XCI6IHt9LFxuICAgKiAgIFwicmVxdWVzdENvbnRleHRcIjoge1xuICAgKiAgICAgICBcImtleVwiOiBcInZhbHVlXCJcbiAgICogICB9XG4gICAqIH1cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhbGwgcGFyYW1ldGVycyB3aXRoaW4gcmVxdWVzdCBjb250ZXh0IHdpbGwgYmUgc2V0IGFzIGZhbHNlXG4gICAqL1xuICByZWFkb25seSByZXF1ZXN0Q29udGV4dD86IFJlcXVlc3RDb250ZXh0O1xuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBxdWVyeXN0cmluZyBpcyB0byBiZSBpbmNsdWRlZCBpbnNpZGUgdGhlIGV4ZWN1dGlvbiBpbnB1dC4gVGhlIGV4ZWN1dGlvbiBpbnB1dCB3aWxsIGluY2x1ZGUgYSBuZXcga2V5IGBxdWVyeVN0cmluZ2A6XG4gICAqXG4gICAqIHtcbiAgICogICBcImJvZHlcIjoge30sXG4gICAqICAgXCJxdWVyeXN0cmluZ1wiOiB7XG4gICAqICAgICBcImtleVwiOiBcInZhbHVlXCJcbiAgICogICB9XG4gICAqIH1cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgcXVlcnlzdHJpbmc/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBwYXRoIGlzIHRvIGJlIGluY2x1ZGVkIGluc2lkZSB0aGUgZXhlY3V0aW9uIGlucHV0LiBUaGUgZXhlY3V0aW9uIGlucHV0IHdpbGwgaW5jbHVkZSBhIG5ldyBrZXkgYHBhdGhgOlxuICAgKlxuICAgKiB7XG4gICAqICAgXCJib2R5XCI6IHt9LFxuICAgKiAgIFwicGF0aFwiOiB7XG4gICAqICAgICBcInJlc291cmNlTmFtZVwiOiBcInJlc291cmNlVmFsdWVcIlxuICAgKiAgIH1cbiAgICogfVxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBwYXRoPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ2hlY2sgaWYgaGVhZGVyIGlzIHRvIGJlIGluY2x1ZGVkIGluc2lkZSB0aGUgZXhlY3V0aW9uIGlucHV0LiBUaGUgZXhlY3V0aW9uIGlucHV0IHdpbGwgaW5jbHVkZSBhIG5ldyBrZXkgYGhlYWRlcnNgOlxuICAgKlxuICAgKiB7XG4gICAqICAgXCJib2R5XCI6IHt9LFxuICAgKiAgIFwiaGVhZGVyc1wiOiB7XG4gICAqICAgICAgXCJoZWFkZXIxXCI6IFwidmFsdWVcIixcbiAgICogICAgICBcImhlYWRlcjJcIjogXCJ2YWx1ZVwiXG4gICAqICAgfVxuICAgKiB9XG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBoZWFkZXJzPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSWYgdGhlIHdob2xlIGF1dGhvcml6ZXIgb2JqZWN0LCBpbmNsdWRpbmcgY3VzdG9tIGNvbnRleHQgdmFsdWVzIHNob3VsZCBiZSBpbiB0aGUgZXhlY3V0aW9uIGlucHV0LiBUaGUgZXhlY3V0aW9uIGlucHV0IHdpbGwgaW5jbHVkZSBhIG5ldyBrZXkgYGF1dGhvcml6ZXJgOlxuICAgKlxuICAgKiB7XG4gICAqICAgXCJib2R5XCI6IHt9LFxuICAgKiAgIFwiYXV0aG9yaXplclwiOiB7XG4gICAqICAgICBcImtleVwiOiBcInZhbHVlXCJcbiAgICogICB9XG4gICAqIH1cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGF1dGhvcml6ZXI/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgdG8gaW50ZWdyYXRlIHdpdGggdmFyaW91cyBTdGVwRnVuY3Rpb24gQVBJXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGVwRnVuY3Rpb25zSW50ZWdyYXRpb24ge1xuICAvKipcbiAgICogSW50ZWdyYXRlcyBhIFN5bmNocm9ub3VzIEV4cHJlc3MgU3RhdGUgTWFjaGluZSBmcm9tIEFXUyBTdGVwIEZ1bmN0aW9ucyB0byBhbiBBUEkgR2F0ZXdheSBtZXRob2QuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICAgIGNvbnN0IHN0YXRlTWFjaGluZSA9IG5ldyBzdGVwZnVuY3Rpb25zLlN0YXRlTWFjaGluZSh0aGlzLCAnTXlTdGF0ZU1hY2hpbmUnLCB7XG4gICAqICAgICAgIHN0YXRlTWFjaGluZVR5cGU6IHN0ZXBmdW5jdGlvbnMuU3RhdGVNYWNoaW5lVHlwZS5FWFBSRVNTLFxuICAgKiAgICAgICBkZWZpbml0aW9uOiBzdGVwZnVuY3Rpb25zLkNoYWluLnN0YXJ0KG5ldyBzdGVwZnVuY3Rpb25zLlBhc3ModGhpcywgJ1Bhc3MnKSksXG4gICAqICAgIH0pO1xuICAgKlxuICAgKiAgICBjb25zdCBhcGkgPSBuZXcgYXBpZ2F0ZXdheS5SZXN0QXBpKHRoaXMsICdBcGknLCB7XG4gICAqICAgICAgIHJlc3RBcGlOYW1lOiAnTXlBcGknLFxuICAgKiAgICB9KTtcbiAgICogICAgYXBpLnJvb3QuYWRkTWV0aG9kKCdHRVQnLCBhcGlnYXRld2F5LlN0ZXBGdW5jdGlvbnNJbnRlZ3JhdGlvbi5zdGFydEV4ZWN1dGlvbihzdGF0ZU1hY2hpbmUpKTtcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgc3RhcnRFeGVjdXRpb24oc3RhdGVNYWNoaW5lOiBzZm4uSVN0YXRlTWFjaGluZSwgb3B0aW9ucz86IFN0ZXBGdW5jdGlvbnNFeGVjdXRpb25JbnRlZ3JhdGlvbk9wdGlvbnMpOiBBd3NJbnRlZ3JhdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBTdGVwRnVuY3Rpb25zRXhlY3V0aW9uSW50ZWdyYXRpb24oc3RhdGVNYWNoaW5lLCBvcHRpb25zKTtcbiAgfVxufVxuXG5jbGFzcyBTdGVwRnVuY3Rpb25zRXhlY3V0aW9uSW50ZWdyYXRpb24gZXh0ZW5kcyBBd3NJbnRlZ3JhdGlvbiB7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RhdGVNYWNoaW5lOiBzZm4uSVN0YXRlTWFjaGluZTtcbiAgY29uc3RydWN0b3Ioc3RhdGVNYWNoaW5lOiBzZm4uSVN0YXRlTWFjaGluZSwgb3B0aW9uczogU3RlcEZ1bmN0aW9uc0V4ZWN1dGlvbkludGVncmF0aW9uT3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIoe1xuICAgICAgc2VydmljZTogJ3N0YXRlcycsXG4gICAgICBhY3Rpb246ICdTdGFydFN5bmNFeGVjdXRpb24nLFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICBjcmVkZW50aWFsc1JvbGU6IG9wdGlvbnMuY3JlZGVudGlhbHNSb2xlLFxuICAgICAgICBpbnRlZ3JhdGlvblJlc3BvbnNlczogaW50ZWdyYXRpb25SZXNwb25zZSgpLFxuICAgICAgICBwYXNzdGhyb3VnaEJlaGF2aW9yOiBQYXNzdGhyb3VnaEJlaGF2aW9yLk5FVkVSLFxuICAgICAgICByZXF1ZXN0VGVtcGxhdGVzOiByZXF1ZXN0VGVtcGxhdGVzKHN0YXRlTWFjaGluZSwgb3B0aW9ucyksXG4gICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy5zdGF0ZU1hY2hpbmUgPSBzdGF0ZU1hY2hpbmU7XG4gIH1cblxuICBwdWJsaWMgYmluZChtZXRob2Q6IE1ldGhvZCk6IEludGVncmF0aW9uQ29uZmlnIHtcbiAgICBjb25zdCBiaW5kUmVzdWx0ID0gc3VwZXIuYmluZChtZXRob2QpO1xuXG4gICAgY29uc3QgY3JlZGVudGlhbHNSb2xlID0gYmluZFJlc3VsdC5vcHRpb25zPy5jcmVkZW50aWFsc1JvbGUgPz8gbmV3IGlhbS5Sb2xlKG1ldGhvZCwgJ1N0YXJ0U3luY0V4ZWN1dGlvblJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnYXBpZ2F0ZXdheS5hbWF6b25hd3MuY29tJyksXG4gICAgfSk7XG4gICAgdGhpcy5zdGF0ZU1hY2hpbmUuZ3JhbnRTdGFydFN5bmNFeGVjdXRpb24oY3JlZGVudGlhbHNSb2xlKTtcblxuICAgIGxldCBzdGF0ZU1hY2hpbmVOYW1lO1xuXG4gICAgaWYgKHRoaXMuc3RhdGVNYWNoaW5lIGluc3RhbmNlb2Ygc2ZuLlN0YXRlTWFjaGluZSkge1xuICAgICAgY29uc3Qgc3RhdGVNYWNoaW5lVHlwZSA9ICh0aGlzLnN0YXRlTWFjaGluZSBhcyBzZm4uU3RhdGVNYWNoaW5lKS5zdGF0ZU1hY2hpbmVUeXBlO1xuICAgICAgaWYgKHN0YXRlTWFjaGluZVR5cGUgIT09IHNmbi5TdGF0ZU1hY2hpbmVUeXBlLkVYUFJFU1MpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTdGF0ZSBNYWNoaW5lIG11c3QgYmUgb2YgdHlwZSBcIkVYUFJFU1NcIi4gUGxlYXNlIHVzZSBTdGF0ZU1hY2hpbmVUeXBlLkVYUFJFU1MgYXMgdGhlIHN0YXRlTWFjaGluZVR5cGUnKTtcbiAgICAgIH1cblxuICAgICAgLy9pZiBub3QgaW1wb3J0ZWQsIGV4dHJhY3QgdGhlIG5hbWUgZnJvbSB0aGUgQ0ZOIGxheWVyIHRvIHJlYWNoIHRoZVxuICAgICAgLy9saXRlcmFsIHZhbHVlIGlmIGl0IGlzIGdpdmVuIChyYXRoZXIgdGhhbiBhIHRva2VuKVxuICAgICAgc3RhdGVNYWNoaW5lTmFtZSA9ICh0aGlzLnN0YXRlTWFjaGluZS5ub2RlLmRlZmF1bHRDaGlsZCBhcyBzZm4uQ2ZuU3RhdGVNYWNoaW5lKS5zdGF0ZU1hY2hpbmVOYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICAvL2ltcG9ydGVkIHN0YXRlIG1hY2hpbmVcbiAgICAgIHN0YXRlTWFjaGluZU5hbWUgPSBgU3RhdGVNYWNoaW5lLSR7dGhpcy5zdGF0ZU1hY2hpbmUuc3RhY2subm9kZS5hZGRyfWA7XG4gICAgfVxuXG4gICAgbGV0IGRlcGxveW1lbnRUb2tlbjtcblxuICAgIGlmIChzdGF0ZU1hY2hpbmVOYW1lICE9PSB1bmRlZmluZWQgJiYgIVRva2VuLmlzVW5yZXNvbHZlZChzdGF0ZU1hY2hpbmVOYW1lKSkge1xuICAgICAgZGVwbG95bWVudFRva2VuID0gSlNPTi5zdHJpbmdpZnkoeyBzdGF0ZU1hY2hpbmVOYW1lIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgbWV0aG9kUmVzcG9uc2Ugb2YgTUVUSE9EX1JFU1BPTlNFUykge1xuICAgICAgbWV0aG9kLmFkZE1ldGhvZFJlc3BvbnNlKG1ldGhvZFJlc3BvbnNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uYmluZFJlc3VsdCxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgLi4uYmluZFJlc3VsdC5vcHRpb25zLFxuICAgICAgICBjcmVkZW50aWFsc1JvbGUsXG4gICAgICB9LFxuICAgICAgZGVwbG95bWVudFRva2VuLFxuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBpbnRlZ3JhdGlvbiByZXNwb25zZSB0aGF0IHBhc3NlcyB0aGUgcmVzdWx0IG9uIHN1Y2Nlc3MsXG4gKiBvciB0aGUgZXJyb3Igb24gZmFpbHVyZSwgZnJvbSB0aGUgc3luY2hyb25vdXMgZXhlY3V0aW9uIHRvIHRoZSBjYWxsZXIuXG4gKlxuICogQHJldHVybnMgaW50ZWdyYXRpb25SZXNwb25zZSBtYXBwaW5nXG4gKi9cbmZ1bmN0aW9uIGludGVncmF0aW9uUmVzcG9uc2UoKSB7XG4gIGNvbnN0IGVycm9yUmVzcG9uc2UgPSBbXG4gICAge1xuICAgICAgLyoqXG4gICAgICAgKiBTcGVjaWZpZXMgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiAocmVnZXgpIHBhdHRlcm4gdXNlZCB0byBjaG9vc2VcbiAgICAgICAqIGFuIGludGVncmF0aW9uIHJlc3BvbnNlIGJhc2VkIG9uIHRoZSByZXNwb25zZSBmcm9tIHRoZSBiYWNrIGVuZC5cbiAgICAgICAqIEluIHRoaXMgY2FzZSBpdCB3aWxsIG1hdGNoIGFsbCAnNFhYJyBIVFRQIEVycm9yc1xuICAgICAgICovXG4gICAgICBzZWxlY3Rpb25QYXR0ZXJuOiAnNFxcXFxkezJ9JyxcbiAgICAgIHN0YXR1c0NvZGU6ICc0MDAnLFxuICAgICAgcmVzcG9uc2VUZW1wbGF0ZXM6IHtcbiAgICAgICAgJ2FwcGxpY2F0aW9uL2pzb24nOiBge1xuICAgICAgICAgICAgXCJlcnJvclwiOiBcIkJhZCByZXF1ZXN0IVwiXG4gICAgICAgICAgfWAsXG4gICAgICB9LFxuICAgIH0sXG4gICAge1xuICAgICAgLyoqXG4gICAgICAgKiBNYXRjaCBhbGwgJzVYWCcgSFRUUCBFcnJvcnNcbiAgICAgICAqL1xuICAgICAgc2VsZWN0aW9uUGF0dGVybjogJzVcXFxcZHsyfScsXG4gICAgICBzdGF0dXNDb2RlOiAnNTAwJyxcbiAgICAgIHJlc3BvbnNlVGVtcGxhdGVzOiB7XG4gICAgICAgICdhcHBsaWNhdGlvbi9qc29uJzogJ1wiZXJyb3JcIjogJGlucHV0LnBhdGgoXFwnJC5lcnJvclxcJyknLFxuICAgICAgfSxcbiAgICB9LFxuICBdO1xuXG4gIGNvbnN0IGludGVnUmVzcG9uc2UgPSBbXG4gICAge1xuICAgICAgc3RhdHVzQ29kZTogJzIwMCcsXG4gICAgICByZXNwb25zZVRlbXBsYXRlczoge1xuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSAqL1xuICAgICAgICAnYXBwbGljYXRpb24vanNvbic6IFtcbiAgICAgICAgICAnI3NldCgkaW5wdXRSb290ID0gJGlucHV0LnBhdGgoXFwnJFxcJykpJyxcbiAgICAgICAgICAnI2lmKCRpbnB1dC5wYXRoKFxcJyQuc3RhdHVzXFwnKS50b1N0cmluZygpLmVxdWFscyhcIkZBSUxFRFwiKSknLFxuICAgICAgICAgICAgJyNzZXQoJGNvbnRleHQucmVzcG9uc2VPdmVycmlkZS5zdGF0dXMgPSA1MDApJyxcbiAgICAgICAgICAgICd7JyxcbiAgICAgICAgICAgICAgJ1wiZXJyb3JcIjogXCIkaW5wdXQucGF0aChcXCckLmVycm9yXFwnKVwiLCcsXG4gICAgICAgICAgICAgICdcImNhdXNlXCI6IFwiJGlucHV0LnBhdGgoXFwnJC5jYXVzZVxcJylcIicsXG4gICAgICAgICAgICAnfScsXG4gICAgICAgICAgJyNlbHNlJyxcbiAgICAgICAgICAgICckaW5wdXQucGF0aChcXCckLm91dHB1dFxcJyknLFxuICAgICAgICAgICcjZW5kJyxcbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSAqL1xuICAgICAgICBdLmpvaW4oJ1xcbicpLFxuICAgICAgfSxcbiAgICB9LFxuICAgIC4uLmVycm9yUmVzcG9uc2UsXG4gIF07XG5cbiAgcmV0dXJuIGludGVnUmVzcG9uc2U7XG59XG5cbi8qKlxuICogRGVmaW5lcyB0aGUgcmVxdWVzdCB0ZW1wbGF0ZSB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgdGhlIGludGVncmF0aW9uXG4gKiBAcGFyYW0gc3RhdGVNYWNoaW5lXG4gKiBAcGFyYW0gb3B0aW9uc1xuICogQHJldHVybnMgcmVxdWVzdFRlbXBsYXRlXG4gKi9cbmZ1bmN0aW9uIHJlcXVlc3RUZW1wbGF0ZXMoc3RhdGVNYWNoaW5lOiBzZm4uSVN0YXRlTWFjaGluZSwgb3B0aW9uczogU3RlcEZ1bmN0aW9uc0V4ZWN1dGlvbkludGVncmF0aW9uT3B0aW9ucykge1xuICBjb25zdCB0ZW1wbGF0ZVN0ciA9IHRlbXBsYXRlU3RyaW5nKHN0YXRlTWFjaGluZSwgb3B0aW9ucyk7XG5cbiAgY29uc3QgcmVxdWVzdFRlbXBsYXRlOiB7IFtjb250ZW50VHlwZTpzdHJpbmddIDogc3RyaW5nIH0gPVxuICAgIHtcbiAgICAgICdhcHBsaWNhdGlvbi9qc29uJzogdGVtcGxhdGVTdHIsXG4gICAgfTtcblxuICByZXR1cm4gcmVxdWVzdFRlbXBsYXRlO1xufVxuXG4vKipcbiAqIFJlYWRzIHRoZSBWVEwgdGVtcGxhdGUgYW5kIHJldHVybnMgdGhlIHRlbXBsYXRlIHN0cmluZyB0byBiZSB1c2VkXG4gKiBmb3IgdGhlIHJlcXVlc3QgdGVtcGxhdGUuXG4gKlxuICogQHBhcmFtIHN0YXRlTWFjaGluZVxuICogQHBhcmFtIGluY2x1ZGVSZXF1ZXN0Q29udGV4dFxuICogQHBhcmFtIG9wdGlvbnNcbiAqIEByZXV0cm5zIHRlbXBsYXRlU3RyaW5nXG4gKi9cbmZ1bmN0aW9uIHRlbXBsYXRlU3RyaW5nKFxuICBzdGF0ZU1hY2hpbmU6IHNmbi5JU3RhdGVNYWNoaW5lLFxuICBvcHRpb25zOiBTdGVwRnVuY3Rpb25zRXhlY3V0aW9uSW50ZWdyYXRpb25PcHRpb25zKTogc3RyaW5nIHtcbiAgbGV0IHRlbXBsYXRlU3RyOiBzdHJpbmc7XG5cbiAgbGV0IHJlcXVlc3RDb250ZXh0U3RyID0gJyc7XG5cbiAgY29uc3QgaW5jbHVkZUhlYWRlciA9IG9wdGlvbnMuaGVhZGVycz8/IGZhbHNlO1xuICBjb25zdCBpbmNsdWRlUXVlcnlTdHJpbmcgPSBvcHRpb25zLnF1ZXJ5c3RyaW5nPz8gdHJ1ZTtcbiAgY29uc3QgaW5jbHVkZVBhdGggPSBvcHRpb25zLnBhdGg/PyB0cnVlO1xuICBjb25zdCBpbmNsdWRlQXV0aG9yaXplciA9IG9wdGlvbnMuYXV0aG9yaXplciA/PyBmYWxzZTtcblxuICBpZiAob3B0aW9ucy5yZXF1ZXN0Q29udGV4dCAmJiBPYmplY3Qua2V5cyhvcHRpb25zLnJlcXVlc3RDb250ZXh0KS5sZW5ndGggPiAwKSB7XG4gICAgcmVxdWVzdENvbnRleHRTdHIgPSByZXF1ZXN0Q29udGV4dChvcHRpb25zLnJlcXVlc3RDb250ZXh0KTtcbiAgfVxuXG4gIHRlbXBsYXRlU3RyID0gZnMucmVhZEZpbGVTeW5jKHBhdGguam9pbihfX2Rpcm5hbWUsICdzdGVwZnVuY3Rpb25zLnZ0bCcpLCB7IGVuY29kaW5nOiAndXRmLTgnIH0pO1xuICB0ZW1wbGF0ZVN0ciA9IHRlbXBsYXRlU3RyLnJlcGxhY2UoJyVTVEFURU1BQ0hJTkUlJywgc3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZUFybik7XG4gIHRlbXBsYXRlU3RyID0gdGVtcGxhdGVTdHIucmVwbGFjZSgnJUlOQ0xVREVfSEVBREVSUyUnLCBTdHJpbmcoaW5jbHVkZUhlYWRlcikpO1xuICB0ZW1wbGF0ZVN0ciA9IHRlbXBsYXRlU3RyLnJlcGxhY2UoJyVJTkNMVURFX1FVRVJZU1RSSU5HJScsIFN0cmluZyhpbmNsdWRlUXVlcnlTdHJpbmcpKTtcbiAgdGVtcGxhdGVTdHIgPSB0ZW1wbGF0ZVN0ci5yZXBsYWNlKCclSU5DTFVERV9QQVRIJScsIFN0cmluZyhpbmNsdWRlUGF0aCkpO1xuICB0ZW1wbGF0ZVN0ciA9IHRlbXBsYXRlU3RyLnJlcGxhY2UoJyVJTkNMVURFX0FVVEhPUklaRVIlJywgU3RyaW5nKGluY2x1ZGVBdXRob3JpemVyKSk7XG4gIHRlbXBsYXRlU3RyID0gdGVtcGxhdGVTdHIucmVwbGFjZSgnJVJFUVVFU1RDT05URVhUJScsIHJlcXVlc3RDb250ZXh0U3RyKTtcblxuICByZXR1cm4gdGVtcGxhdGVTdHI7XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RDb250ZXh0KHJlcXVlc3RDb250ZXh0T2JqOiBSZXF1ZXN0Q29udGV4dCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgYWNjb3VudElkOiByZXF1ZXN0Q29udGV4dE9iaj8uYWNjb3VudElkPyAnJGNvbnRleHQuaWRlbnRpdHkuYWNjb3VudElkJzogdW5kZWZpbmVkLFxuICAgIGFwaUlkOiByZXF1ZXN0Q29udGV4dE9iaj8uYXBpSWQ/ICckY29udGV4dC5hcGlJZCc6IHVuZGVmaW5lZCxcbiAgICBhcGlLZXk6IHJlcXVlc3RDb250ZXh0T2JqPy5hcGlLZXk/ICckY29udGV4dC5pZGVudGl0eS5hcGlLZXknOiB1bmRlZmluZWQsXG4gICAgYXV0aG9yaXplclByaW5jaXBhbElkOiByZXF1ZXN0Q29udGV4dE9iaj8uYXV0aG9yaXplclByaW5jaXBhbElkPyAnJGNvbnRleHQuYXV0aG9yaXplci5wcmluY2lwYWxJZCc6IHVuZGVmaW5lZCxcbiAgICBjYWxsZXI6IHJlcXVlc3RDb250ZXh0T2JqPy5jYWxsZXI/ICckY29udGV4dC5pZGVudGl0eS5jYWxsZXInOiB1bmRlZmluZWQsXG4gICAgY29nbml0b0F1dGhlbnRpY2F0aW9uUHJvdmlkZXI6IHJlcXVlc3RDb250ZXh0T2JqPy5jb2duaXRvQXV0aGVudGljYXRpb25Qcm92aWRlcj8gJyRjb250ZXh0LmlkZW50aXR5LmNvZ25pdG9BdXRoZW50aWNhdGlvblByb3ZpZGVyJzogdW5kZWZpbmVkLFxuICAgIGNvZ25pdG9BdXRoZW50aWNhdGlvblR5cGU6IHJlcXVlc3RDb250ZXh0T2JqPy5jb2duaXRvQXV0aGVudGljYXRpb25UeXBlPyAnJGNvbnRleHQuaWRlbnRpdHkuY29nbml0b0F1dGhlbnRpY2F0aW9uVHlwZSc6IHVuZGVmaW5lZCxcbiAgICBjb2duaXRvSWRlbnRpdHlJZDogcmVxdWVzdENvbnRleHRPYmo/LmNvZ25pdG9JZGVudGl0eUlkPyAnJGNvbnRleHQuaWRlbnRpdHkuY29nbml0b0lkZW50aXR5SWQnOiB1bmRlZmluZWQsXG4gICAgY29nbml0b0lkZW50aXR5UG9vbElkOiByZXF1ZXN0Q29udGV4dE9iaj8uY29nbml0b0lkZW50aXR5UG9vbElkPyAnJGNvbnRleHQuaWRlbnRpdHkuY29nbml0b0lkZW50aXR5UG9vbElkJzogdW5kZWZpbmVkLFxuICAgIGh0dHBNZXRob2Q6IHJlcXVlc3RDb250ZXh0T2JqPy5odHRwTWV0aG9kPyAnJGNvbnRleHQuaHR0cE1ldGhvZCc6IHVuZGVmaW5lZCxcbiAgICBzdGFnZTogcmVxdWVzdENvbnRleHRPYmo/LnN0YWdlPyAnJGNvbnRleHQuc3RhZ2UnOiB1bmRlZmluZWQsXG4gICAgc291cmNlSXA6IHJlcXVlc3RDb250ZXh0T2JqPy5zb3VyY2VJcD8gJyRjb250ZXh0LmlkZW50aXR5LnNvdXJjZUlwJzogdW5kZWZpbmVkLFxuICAgIHVzZXI6IHJlcXVlc3RDb250ZXh0T2JqPy51c2VyPyAnJGNvbnRleHQuaWRlbnRpdHkudXNlcic6IHVuZGVmaW5lZCxcbiAgICB1c2VyQWdlbnQ6IHJlcXVlc3RDb250ZXh0T2JqPy51c2VyQWdlbnQ/ICckY29udGV4dC5pZGVudGl0eS51c2VyQWdlbnQnOiB1bmRlZmluZWQsXG4gICAgdXNlckFybjogcmVxdWVzdENvbnRleHRPYmo/LnVzZXJBcm4/ICckY29udGV4dC5pZGVudGl0eS51c2VyQXJuJzogdW5kZWZpbmVkLFxuICAgIHJlcXVlc3RJZDogcmVxdWVzdENvbnRleHRPYmo/LnJlcXVlc3RJZD8gJyRjb250ZXh0LnJlcXVlc3RJZCc6IHVuZGVmaW5lZCxcbiAgICByZXNvdXJjZUlkOiByZXF1ZXN0Q29udGV4dE9iaj8ucmVzb3VyY2VJZD8gJyRjb250ZXh0LnJlc291cmNlSWQnOiB1bmRlZmluZWQsXG4gICAgcmVzb3VyY2VQYXRoOiByZXF1ZXN0Q29udGV4dE9iaj8ucmVzb3VyY2VQYXRoPyAnJGNvbnRleHQucmVzb3VyY2VQYXRoJzogdW5kZWZpbmVkLFxuICB9O1xuXG4gIGNvbnN0IGNvbnRleHRBc1N0cmluZyA9IEpTT04uc3RyaW5naWZ5KGNvbnRleHQpO1xuXG4gIC8vIFRoZSBWVEwgVGVtcGxhdGUgY29uZmxpY3RzIHdpdGggZG91YmxlLXF1b3RlcyAoXCIpIGZvciBzdHJpbmdzLlxuICAvLyBCZWZvcmUgc2VuZGluZyB0byB0aGUgdGVtcGxhdGUsIHdlIHJlcGxhY2UgZG91YmxlLXF1b3RlcyAoXCIpIHdpdGggQEAgYW5kIHJlcGxhY2UgaXQgYmFjayBpbnNpZGUgdGhlIC52dGwgZmlsZVxuICBjb25zdCBkb3VibGVxdW90ZXMgPSAnXCInO1xuICBjb25zdCByZXBsYWNlV2l0aCA9ICdAQCc7XG4gIHJldHVybiBjb250ZXh0QXNTdHJpbmcuc3BsaXQoZG91YmxlcXVvdGVzKS5qb2luKHJlcGxhY2VXaXRoKTtcbn1cblxuLyoqXG4gKiBNZXRob2QgcmVzcG9uc2UgbW9kZWwgZm9yIGVhY2ggSFRUUCBjb2RlIHJlc3BvbnNlXG4gKi9cbmNvbnN0IE1FVEhPRF9SRVNQT05TRVMgPSBbXG4gIHtcbiAgICBzdGF0dXNDb2RlOiAnMjAwJyxcbiAgICByZXNwb25zZU1vZGVsczoge1xuICAgICAgJ2FwcGxpY2F0aW9uL2pzb24nOiBNb2RlbC5FTVBUWV9NT0RFTCxcbiAgICB9LFxuICB9LFxuICB7XG4gICAgc3RhdHVzQ29kZTogJzQwMCcsXG4gICAgcmVzcG9uc2VNb2RlbHM6IHtcbiAgICAgICdhcHBsaWNhdGlvbi9qc29uJzogTW9kZWwuRVJST1JfTU9ERUwsXG4gICAgfSxcbiAgfSxcbiAge1xuICAgIHN0YXR1c0NvZGU6ICc1MDAnLFxuICAgIHJlc3BvbnNlTW9kZWxzOiB7XG4gICAgICAnYXBwbGljYXRpb24vanNvbic6IE1vZGVsLkVSUk9SX01PREVMLFxuICAgIH0sXG4gIH0sXG5dO1xuIl19
\No newline at end of file